我在Web服务器上使用了一个简单的git repo,使用post-receive hook来自动检查对网站的更改。这一直很有效。
然而,一位同事最近克隆了裸仓(git clone <ssh url>
),对其本地仓库进行了一些更改,提交了它们,然后将更改推回(git push origin master
)。我不确定这个过程是否是导致问题的原因,但是自推送以来,后接收挂钩不再有效。它输出失败:
fatal: You are on a branch yet to be born
这是钩子:
#!/bin/bash
GIT_WORK_TREE=/home/marweldc/app git checkout -f
我可以将我的同事从遥控器所做的更改拉到我的本地实例。在服务器上的裸仓库中运行git branch
显示* master
,git log
显示所有更改,包括我的同事,因此远程仓库显然可以正常跟踪。< / p>
但是,如果我这样做,例如,GIT_WORK_TREE=/home/marweldc/app git status
我得到以下输出:
# Not currently on any branch.
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# ../CONTRIBUTING.md
# ../README.inno.txt
# <all the other files and folders that should be in the repo>
nothing added to commit but untracked files present (use "git add" to track)
我也尝试过运行GIT_WORK_TREE=/home/marweldc/app git checkout -f master
,产生:
error: pathspec '.git/master' did not match any file(s) known to git.
我们很难过。什么改变导致我们的钩子在它之前正常工作时以这种方式失败?
修改
我尝试过的一些事情在下面发表评论:
cat HEAD
会产生ref: refs/heads/master
GIT_TRACE=1 git rev-parse master
trace: built-in: git 'rev-parse' 'master'
f6462b06f75d126ab932e3cfccef7385da2805ba
但是设置了--work-tree
选项的相同命令会产生
trace: built-in: git 'rev-parse' 'master'
master
fatal: ambiguous argument 'master': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
GIT_WORK_TREE=/home/marweldc/app-new git checkout -f
(一个新的目录来结帐)可以正常使用答案 0 :(得分:1)
编辑:这里有一些非常具体的(可能是CentOS特定的)问题,在这里使用的旧Git版本1.7.1中有单独的Git和工作树目录,这样对于这个特定情况, --work-tree=/home/marweldc/app
导致Git无法在Git目录和工作树之间来回传递。 (其他工作树路径不会导致问题。)
Git没有注意到自己无法回到裸存储库,然后无法对分支名称做任何事情(因为它无法返回到存储库,它可能会在所有内容中失败此时)。
更现代的Git可能首先没有bug,或者会注意到在工作树和裸存储库之间来回切换失败。
同时,指定--git-dir=<path>
似乎解决了这个问题。
原始(一般)答案如下。
此:
fatal: You are on a branch yet to be born
意味着它所说的,尽管它说的可能令人困惑。 :-)你真的是&#34; on&#34;一些尚不存在的分支。
(目前还不清楚 - 你可能有一个&#34;分离的HEAD&#34;,就像Git所说的那样 - 但它看起来好像你不再拥有一个master
分支,如果你曾经做过的话。)
使用git branch
查看您现在所在的分支机构以及您可以使用的分支机构。使用git symbolic-ref HEAD refs/heads/master
强制将裸存储库HEAD
设置回master
分支。对于名为 B 的其他分支,请使用refs/heads/B
。
长篇答案,即接下来发生的事情。
在任何普通的非裸存储库中,您可以通过运行git status
来查看您所在的分支。但git status
查看工作树,因此在 bare 存储库中,git status
拒绝运行:没有工作树。
查看您所在分支的另一种方法是运行git branch
:
$ git branch
diff-merge-base
* master
stash-exp
这适用于裸存储库和非裸存储库。 *
以当前分支的名称命名。
答案 1 是:git checkout
。例如,git checkout master
会将您(或我)放在master
上,git checkout stash-exp
会将您(或我)放在stash-exp
上。
1 还有另一种方法,使用管道命令,但你通常不想使用它,因为它可能会弄乱当前的差异提交,索引和工作树。但是由于裸存储库没有工作树,所以这变得......好吧,#34;安全&#34;太强大,但我们可以说&#34;更不那么危险&#34;。
答案是仍然 git checkout
。
当您在裸存储库中签出分支时,它会使用和更改当前分支,其方式与在非裸存储库中签出分支时完全相同。 < / p>
当然,您不能 git checkout
裸存储库中的分支,因为它会更新工作树。当您使用git --work-tree=... checkout ...
时,可以除外。您提供要签出的分支的名称,并且像往常一样将新分支名称写入HEAD
。如果您通过哈希ID签出提交,那么分离{ {1}}像往常一样。
但还有一个特殊情况:如果您将HEAD
设置为尚不存在的分支的名称(就像使用HEAD
一样例如),将名称放入git checkout --orphan
而不创建分支。这在普通(非裸)存储库中是正常的,除了你只在两种情况下看到它:
首次创建新的空存储库时。您已HEAD
,但master
尚不存在。您可以通过在存储库中放置提交来解决此问题,该提交将转到master
,从而创建master
。 (新提交是 root 提交,即没有父提交。)
当您使用master
时:通过将分支的名称写入{{1},这与您在新的空存储库中设置时的方式相同像往常一样,但没有创建分支。您可以通过编写一个新的提交来解决这种情况,该提交将进入未出生的分支,该分支将创建分支,该分支现在已经生成(存在,指向您刚刚创建的新根提交。)
显然,你不能在裸存储库中以通常的方式执行此操作,因为通常的方法是使用工作树,git checkout --orphan
事物到索引中,{{1} }。裸存储库没有工作树。 (它仍然有索引和HEAD
,您可以在提供工作树git add
时执行此操作,仍然可以通过写入因为他们不了解索引,所以这对于许多人的接收后部署挂钩有点棘手和混乱。)
您可以所做的一切,并且在裸存储库中一直这样做是接收git commit
es。当您收到推送时,您接受来自另一个Git形式的请求(或命令):
git checkout
分支设置为提交--work-tree
git push
(由您决定是否以及如何在master
或1234567
挂钩中检查这些请求。如果您没有做任何特别的事情,那么您可以获得Git&#39; s默认的内置检查,允许任何人创建或删除任何分支或标记,但只允许快速推送分支。)
例如,假设您在裸存储库中的分支testing
上,而分支pre-receive
尚不存在。然后,Interwebs上的某个人连接到你的服务器并说:&#34;嘿,你,裸Git存储库,在这里有一些提交,现在创建分支update
指向提交master
&#34!;在这种情况下,假设您接受此请求/命令,一旦您的Git完成为他们提供服务,您做现在有一个master
。这将带你从:
master
为:
1234567
因为您之前不存在的当前分支master
,确实现在存在。
fatal: You are on a branch yet to be born
和On branch master
管道命令旨在用于脚本。他们假设您确切知道自己在做什么。 (如果你在不知道自己在做什么的情况下使用它们,你就会弄得一团糟:它们没有内置的安全检查。)其中第二个特别是Git如何在内部设置master
来选择你的哪个分支&#34; on&#34;。
如果你跑:
git update-ref
这会将git symbolic-ref
写入HEAD
,您现在是git symbolic-ref HEAD refs/heads/branch
。它没有更新索引并且它没有更新工作树 - 但是在裸存储库中,没有工作树,并且接收推送不会更新索引,所以这与收到推送时发生的情况非常相似。
因此,这是一个相当安全的事情。它允许您更改所在的分支,而无需使用ref: refs/heads/branch
。这是正常的和正确的,尽管很谨慎 - 确保正确拼写分支名称,并包含HEAD
前缀方式以在裸存储库中设置On branch branch
。