用git恢复部分提交

ski*_*ppy 135 git git-cvs

我想在git中恢复一个特定的提交.不幸的是,我们的组织仍然使用CVS作为标准,所以当我提交回CVS时,多个git提交被归为一个.在这种情况下,我很想挑出原始的git提交,但这是不可能的.

是否有类似的方法git add --patch允许我有选择地编辑差异来决定提交的哪些部分还原?

mip*_*adi 211

使用--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
Run Code Online (Sandbox Code Playgroud)

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

  • `git reset --hard`对于新手很危险,因为它可能会松散想要的编辑.相反习惯了`git status`,这提示`git checkout - FILE..`可以更安全地恢复. (14认同)
  • 对于那些不太熟悉git的人来说,可能值得添加最后需要的命令:在提交之后,`git reset --hard`放弃你不想恢复的其他更改. (12认同)
  • `git` 中多么大的遗漏啊;`git revert` 应该只接受 `--patch` 参数。 (3认同)

use*_*062 37

我成功地使用了以下内容.

首先恢复完整提交(将其置于索引中)但不提交.

git revert -n <sha1>  # -n is short for --no-commit
Run Code Online (Sandbox Code Playgroud)

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

git reset -p          # -p is short for --patch  
Run Code Online (Sandbox Code Playgroud)

然后提交不良更改的反向差异

git commit -m "Partially revert <sha1>..."
Run Code Online (Sandbox Code Playgroud)

最后,恢复的GOOD更改(已由reset命令取消暂停)仍在工作树中.他们需要清理.如果工作树中没有剩余其他未提交的更改,则可以通过执行此操作

git reset --hard
Run Code Online (Sandbox Code Playgroud)

  • 这不是接受答案(使用`reset HEAD .`)的优秀替代品,因为它不需要最终清理工作目录吗? (5认同)
  • 这个答案是优越的,因为`reset -p`比`reset HEAD`后跟`add -p`短.但它仍然需要清理,因为已经重置的"好"帅哥仍然在提交后的工作目录中. (2认同)

Wal*_*alf 8

另一种选择(如果文件的当前版本与您尝试恢复的版本相差不太远)是checkout交互方式。查看git log并获取您想要撤消的提交的哈希值,或者紧邻其之前的提交的哈希值。您的命令变为:

git checkout --patch HASH_OF_COMMIT_TO_REVERT^ -- file/you/want/to/fix.ext
Run Code Online (Sandbox Code Playgroud)

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

git checkout --patch HASH_PRECEDING_COMMIT_TO_REVERT -- file/you/want/to/fix.ext
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过在修补时选择s(拆分)选项来选择要恢复的块或其中的一部分。

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


小智 5

解决方案:

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.
Run Code Online (Sandbox Code Playgroud)

  • @Krzysztof 为什么最后结帐很重要,为什么这个解决方案与 user1338062 的解决方案不同? (2认同)

jef*_*150 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 -- .
Run Code Online (Sandbox Code Playgroud)