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

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

问题描述

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

偶尔,我在处理一个(不相关的)特性时会注意到我的代码中存在一个错误。然后快速的 git blame 就会发现这个bug在几次提交之前就已经介绍过了(我承诺很多,所以通常不是引入bug的最新提交)。在这一点上,我通常这样做:

  git stash#暂时将我的工作放在一旁
git rebase -i< ; bad_commit>〜1#在坏提交前一步重新绑定
#标记用于编辑的提交
vim< affected_sources> #修复bug
git add< affected_sources> #阶段修复
git commit -C< bad_commit> #提交与以前相同的日志消息的修复
git rebase --continue#base所有后来更改到此

然而,这种情况经常发生,以致上述顺序变得令人讨厌。特别是'互动式底牌'很无聊。上述顺序有没有捷径可以让我修改过去任意提交的阶段性更改?我完全意识到这会改变历史,但我经常犯错误,所以我真的很喜欢这样的事情。

  vim< affected_sources> #修正bug 
git add -p< affected_sources> #将我的'fixup'hungs标记为
git fixup< bad_commit> #使用分步更改修改指定的提交,
#重新绑定重写
#commit时的任何后续提交。

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

解决方案

UPDATED ANSWER



前一段时间,新的 - fixup 参数被添加到 git commit 中,它可以用来构造一个提交日志消息,适合 git rebase - 互动--autosquash 。所以,修正过去提交的最简单方法是:

  $ git add ...#修复修复
$ git commit --fixup = a0b1c2d3#执行提交修复破坏a0b1c2d3
$ git rebase -i --autosquash a0b1c2d3〜1#现在将fixup commit合并到已损坏的提交中



ORIGINAL ANSWER



这是我前一段写的一个小Python脚本,它实现了 git fixup 我希望在我原来的问题中使用逻辑。该脚本假定您执行了一些更改,然后将这些更改应用于给定的提交。
$ b 注意:该脚本是Windows特定的;它会查找 git.exe 并使用 set 设置 GIT_EDITOR 环境变量$ C>。根据需要为其他操作系统进行调整。



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

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

#取自http://stackoverflow.com/questions/377017/test-if-executable-exists-in python
def其中(程序):
导入os
def is_exe(fpath):
返回os.path.exists(fpath)和os.access(fpath,os.X_OK)
$ b $ fpath,fname = os.path.split(program)
if fpath:
如果is_exe(程序):
返回程序
else:
用于os.environ中的路径[PATH]。split(os.pathsep) :
exe_file = os.path.join(路径,程序)$ b $如果is_exe(exe_file):
返回exe_file

返回无

如果len(sys.argv)!= 2:
print用法:git fixup< commit>
sys.exit(1)

git = which(git.exe)
如果不是git:
printgit-fixup:failed to locate git可执行文件
sys.exit(2)

broken_commit = sys.argv [1]
如果调用([git,rev-parse,--verify, --quiet,broken_commit])!= 0:
printgit-fixup:%s不是有效的提交%broken_commit
sys.exit(3)

如果调用([git,diff,--staged,--quiet])== 0:
printgit-fixup:无法修复过去的提交;没有修复上演。
sys.exit(4)

如果调用([git,diff,--quiet])!= 0:
printgit-fixup:can not fixup过去提交;工作目录必须是干净的。
sys.exit(5)

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


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:

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?

解决方案

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

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.

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.

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天全站免登陆