[英]Git - remote: fatal: You are on a branch yet to be born
Im trying to setup a hook to push from my desktop to my server.我试图设置一个钩子从我的桌面推送到我的服务器。 This has worked countless times in the past but now I'm getting an error upon setting up a new site:
这在过去已经成功过无数次,但现在我在设置新站点时遇到错误:
remote: fatal: You are on a branch yet to be born
I've done the same series as commands as always, as per this guide .根据本指南,我一如既往地完成了与命令相同的系列。
So on my server I make a git dir.所以在我的服务器上我创建了一个 git 目录。 For instance example.git
例如example.git
I then run git init --bare
.然后我运行
git init --bare
。 After which I go to my hooks:之后我去我的钩子:
cd hooks/
cat > post-receive
Inside my post-receive I place:在我的 post-receive 里面,我放置:
#!/bin/sh
git --work-tree=/home/username/public_html/example.com --git-dir=/home/username/example.git checkout -f
I Ctrl + D out to save.我Ctrl+D出来保存。 Then run
chmod +x post-receive
然后运行
chmod +x post-receive
Then locally I run: git remote add live ssh://username@domain.com:x/home/username/example.git
然后在本地运行:
git remote add live ssh://username@domain.com:x/home/username/example.git
Then I can run: git push -u live master_prefix
然后我可以运行:
git push -u live master_prefix
The only thing I'm doing different is I'm within a branch called master_something, rather than master.我做的唯一不同的是我在一个名为 master_something 的分支中,而不是 master。 Would this be causing the issue and if so, what do I need to do?
这是否会导致问题,如果是,我需要做什么?
Edit, September 2020 : This is becoming more common because people are renaming existing master
branches to main
or similar in various server-side bare repositories.编辑,2020 年 9 月:这变得越来越普遍,因为人们正在各种服务器端裸存储库中将现有的
master
分支重命名为main
或类似的。 For a TL;DR, if you've done this in a server-side bare repository—or made a repository with git init --bare
without also updating the initial master
part—you will want to adjust the HEAD
setting in this bare repository.对于 TL;DR,如果您已经在服务器端裸仓库中完成了此操作——或者使用
git init --bare
创建了一个仓库而没有同时更新初始master
部件——您将需要在这个裸仓库中调整HEAD
设置. Jump down to the So what to do?跳到下面那该怎么办? section for instructions.
部分的说明。
It is, as you suspected, because you're pushing a branch named master_prefix
rather than master.正如您所怀疑的那样,这是因为您正在推送名为
master_prefix
而不是 master 的分支。 As for what to do, well, that depends on what you want to happen.至于做什么,那取决于你想要发生什么。 Skip to the end if you want to see several options.
如果您想查看多个选项,请跳到最后。
First, though, let's break this down a bit.不过,首先,让我们把它分解一下。
Any message that begins with:任何以以下开头的消息:
remote: ...
is actually coming from the "other guy".实际上来自“另一个人”。 When you do a push (or fetch, for that matter), your Git calls up another Git over the Internet-phone or equivalent.
当您执行推送(或获取,就此而言)时,您的 Git 会通过互联网电话或等效方式调用另一个 Git。 They exchange information using a protocol that helps them identify when they're talking to each other directly, and when your Git is getting stuff from their end that's not from their Git , but rather from something their Git is using.
他们使用一种协议交换信息,该协议可帮助他们识别何时直接相互交谈,以及何时您的 Git 从他们的一端获取的东西不是来自他们的Git ,而是来自他们的 Git 正在使用的东西。
In this case, their Git (on the server) is running their Git's hooks.在这种情况下,他们的 Git(在服务器上)正在运行他们的 Git 钩子。 There's just the one hook—you created it, so we could call it "your" hook, but your computer running your Git has no idea that the stuff on the server is authored by you: it doesn't know, doesn't need to know, and doesn't care;
只有一个钩子——你创建了它,所以我们可以称它为“你的”钩子,但是你运行 Git 的计算机不知道服务器上的东西是你创作的:它不知道,不需要知道,并且不在乎; it just delivers messages.
它只是传递消息。 So we'll call it "their" hook.
所以我们称它为“他们的”钩子。
Their hook says:他们的钩子说:
fatal: You are on a branch yet to be born
and you see it on your end prefixed with remote:
to let you know it's not your Git that's saying things, it's something on their end.你会在你的一端看到它以
remote:
为前缀remote:
让你知道不是你的Git 在说事情,而是他们的事情。
At this point, the best thing to do is to change perspectives, by pretending "you" are now the server.在这一点上,最好的办法是改变观点,假装“你”现在是服务器。 On "your" end, your Git fires up and receives stuff (successfully, and puts in the requested branch,
master_prefix
), then runs the one hook.在“你的”端,你的 Git 启动并接收东西(成功,并放入请求的分支
master_prefix
),然后运行一个钩子。 That hook fires up another, separate, git checkout
command:该钩子会启动另一个单独的
git checkout
命令:
git --work-tree=/home/username/public_html/example.com --git-dir=/home/username/example.git checkout -f
This is pretty long so let's shorten it by ignoring the options for a moment.这很长,所以让我们暂时忽略选项来缩短它。 Aside from setting the work and git directories, it's just
git checkout -f
.除了设置 work 和 git 目录之外,它只是
git checkout -f
。
If you ran this command by itself somewhere else, what branch will it check out?如果您在其他地方单独运行此命令,它将检查哪个分支? This isn't a rhetorical question, and the answer is in the documentation , although it may be unclear and even misleading:
这不是一个修辞问题,答案在文档中,尽管它可能不清楚甚至具有误导性:
You could omit
branch
, in which case the command degenerates to "check out the current branch", which is a glorified no-op with a rather expensive side-effects to show only the tracking information, if exists, for the current branch.您可以省略
branch
,在这种情况下,命令退化为“检查当前分支”,这是一个美化的无操作,具有相当昂贵的副作用,仅显示当前分支的跟踪信息(如果存在)。
Because of the --work-dir
and --git-dir
options and the fact that the (bare) repository might be changed, it's not "a glorified no-op" after all, but it does use:由于
--work-dir
和--git-dir
选项以及(裸)存储库可能会更改的事实,它毕竟不是“美化的无操作”,但它确实使用:
the current branch
当前分支
That's the key, right there: the current branch .这就是关键,就在那里:当前分支。 What is the "current branch" of this bare repository?
这个裸存储库的“当前分支”是什么?
The answer is the same as for any repo (bare or not): the current branch is the one named in the HEAD
file.答案与任何 repo(裸或非裸)相同:当前分支是在
HEAD
文件中命名的分支。 If you poke around in this bare repository, you'll find that file;如果你在这个裸存储库中浏览,你会找到那个文件; examine it and it will say:
检查它,它会说:
$ cat HEAD
ref: refs/heads/master
$
In other words, HEAD
names the current branch, which—since the git init
set it that way and nothing since then has changed it—is master
.换句话说,
HEAD
将当前分支命名为master
,因为git init
这种方式设置它并且此后没有任何更改它。
So your git checkout -f
command is attempting to check out branch master
.所以你的
git checkout -f
命令试图检查分支master
。
What branches actually exist?实际存在哪些分支? You can find out, by going into the bare repository and running
git branch
:您可以通过进入裸存储库并运行
git branch
:
$ git branch
master_prefix
$
I got this with git version 2.3.0
: note that there's no * master
output.我在
git version 2.3.0
得到了这个:请注意,没有* master
输出。 Other (future, really) versions of Git might show you * master
since that is the branch you're on—even though it does not exist yet!其他(未来,真的)Git 版本可能会向您显示
* master
因为这是您所在的分支——即使它还不存在!
What's going on?这是怎么回事? The answer is that any time you create a new branch that's not connected to any existing revision—which is always true for the
master
branch in a newly created repository—Git handles this by writing the branch name into HEAD
, but not writing any revision ID into the appropriate file(s) for that branch.答案是,每当您创建一个未连接到任何现有修订的新分支时(对于新创建的存储库中的
master
分支总是如此),Git 会通过将分支名称写入HEAD
处理此问题,但不写入任何修订 ID到该分支的适当文件中。 This is how Git records the idea that the named branch has not yet been created, but will be once you provide the first commit(s) for that branch.这就是 Git 记录命名分支尚未创建的想法的方式,但是一旦您为该分支提供了第一个提交。
(If you use git checkout -b newbranch --orphan
you get in this same "yet to be born" state for the new branch. It's most common for master
of course, since that's how any brand-new, empty repository starts out.) (如果您使用
git checkout -b newbranch --orphan
您会在新分支的“尚未出生”状态中获得相同的状态。当然,这对于master
是最常见的,因为这就是任何全新的空存储库开始的方式。 )
As I noted before, this really depends on what you want to have happen.正如我之前提到的,这实际上取决于您希望发生什么。
You have a new (initially empty) bare repository with no master
branch (but a post-receive hook that tries to export the current branch, which is still master
).您有一个新的(最初为空的)裸仓库,没有
master
分支(但是有一个 post-receive 钩子,它试图导出当前分支,它仍然是master
)。 Then you supply, from another system, a new branch, but it's not master
.然后你从另一个系统提供一个新的分支,但它不是
master
。 I see two obvious possible "want"s although perhaps you want something fancier than either of these:我看到了两个明显可能的“想要”,尽管你可能想要比这两个更高级的东西:
You want to export nothing since there's no master
to export: modify your hook to check whether the current branch exists:您不想导出任何内容,因为没有要导出的
master
:修改您的钩子以检查当前分支是否存在:
current_branch=$(git symbolic-ref HEAD) || exit 1 sha1=$(git rev-parse -q --verify $current_branch) || exit 0 # ok, the current branch exists; deploy it as usual git --work-tree=... --git-dir=... checkout -f
You want to export something other than the current ( master
) branch.您想导出当前 (
master
) 分支以外的内容。 Decide whether that means "forever" or "until master
appears" or whatever;决定这是否意味着“永远”或“直到
master
出现”或其他什么; modify your deployment script if needed or desired, or just change Git's idea of the current-branch.如果需要或需要,修改你的部署脚本,或者只是改变 Git 对当前分支的想法。
Let's say you want master_prefix
deployed now and forever.假设您希望现在和永远部署
master_prefix
。 Normally, you'd switch the bare repo to master_prefix
with a simple git checkout
, but you can't because (1) it's a --bare
repo and (2) there is no master_prefix
yet (unless you're doing this post-push as a fixup step).通常,您可以使用简单的
git checkout
将裸master_prefix
切换到master_prefix
,但您不能这样做,因为 (1) 它是一个--bare
repo 并且 (2) 还没有master_prefix
(除非您正在执行此帖子- push 作为修复步骤)。
There are two easy ways, on the server, to update its own idea of the current branch, even if the new one does not yet exist:在服务器上有两种简单的方法来更新它自己对当前分支的想法,即使新的想法还不存在:
$ echo ref: refs/heads/master_prefix > HEAD
does the trick by (c)rudely bypassing Git entirely, or:通过 (c) 粗鲁地完全绕过 Git 来解决问题,或者:
$ git symbolic-ref HEAD refs/heads/master_prefix
does the same thing using Git.使用 Git 做同样的事情。
Alternatively, you can specify the precise branch that the post-receive script should check out:或者,您可以指定接收后脚本应检出的精确分支:
$ git --work-tree=... --git-dir=... checkout -f master_prefix
Note that this will cause Git to change the current branch (in the bare repository) to master_prefix
on each push.请注意,这将导致 Git 在每次推送时将当前分支(在裸存储库中)更改为
master_prefix
。
Since your hook does not look at which branch(es) have been updated if any, there's no way to tell which branch(es) to deploy, other than to use whatever is the default (in HEAD
) or explicitly deploy a particular branch (add an argument).由于您的钩子不会查看哪个分支已更新(如果有),因此无法确定要部署哪个分支,除了使用默认值(在
HEAD
)或显式部署特定分支(添加一个参数)。
It's also worth noting a subtle tricky bit: the index
file in the bare repository will record what's been checked-out to the specified work-tree.还值得注意的是一个微妙的技巧:裸存储库中的
index
文件将记录已检出到指定工作树的内容。 As long as you have a single deployment location and/or a single branch deployed, this will be fine.只要您有一个部署位置和/或部署了一个分支,就可以了。 If you start getting fancy (eg, deploying
master
to the regular server, but test
to a test service on the same server), you may want to modify the deployment script, either to clean out and rebuild the target or to use multiple index files.如果您开始喜欢上(例如,将
master
部署到常规服务器,但test
到同一服务器上的测试服务),您可能需要修改部署脚本,以清除并重建目标或使用多个索引文件.
Most of the above doesn't matter until you start getting fancy.直到你开始变得花哨之前,上面的大部分内容都无关紧要。 The main thing is that you must decide what you want deployed, and maybe create a
master
branch.最重要的是你必须决定你想要部署什么,并且可能创建一个
master
分支。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.