【问题标题】:Reverting part of a commit with git使用 git 恢复部分提交
【发布时间】:2011-06-15 07:12:48
【问题描述】:

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

是否有类似于git add --patch 的方法可以让我有选择地编辑差异来决定要恢复提交的哪些部分?

【问题讨论】:

  • 更多解决方案here,但重点是限制部分还原到特定文件。

标签: git git-cvs


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    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 添加的文件是您要还原的文件,而不是您要保留的文件。

    【讨论】:

    • 可能值得添加最终所需的命令,对于那些不太熟悉 git 的人:提交后,git reset --hard 丢弃您不想恢复的其他更改。
    • git reset --hard 对新手来说很危险,因为它可能会丢失想要的编辑。而是习惯git status,这提示git checkout -- FILE.. 可以更安全地还原。
    • git 中有多么大的遗漏; git revert 应该只接受 --patch 参数。
    • @Kaz: git revert 用于恢复整个提交。您可以使用git checkout -p 以交互方式选择要还原的位。
    • 我还想添加(也许)显而易见的,即首先保存您的工作。要么先commit,要么先试试stash,然后试试revert
    【解决方案3】:

    我已经成功使用了以下。

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

    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
    

    【讨论】:

    • 这不是公认答案(使用reset HEAD .)的更好选择吗,因为它不需要最终清理工作目录?
    • 这个答案更好,因为reset -preset HEAD 短,后跟add -p。但它仍然需要清理,因为已重置的“好”块在提交后仍在工作目录中。
    • 这个答案并不好,因为以交互方式删除您想要的更改通常会令人困惑且容易出错 --- 特别是如果其中任何一个需要编辑。
    【解决方案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.
    

    【讨论】:

    • 如果您说它与公认的解决方案有何不同,这将对人们有所帮助
    • @Krzysztof 为什么最后结帐很重要,为什么这个解决方案与 user1338062 的不同?
    【解决方案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 -- .
    

    【讨论】:

      【解决方案6】:

      另一种选择(如果您当前的文件版本与您尝试还原的版本相差不远)是获取 commit 的哈希值 您想要的那个之前部分还原(来自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 重新开始。

      【讨论】:

        猜你喜欢
        • 2016-06-23
        • 1970-01-01
        • 2021-01-22
        • 1970-01-01
        • 2011-04-08
        • 1970-01-01
        • 2015-06-15
        • 2021-04-13
        • 2011-10-11
        相关资源
        最近更新 更多