1

今天我在做我的一个项目,我意识到 git 有点奇怪。Git 将允许您将工作提交到幽灵分支。我使用术语ghost branch是因为更改存在于树中的某处但会回避git log --graph --decorate --oneline --all。谁能向我解释这是为什么?

重现此行为的步骤

进入分离的头部状态(你可以通过执行到达那里git checkout <hash>)。

# Not currently on any branch.
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   uml 1.pdf

对您的代码库进行一些更改。并使用 . 检查工作目录的状态git status。这应该列出更改,但声明您不在任何分支上。

# Not currently on any branch.
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   .gitignore
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   uml 1.pdf

使用提交更改git commit -am '<message>'

[detached HEAD ded7725] updated .gitignore
 1 files changed, 8 insertions(+), 1 deletions(-)

如果您随后签出一个已知的分支,例如“master”,那么在 detached head 状态下提交的所有更改都将消失。这是意料之中的。

Runniggit log --graph --decorate --oneline --all将显示所有提交,除了分离头上提交的提交(ded7725在我的情况下)。

但是, agit checkout <hash-for-ghost-branch>返回提交到 ghost 分支的更改。问题是:人们无法永远记住这个哈希值。

预期的行为将是这个幽灵分支将在一个有点悬垂的叶子上记录图表。但它不存在。任何关于为什么会发生这种情况的解释都值得赞赏。或者也许我错过了一个显示隐藏分支的标志......

4

3 回答 3

2

正如你所说的,“幽灵”分支不是一个分支。它是 DAG 上的提交,没有任何东西指向。

虽然我没有看过代码,但我想 git log 会通过从分支指针开始并向后工作来绘制图表并列出提交。由于您在分离 HEAD 状态下的提交没有任何指向它们,因此 git log 无法“看到”它们。

要解决这个问题,只需使用git branch branch_name <commit>. 然后 git log 将具有指向在分离的 HEAD 状态下完成的最后一次提交的内容,并在显示日志/绘制图形时“找到”这些提交。

于 2012-07-25T21:16:28.317 回答
2

这个“幽灵”分支没有出现在你的 git log --all 中的根本原因是这个日志只会代表所有的分支,而不是所有现有的提交。您必须考虑,当您重新提交提交时,您不会删除旧提交,您只需将它们复制到另一个父级,因此它们也是没有任何分支的提交,就像您的幽灵分支一样。

提交就像其他对象引用的对象,git 保存的唯一对象是分支引用的对象。它真的就像一个垃圾收集的内存,你的提交是你在内存中创建的一个对象,没有引用它。如果你运行git gcgit 将删除所有这些没有被任何分支引用的提交,包括你的“幽灵分支”。

您的解决方案是保留对此提交的引用,方法是按照 wasworld 的说明创建一个分支,或者标记您的提交git tag tagname sha1

编辑:git gc根据其手册页,不会删除最近的提交:

The optional configuration variable gc.reflogExpire can be set to indicate how long 
historical entries within each branch's reflog should remain available in this 
repository. The setting is expressed as a length of time, for example 90 days or 3
months. It defaults to 90 days.

因此,默认情况下,您的 ghost 分支将在git gc90 天内安全(无需您请求即可启动)。

于 2012-07-25T21:36:21.943 回答
1

在 git 中,分支只是指向提交的指针。所以当你说“问题是:一个人不能永远记住这个哈希”时,为什么不直接在它上面创建一个分支呢?

git branch branch_name <commit>

还要记住的是,如果您不创建任何指向此提交的分支,那么一旦到期时间过去,它将被 gc'ed。默认值为 90 天。

于 2012-07-25T21:31:44.300 回答