使用git还原部分提交


143

我想还原git中的特定提交。不幸的是,我们的组织仍然将CVS用作标准,因此当我提交回CVS时,多个git提交被合并为一个。在这种情况下,我希望选择原始的git commit,但这是不可能的。

是否有类似的方法git add --patch可以让我选择性地编辑差异以确定提交的哪些部分要还原?


这里有更多解决方案,但重点在于限制部分还原到特定文件。
ntc2 2014年

Answers:


225

在中使用--no-commit-n)选项git revert,然后撤消更改,然后使用git add --patch

$ git revert -n $bad_commit    # Revert the commit, but don't commit the changes
$ git reset HEAD .             # Unstage the changes
$ git add --patch .            # Add whatever changes you want
$ git commit                   # Commit those changes

注意:使用git add --patch添加的文件是要还原的文件,而不是要保留的文件。


13
对于那些不太熟悉git的用户,可能值得添加最后的必需命令:提交后,git reset --hard丢弃您不想还原的其他更改。
tremby 2012年

15
git reset --hard对于新手来说很危险,因为它可能会丢失想要的编辑内容。而是习惯了git status,这暗示着git checkout -- FILE..可以更安全地还原内容。
蒂诺

多么巨大的遗漏git; git revert应该只是--patch吵架。
卡兹(Kaz)

@Kaz:git revert用于还原整个提交。您可以git checkout -p用来交互式地选择要还原的位。
mipadi

1
我还想添加(也许)显而易见的东西,这首先保存您的工作。无论是commit第一,或者stash,再试试revert
费利佩·阿尔瓦雷斯

39

我已经成功使用了以下内容。

首先还原完整的提交(将其放入索引),但不提交。

git revert -n <sha1>  # -n is short for --no-commit

然后以交互方式从索引中删除还原的GOOD更改

git reset -p          # -p is short for --patch  

然后提交差价的反向差异

git commit -m "Partially revert <sha1>..."

最终,还原的GOOD更改(已由reset命令取消暂存)仍在工作树中。他们需要清理。如果工作树中没有其他未提交的更改,可以通过以下方法完成

git reset --hard

5
这不是公认的答案(使用reset HEAD .)的最佳替代方法,因为它不需要最终清除工作目录吗?
史蒂文·卢

2
此答案是优越的,因为reset -p它比reset HEAD后跟的要短add -p。但这仍然需要清理,因为在提交后,已重置的“好”块仍在工作目录中。
Chiel 10 Brinke

这个答案并不出众,因为交互移除你的变化经常混淆,而且容易出错---特别是如果其中任何需要的编辑。
卡兹(Kaz)

5

就我个人而言,我更喜欢这个版本,它可以重用自动生成的提交消息,并为用户提供在最终提交之前编辑并粘贴“部分地”一词的机会。

# generate a revert commit
# note the hash printed to console on success
git revert --no-edit <hash to revert>

# undo that commit, but not its changes to the working tree
# (reset index to commit-before-last; that is, one graph entry up from HEAD)
git reset HEAD~1

# interactively add reversions
git add -p

# commit with pre-filled message
git commit -c <hash from revert commit, printed to console after first command>

# reset the rest of the current directory's working tree to match git
# this will reapply the excluded parts of the reversion to the working tree
# you may need to change the paths to be checked out
# be careful not to accidentally overwrite unsaved work
git checkout -- .

4

解:

git revert --no-commit <commit hash>
git reset -p        # every time choose 'y' if you want keep the change, otherwise choose 'n'
git commit -m "Revert ..."
git checkout -- .   # Don't forget to use it.

如果您说它与公认的解决方案
有何

1
@Krzysztof为什么最后的结帐很重要,为什么此解决方案与user1338062不同?
马丁

3

另一种选择(如果文件的当前版本与您要还原的版本相距不远)是在要部分还原(从)的提交之前立即获取提交的哈希git log。然后,您的命令将变为:

$ git checkout -p <hash_preceding_commit_to_revert> -- file/you/want/to/fix.ext

这确实会更改工作树中的文件,但不会创建任何提交,因此,如果您确实塞满了文件,则可以从重新开始git reset --hard -- file/you/want/to/fix.ext


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.