创建带有最近N次提交的分支。

23

我已经克隆了代码仓库并进行了一些提交:

git clone ...
git add
git commit
git add
git commit
git add 
git commit 

现在我意识到将所有的提交移动到另一个新分支会更好。如何最好地做到这一点?

3个回答

33

简单来说,检出你的新分支,然后将旧分支(假设为master且有3个提交)移回:

git checkout -b my_new_branch
git branch -f master HEAD~3

不错。不过我认为你可能需要一个 -fgit branch -f master HEAD~3 - Rob Davis
@rob:是的,我忘记在那里加上“-f”了。 - knittl
1
@BrettRyan:嗯,你得强制推送 - 但这将改变历史记录。所有已经从你的仓库拉取或克隆的人都会感到困惑。只有在真的必须时才这样做。 - knittl
@knittl 我想做的就是撤销3个提交,例如,它们可以留在历史记录中,只需撤消所有更改并作为新提交进行提交,提交消息应说明导致了撤消。 - Brett Ryan
这个回答解释了git-revert的用法,让我能够实现我想要的功能。 - Brett Ryan
@BrettRyan:好的,这是另一种情况。这个答案(和问题)是关于如何将最后N个提交移动到另一个分支(并从当前分支中有效地删除)。如果您想撤消最后N个提交(也就是创建一个与HEAD^N相同树的提交),可以执行以下操作:git reset --soft HEAD^3; git commit -m'undoing the last 3 commits'; - knittl

5

knittl's answer适用,但还有其他方法可以做到这一点。

我假设你在克隆这个仓库时处于master分支,当你第一次克隆这个仓库时,主分支将与你从中克隆的仓库上的主分支匹配。这是origin/master。由于你的问题以clone开头,这是一个合理的假设。

因此,在你在主分支上进行提交之后,你现在超过了origin/master分支。

你要做的第一件事就是创建一个新分支。

git branch new_branch

注意:此命令仅创建新分支,但不会切换分支。因此,masternew_branch现在指向相同的提交,但您仍然在master分支上。
下一步要做的是将当前分支(即master)设置为添加提交之前的状态。这与origin/master的状态相同,因此您可以发出此命令。
git reset --hard origin/master

这将把当前分支设置为与origin/master相同的状态。 --hard将索引和工作树设置为初始状态。还有其他标志,但它们在此处无法实现您想要的功能。(注意:如果您在工作树中有未提交的更改,则现在它们已被丢弃。在重置之前,在这种情况下使用git stash。)
因此,现在您位于指向与origin/master相同状态的master上,您只需要切换到新分支即可:
git checkout new_branch

是的,这个命令有点长(3个命令而不是2个),但你不需要数一下要回退多少次提交,即使你已经创建了分支、合并和变基,这个方法也可以使用;另外我还可以解释Git中其他的做法。


reset --hard 将从工作树中删除所有更改。你提到了“将索引和工作树设置为初始状态”,但我认为这个警告对于 Git 新手来说不够清晰。在合并、变基和其他操作后,使用 git branch 也可以起作用。你可以使用 git branch -f master origin/master 在 origin/master 提交(或任何其他位置)重新创建主分支。 - knittl
@abizem:一个Git仓库只有一个工作树。对于new_branchmaster来说都是一样的。如果你在master上执行了git reset --hard,然后切换回new_branch,你仍然会有一个干净的工作树——除非你在切换分支之前进行了存储并在执行分支之间的切换和重置游戏后弹出了更改。我没有看到你的答案中提到stash ;) - knittl
3
你可以在knittl的版本中使用origin/master代替HEAD~3 - Paŭlo Ebermann
1
@Abizern:问题(knittl指出的)是reset --hard会丢失工作树中的任何未提交的更改(普通的checkout会在这里抱怨)。可以通过在之前使用git stash来避免这种情况,或者使用knittl的版本,它根本不会影响工作树。 - Paŭlo Ebermann
1
我并没有说你的答案是错的,我只是觉得它缺少了一个有关丢失未提交更改的警告。不过,你关于不同工作树适用于不同分支的评论是错误的。add+commit 并不意味着每个更改都已经被提交了... - knittl
显示剩余6条评论

2
创建一个新分支,然后将HEAD重置为origin/master。
git branch new_branch
git reset --hard origin/master

注意:这个最后的命令将会丢弃你工作副本中尚未提交的任何内容。如果有任何需要保留的内容,请在此之前使用git stash

然后切换到你的新分支。

git checkout new_branch

reset --hard会从工作树中删除所有更改!这是一个非常糟糕的建议,完全没有任何警告提示。 - knittl
@knittl - 实际上不会,因为你已经在new_branch中进行了更改。它将重置主分支的工作树,但然后你可以检出new_branch - Abizern
@abizem:请查看我对你的回答评论的回复。 - knittl
@knittl:我在这里添加了一个警告。 - Paŭlo Ebermann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接