【问题标题】:What happens when you create a git branch and then remove the previous commit?当你创建一个 git 分支然后删除之前的提交时会发生什么?
【发布时间】:2011-11-08 22:36:06
【问题描述】:

我创建了一个新文件(包含大量代码和辛勤工作)并将其提交到我的 git 存储库的主分支。片刻之后,我意识到我可能应该为该文件创建一个分支。我以为我可以撤销 master 的提交并在分支上再次提交,但我认为我做事的顺序很愚蠢。出于某种原因,我先创建了分支,然后以 is it possible to revoke commits? 为指导撤销了提交。

这基本上是我所做的:

echo "Lots of code and hard work" > newfile.txt
git commit -m "thoughtless commit" newfile.txt
# Oh wait, I should've branched!
git branch thoughtful
git checkout thoughtful
# Hmm, I didn't mean for that last commit to be in master
git checkout master
# get the previous commit's hash
oldhead=$(git log | awk 'BEGIN{commitcount=0; } /^commit/{ if (commitcount++ == 1) { print $2 }; }')
git reset --hard "$oldhead"
git checkout thoughtful

所以现在我显然废弃了 master 上的提交(事实上,master 上不再存在“newfile.txt”),但它仍然存在于 >周到(我猜是reflog)。

有人能解释一下我在这里做了什么吗,为什么不需要提交 thoughtful

【问题讨论】:

  • 为了将来参考,您的reset 命令可以缩写为git reset --hard HEAD^,而不需要oldhead

标签: git branching-and-merging


【解决方案1】:

当您创建分支thoughtful 时,它从master 的当前状态开始,该状态已经包含提交。从那时起,这两个分支不再相关。无论您对master 做什么,都不会影响thoughtful。无论如何,引入文件的提交仍将是 thoughtful 的一部分。

您应该尝试git log thoughtfulgit log master 来查看提交历史。在 thoughtful 上,您仍然会看到您尝试从 master 中删除的提交。

下面是更完整的细分

假设我们目前在master...

echo "Lots of code and hard work" > newfile.txt
git commit -m "thoughtless commit" newfile.txt

您已在 master 上创建了一个提交,其中包含 newfile.txt

# Oh wait, I should've branched!
git branch thoughtful

您创建了一个分支 thoughtful,它处于当前状态 master,但在其他方面与 master 完全无关。分支的起点是master,因为您没有明确指定起点并且master 当前已签出。

git checkout thoughtful

现在你在thoughtful;您不必checkout 新分支来使它们成为现实,这一步绝对没有效果,因为您执行了以下操作:

# Hmm, I didn't mean for that last commit to be in master
git checkout master

现在你在master

# get the previous commit's hash
oldhead=$(git log | awk 'BEGIN{commitcount=0; } /^commit/{ if (commitcount++ == 1) { print $2 }; }')

您已经跳过了 圈以获得上一次提交,而您本来可以使用 master~HEAD~是你获得“先前”提交的方式,而不是通过检查git log。以后要撤消上一次提交,请使用git reset --hard HEAD~

git reset --hard "$oldhead"

您已更改提交 master 指向。现在是上面命令发现的任何提交,大概是在引入newfile.txt 之前的提交。使用--hard 会导致Git 也更新工作目录,所以newfile.txt 消失了;如果您省略了--hardnewfile.txt 仍会在目录中,但会在git status 中列为新文件。

git checkout thoughtful

您已返回到包含newfile.txtthoughtful,更新您的工作目录并重新引入newfile.txt

【讨论】:

    【解决方案2】:

    理解这一点的基础是,您必须将分支可视化为指向提交的指针,该提交是分支的 HEAD。每个提交都指向其一个或多个父级。分支(master 等)是一个指针。不多也不少。

    当您创建 thoughtful 时,您创建了另一个指向与 master 相同的提交的指针。然后,您将主指针移至上一个提交。您没有删除提交或类似的东西,您将主指针移动到上一个提交。而你的 thoughtful 分支/指针仍然指向你想要的提交。你正处于你想要的状态!

    PS:要获得旧的 HEAD,请使用 git reflog 或引用名称,如 HEAD@{1}。此外,在这种情况下,HEAD~ 也会为您提供正确的。

    【讨论】:

    • 好的,但我认为 tags 是指向提交的指针。标签和分支之间的区别仅仅是语义上的吗?
    • @kojiro - 是的语义和他们可以指向的内容不同,但指针仍然 - stackoverflow.com/questions/1457103/…
    • git book on tags 表示标签是basically a branch that never moves。最容易认为您的提交保存了该提交点磁盘上所有文件的整个状态,并且标签/分支是指向这些提交的指针。
    猜你喜欢
    • 1970-01-01
    • 2013-10-13
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 2021-10-20
    • 2021-08-02
    • 2015-05-10
    相关资源
    最近更新 更多