用 git 恢复提交的一部分

我想在 git 中恢复一个特定的提交。不幸的是,我们的组织仍然使用 CVS 作为标准,所以当我重新提交到 CVS 时,多个 git 提交合并为一个。在这种情况下,我希望挑出最初的 git 提交,但这是不可能的。

是否有一种类似于 git add --patch的方法,允许我选择性地编辑差异,以决定恢复提交的哪些部分?

49352 次浏览

您可以使用 git-return-n,然后使用 add-patch 来选择 hunks。

git revert使用 --no-commit(-n)选项,然后卸载更改,然后使用 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 添加的文件是要还原的文件,而不是要保留的文件。

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

首先恢复完整提交(将其放入 index 中) ,但不提交。

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>..."

最后,恢复好的更改(已经被重置命令取消暂存)仍然在工作树中。他们需要被清理干净。如果工作树中没有其他未提交的更改,可以通过

git reset --hard

解决方案:

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.

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

# 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 -- .

另一种替代方法(如果文件的当前版本距离您试图恢复的版本不太远)是交互式的 checkout。查看 git log并获取您希望撤消的提交的散列,或者它的 就在那之前散列。你的命令变成:

git checkout --patch HASH_OF_COMMIT_TO_REVERT^ -- file/you/want/to/fix.ext

(其中 ^表示父提交)或:

git checkout --patch HASH_PRECEDING_COMMIT_TO_REVERT -- file/you/want/to/fix.ext

然后,您可以选择恢复的块,或部分,通过选择 s(分割)选项时修补。

这确实改变了工作树中的文件,但是没有创建提交,所以如果你真的很忙,你可以重新开始使用 git reset --hard -- file/you/want/to/fix.ext