Git - 远程:致命:你还在分支机构尚未出生

Doi*_*gey 19 git ssh github

我试图设置一个钩子从我的桌面推送到我的服务器.这在过去已经无数次,但现在我在设置新网站时遇到错误:

remote: fatal: You are on a branch yet to be born
Run Code Online (Sandbox Code Playgroud)

根据本指南,我和往常一样完成了与命令相同的系列.

所以在我的服务器上我做了一个git目录.例如example.git

然后我跑了git init --bare.之后我去了我的钩子:

cd hooks/
cat > post-receive
Run Code Online (Sandbox Code Playgroud)

在我的收到后我放置:

#!/bin/sh
git --work-tree=/home/username/public_html/example.com --git-dir=/home/username/example.git checkout -f
Run Code Online (Sandbox Code Playgroud)

我按Ctrl + D保存.然后跑chmod +x post-receive

然后我在本地运行: git remote add live ssh://username@domain.com:x/home/username/example.git

然后我可以运行: git push -u live master_prefix

我唯一不同的是我在一个名为master_something的分支中,而不是master.这会导致问题,如果是,我需要做什么?

tor*_*rek 35

正如你所怀疑的那样,因为你正在推动一个名为master_prefix而不是主人的分支.至于做什么,那取决于你想要发生什么.如果要查看多个选项,请跳至最后.

首先,让我们稍微打破一下.

任何以:

remote: ...
Run Code Online (Sandbox Code Playgroud)

实际上是来自"其他人".当你进行推送(或获取,就此而言)时,你的git通过互联网电话或同等机构调用另一个git.他们使用一种协议来交换信息,这些协议可以帮助他们识别他们何时直接交谈,以及当你的git从他们的端口获取的东西不是来自他们的git,而是来自他们的git正在使用的东西.

在这种情况下,他们的git(在服务器上)运行他们的git的钩子.只有一个钩子 - 你创建了它,所以我们可以称之为"你的"钩子,但运行你的git的计算机不知道服务器上的东西是由你创作的:它不知道,不需要要知道,也不在乎; 它只是传递信息.所以我们称之为"他们的"钩子.

他们的钩子说:

fatal: You are on a branch yet to be born
Run Code Online (Sandbox Code Playgroud)

并且你看到它在你的头上以前缀为止remote:让你知道这不是你的 git说的东西,这是他们的结果.


在这一点上,最好的办法是改变观点,假装"你"现在是服务器.在"你的"结束时,你的git会激活并接收内容(成功并放入请求的分支中master_prefix),然后运行一个钩子.那个钩子启动另一个单独的git命令:

git --work-tree=/home/username/public_html/example.com --git-dir=/home/username/example.git checkout -f
Run Code Online (Sandbox Code Playgroud)

这很长,所以让我们暂时忽略这些选项来缩短它.除了设置工作和git目录,它只是git checkout -f.

如果您在其他地方单独运行此命令,它将检查哪个分支?这不是一个修辞问题,答案在文档中,尽管可能不清楚甚至误导:

您可以省略branch,在这种情况下,命令退化为"检出当前分支",这是一个带有相当昂贵的副作用的美化无操作,仅显示当前分支的跟踪信息(如果存在).

由于这些--work-dir--git-dir选项以及(裸)存储库可能被更改的事实,它毕竟不是"光荣的无操作",但它确实使用:

目前的分支

那是关键,就在那里:现在的分支.这个裸存储库的"当前分支"是什么?

答案与任何repo(裸或不)相同:当前分支是HEAD文件中命名的分支.如果你在这个裸存储库中搜索,你会找到该文件; 检查它,它会说:

$ cat HEAD
ref: refs/heads/master
$ 
Run Code Online (Sandbox Code Playgroud)

换句话说,HEAD命名当前分支,因为它git init设置了那个方式,从那以后没有改变它 - 是master.

所以你的git checkout -f命令正试图检查分支master.

实际存在哪些分支?你可以通过进入裸存储库并运行来找到git branch:

$ git branch
  master_prefix
$ 
Run Code Online (Sandbox Code Playgroud)

我得到了这个git version 2.3.0:请注意,没有* master输出.其他(未来,真正的)git版本可能会告诉你,* master因为那是你所在的分支 - 即使它还不存在!

这是怎么回事?答案是,每当你创建一个没有连接到任何现有版本master的新分支时 - 对于新创建的存储库中的分支总是如此- git通过将分支名称写入HEAD,但不将任何修订ID写入该分支的适当文件.这就是git如何记录尚未创建命名分支的想法,但是一旦你为该分支提供了第一个提交.

(如果你使用git checkout -b newbranch --orphan你进入新分支的同样"尚未出生"的状态.master当然,这是最常见的,因为这是任何全新的,空的存储库的开始.)


那么该怎么办?

正如我之前提到的,这实际上取决于你想要发生什么.

你有一个新的(最初是空的)裸存储库没有master分支(但是一个试图导出当前分支的后接收挂钩,它仍然是master).然后你从另一个系统提供一个新的分支,但事实并非如此master.我看到两个明显可能的"想要",尽管你可能想要比这些更好的东西:

  1. 你想要导出什么,因为没有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
    
    Run Code Online (Sandbox Code Playgroud)
  2. 您想要导出除current(master)分支之外的其他内容.决定这是"永远"还是"直到master出现"或其他什么; 如果需要或需要修改您的部署脚本,或者只是更改git对当前分支的想法.

    假设你想要master_prefix现在和永远部署.通常情况下,你可以master_prefix用一个简单的方式切换裸仓库git checkout,但你不能因为(1)它是一个--bare仓库而且(2)还没有master_prefix(除非你做这个后推作为修复步骤).

    在服务器上,有两种简单的方法可以更新自己对当前分支的想法,即使新的分支尚不存在:

    $ echo ref: refs/heads/master_prefix > HEAD
    
    Run Code Online (Sandbox Code Playgroud)

    通过(c)粗暴地完全绕过git,或者:

    $ git symbolic-ref HEAD refs/heads/master_prefix
    
    Run Code Online (Sandbox Code Playgroud)

    用git做同样的事情.

    或者,您可以指定接收后脚本应检出的精确分支:

    $ git --work-tree=... --git-dir=... checkout -f master_prefix
    
    Run Code Online (Sandbox Code Playgroud)

    请注意,这将导致git master_prefix在每次推送时将当前分支(在裸存储库中)更改为.

    由于你的钩子没有查看哪个分支已被更新(如果有的话),除了使用默认(in HEAD)或显式部署特定分支之外,没有办法分辨哪个分支(添加)一个论点).

    值得注意的是一个微妙的技巧:index裸存储库中的文件将记录已检出的指定工作树.只要您部署了单个部署位置和/或单个分支,就可以了.如果您开始喜欢(例如,部署master到常规服务器,而是部署到test同一服务器上的测试服务),您可能需要修改部署脚本,以清理和重建目标或使用多个索引文件.

除非您开始喜欢,否则上述大部分内容都无关紧要.主要的是你必须决定你想要部署什么,并可能创建一个master分支.

  • 长话短说,我只需要“checkout -f {MyActualBranch}”..欢呼伙伴:) (6认同)