git:git revert的更好方法,无需额外的恢复提交

git: better way for git revert without additional reverted commit

我在一个远程+本地分支中有一个提交,我想将该提交从历史中抛出,并将其中一些提交放到自己的分支中。

基本上,现在我有:

1
           D---E---F---G master

我想要:

1
2
3
             E---G topic
            /
           D master

这应该在本地和(只有一个,称为源站)远程存储库中都存在。

哪种方法最干净?

此外,还有其他人克隆了该repo,并签出了主分支。如果我在远程回购中做这样一个改变,"git-pull"会对他们起到同样的作用吗?


如果你已经发表了,那么你是对的,你不想重写master的历史。你想要的是发布一个提交给master,使它回到它在D的状态,同时保留它的当前历史记录,以便其他用户可以轻松地合并或重新设置他们的工作。

如果你打算在将来某个时候把topic合并成master,那么你可能还想在mastertopic之间建立一个新的共同基础,这样当你随后合并topic时,你就不会失去在master。最简单的方法是在"撤消"提交的基础上进行"重做"提交,将master重置回其原始状态,并在此基础上建立新的topic分支。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# checkout master branch (currently at G)
git checkout master

# Reset the index to how we want master to look like
git reset D

# Move the branch pointer back to where it should be, leaving the index
# looking like D
git reset --soft HEAD@{1}

# Make a commit (D') for the head of the master branch
git commit -m"Temporarily revert E, F and G"

# Create the new topic branch based on master.
# We're going to make it on top of master and the 'undo'
# commit to ensure that subsequent merges of master->topic
# or topic->master don't merge in the undo.
git checkout -b topic

# Revert the undo commit, making a redo commit (G').
git revert HEAD

作为另一种选择,您可以将提交E、F和G分别重做每个部分,但由于E、F和G已经在您的发布历史中,如果您只引用"撤消"提交并说该提交正在撤消,则可能更容易理解。不管怎样,这就是git revert所做的。

基本上你所知道的就是这个。

1
2
3
4
D -- E -- F -- G -- D'      <-- master
                     \
                      \
                        G'  <-- topic

重要的是,您没有重写历史,主题是基于master的,因此合并不会意外地应用任何"撤消"提交。现在您可以安全地将mastertopic推送到远程存储库。


如果你愿意的话,你可以重写你的历史,但是如果其他人有历史的副本,那是个坏主意。在这种情况下,您可能会使用交互式的REBASE:git rebase -i master topic。这将为您提供从主控形状到主题的提交列表,以及有关如何使用它们的提示。您只需要删除包含要删除的提交的行。

也就是说,我必须强调,如果有人有这样的历史,那么这样做是不负责任的。您必须强制将其推送到中央回购,其他人必须修复其存储库以匹配,根据情况,可能相对简单或复杂。

在git-rebase手册页中有一个很好的部分叫做"从上游的钢筋中恢复",讨论如何处理这个问题,如果您真的决定这样做的话。

编辑:

对于简单的历史,一个常见的情况是,在迫使非快速推进中央回购(push -f之后),其他开发商:

  • 备份他们的老主人:git branch -m master master_old
  • 从源站获取更新并重新创建主服务器:git remote update origin; git branch master origin/master
  • 将所有主题分支重新设置为新主控形状:git rebase --onto master master_old topic

如果他们在自己的主科工作,而主科还没有开始,他们将不得不变得更加狂热,重新调整这项工作和所有的主题分支到主科的新位置…这应该让你明白为什么改写别人的历史是如此可怕。事实上,一旦某些东西被传递到公共存储库中,您应该将其视为硬记录和快速记录的历史,而不是正在进行的工作。


我发现git stash很有用

把它藏起来,不要再看了。