git - 我怎样才能轻松修复过去的提交?

标签 git rewrite

我刚刚读了amending a single file in a past commit in git但不幸的是,公认的解决方案“重新排序”了提交,这不是我想要的。所以这是我的问题:

在处理(不相关的)功能时,我时不时地注意到代码中的错误。一个快速的 git blame 然后会显示错误已经在几次提交之前引入(我提交了很多,所以通常不是最近的提交引入了错误)。在这一点上,我通常这样做:

git stash                      # temporarily put my work aside
git rebase -i <bad_commit>~1   # rebase one step before the bad commit
                               # mark broken commit for editing
vim <affected_sources>         # fix the bug
git add <affected_sources>     # stage fixes
git commit -C <bad_commit>     # commit fixes using same log message as before
git rebase --continue          # base all later changes onto this

但是,这种情况经常发生,以至于上面的序列变得很烦人。特别是“交互式 rebase ”很无聊。上面的顺序有没有捷径,可以让我用分阶段的更改修改过去的任意提交?我很清楚这会改变历史,但我经常犯错,所以我真的很想拥有类似的东西

vim <affected_sources>             # fix bug
git add -p <affected_sources>      # Mark my 'fixup' hungs for staging
git fixup <bad_commit>             # amend the specified commit with staged changes,
                                   # rebase any successors of bad commit on rewritten 
                                   # commit.

也许是一个可以使用管道工具等重写提交的智能脚本?

最佳答案

更新的答案

不久前,一个新的--fixup 参数被添加到git commit 中,它可以被用来构造一个带有适合git 的日志消息的提交 rebase --interactive --autosquash。因此,现在修复过去提交的最简单方法是:

$ git add ...                           # Stage a fix
$ git commit --fixup=a0b1c2d3           # Perform the commit to fix broken a0b1c2d3
$ git rebase -i --autosquash a0b1c2d3~1 # Now merge fixup commit into broken commit

原始答案

这是我不久前写的一个小 Python 脚本,它实现了我希望在我的原始问题中使用的这个 git fixup 逻辑。该脚本假设您进行了一些更改,然后将这些更改应用于给定的提交。

注意:此脚本是特定于 Windows 的;它查找 git.exe 并使用 set 设置 GIT_EDITOR 环境变量。根据其他操作系统的需要进行调整。

使用这个脚本,我可以精确地实现我要求的“修复损坏的源、阶段修复、运行 git fixup”工作流:

#!/usr/bin/env python
from subprocess import call
import sys

# Taken from http://stackoverflow.com/questions/377017/test-if-executable-exists-in python
def which(program):
    import os
    def is_exe(fpath):
        return os.path.exists(fpath) and os.access(fpath, os.X_OK)

    fpath, fname = os.path.split(program)
    if fpath:
        if is_exe(program):
            return program
    else:
        for path in os.environ["PATH"].split(os.pathsep):
            exe_file = os.path.join(path, program)
            if is_exe(exe_file):
                return exe_file

    return None

if len(sys.argv) != 2:
    print "Usage: git fixup <commit>"
    sys.exit(1)

git = which("git.exe")
if not git:
    print "git-fixup: failed to locate git executable"
    sys.exit(2)

broken_commit = sys.argv[1]
if call([git, "rev-parse", "--verify", "--quiet", broken_commit]) != 0:
    print "git-fixup: %s is not a valid commit" % broken_commit
    sys.exit(3)

if call([git, "diff", "--staged", "--quiet"]) == 0:
    print "git-fixup: cannot fixup past commit; no fix staged."
    sys.exit(4)

if call([git, "diff", "--quiet"]) != 0:
    print "git-fixup: cannot fixup past commit; working directory must be clean."
    sys.exit(5)

call([git, "commit", "--fixup=" + broken_commit])
call(["set", "GIT_EDITOR=true", "&&", git, "rebase", "-i", "--autosquash", broken_commit + "~1"], shell=True)

关于git - 我怎样才能轻松修复过去的提交?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3103589/

相关文章:

.htaccess - 从 url .htaccess 重写/重定向特定单词

apache - 为 JIRA ServiceDesk 重写条件规则

javascript - Trigger.io 协作

php - 如何确定 URL 是否在 PHP 中重定向?

wordpress - 在自己的目录中安装 WordPress 但永久链接失败

.htaccess - 使用 htaccess 重写 url

git - 错误 : RPC failed; HTTP 503 curl 22 The requested URL returned error: 503

windows - 在 Windows 上签署 git commit 时出现 "No secret key"错误

git 命令仅在文件夹中添加/暂存修改的文件

git - 检查远程 Git 上是否存在本地分支