如何轻松修复过去的提交? [英] How can I easily fixup a past commit?

查看:19
本文介绍了如何轻松修复过去的提交?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚读了 修改单个文件过去在 git 中提交 但不幸的是,接受的解决方案重新排序"了提交,这不是我想要的.所以这是我的问题:

I just read amending a single file in a past commit in git but unfortunately the accepted solution 'reorders' the commits, which is not what I want. So here's my question:

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

Every now and then, I notice a bug in my code while working on an (unrelated) feature. A quick git blame then reveals that the bug has been introduced a few commits ago (I commit quite a lot, so usually it's not the most recent commit which introduced the bug). At this point, I usually do this:

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

然而,这种情况经常发生,以至于上面的序列变得很烦人.尤其是交互式变基"很无聊.上述顺序是否有任何快捷方式,可以让我通过分阶段更改修改过去的任意提交?我非常清楚这会改变历史,但我经常犯错误,以至于我真的很想拥有这样的东西

However, this happens so often that the above sequence is getting annoying. Especially the 'interactive rebase' is boring. Is there any shortcut to the above sequence, which lets me amend an arbitrary commit in the past with the staged changes? I'm perfectly aware that this changes the history, but I'm doing mistakes so often that I'd really love to have something like

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.

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

Maybe a smart script which can rewrite commits using plumbing tools or so?

推荐答案

更新的答案

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

UPDATED ANSWER

A while ago, a new --fixup argument was added to git commit which can be used to construct a commit with a log message suitable for git rebase --interactive --autosquash. So the simplest way to fixup a past commit is now:

$ 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 逻辑.该脚本假定您暂存了一些更改,然后将这些更改应用于给定的提交.

ORIGINAL ANSWER

Here's a little Python script I wrote a while ago which implements this git fixup logic I hoped for in my original question. The script assumes that you staged some changes and then applies those changes to the given commit.

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

NOTE: This script is Windows-specific; it looks for git.exe and sets the GIT_EDITOR environment variable using set. Adjust this as needed for other operating systems.

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

Using this script I can implement precisely the 'fix broken sources, stage fixes, run git fixup ' workflow I asked for:

#!/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)

这篇关于如何轻松修复过去的提交?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆