如何将最后一次的git提交编辑为补丁文件?

10
有时候,通过编辑补丁文件而不是直接更改文件、将它们添加到工作集并修改提交,来修改提交是很有用的。
为了使这个过程变得容易,有一个命令在git中会很有用,它可以像git commit --amend一样(没有任何已暂存的更改),立即打开最近的提交,让用户可以在编辑器中编辑该提交作为一个补丁文件。
在git中,是否有可能:
  1. 只使用一个命令
  2. 不丢失提交信息?

1
git add --edit 只对新更改有效。 - wodow
一种可能性:https://blog.aloni.org/posts/gitology-2-git-retext/ - wodow
2个回答

10

我不确定是否可以在单个命令中完成,但几乎可以:

git reset -N HEAD~
git add --edit
git commit --reuse-message=ORIG_HEAD

一些解释:

  • git reset -N HEAD~:撤销上一次提交但保留更改内容
  • git add --edit 允许您以补丁格式编辑更改内容
  • git commit --reuse-message=ORIG_HEAD:使用 ORIG_HEAD 的提交消息提交缓存区的更改,ORIG_HEAD 是指 git reset 前所在的提交。

注意:由于只有 git add --edit 需要交互,如果需要,您甚至可以将这些命令链接在一行中并为其创建 Bash 或 Git 别名:

git reset -N HEAD~ && git add --edit && git commit --reuse-message=ORIG_HEAD

注意2:如果您编辑了提交内容,则此命令后,一些更改将保留在您的git存储库中。 您必须选择放弃所有更改(git checkout -- :/)或提交它们或...

如果您不对这些更改做任何操作,则调用上述命令两次将始终向您显示从第一个提交开始的更改:

git commit -am "very first commit"
git reset -N HEAD~
git add --edit # edit very first commit as patch
git commit --reuse-message=ORIG_HEAD
# you now have some unstaged changes lying around.
git reset HEAD~ # undo second commit
# the unstaged changes that are lying around now 
# are a combination of second commit and the unstaged changes
# that were still lying around.
# That combination = content of very first commit
git add --edit # edit that combination
git commit --reuse-message=ORIG_HEAD

如果您想要一个完整的命令,以便您可以继续应用;您可以包括放弃更改:

git reset -N HEAD~ && git add --edit && git commit --reuse-message=ORIG_HEAD && git checkout -- :/

请注意,这种方法是危险的,因为可能会丢失更改...


完整的脚本

您可以将此脚本保存为/usr/bin/git-edit-last-commit,然后通过git edit-last-commit运行它:

#!/bin/bash
set -e # exit on first error
if ! git diff-files --quiet
then
    echo "Your git repository is not clean: you have unstaged changes."
    exit 1
fi
if ! git diff-index --quiet --cached HEAD --
then
    echo "Your git repository is not clean: you have staged changes."
    exit 1
fi
git reset -N HEAD~
git add --edit
git commit --reuse-message=ORIG_HEAD
# supposing that this edit is really what you wanted, we can throw away leftovers
# if work was lost, in can be recovered using git reflog
git checkout -- :/

测试一下,它可以“一次”工作,但如果“重复”就不行:进行提交,使用命令序列进行编辑并制作补丁,然后再次运行命令序列并查看原始提交的补丁。 - wodow
@wodow 我已经扩展了我的答案,以向您解释该行为。 - Chris Maes
@wodow 现在是一个完整的脚本,并有一些保护措施:您可能不想重写列表提交并包括未暂存/已暂存的更改...否则,最后的 git checkout 部分可能会丢弃工作。 - Chris Maes
1
git reset HEAD~ 应该包括 -N,即 git reset -N HEAD~,这样在提交中添加的文件将被标记为“意向添加”,而不是未跟踪。 - Christoffer Hammarström

0

如果您需要编辑多个提交,可以使用 git format-patchgit am

git format-patch ${commit_hash}^ --stdout > patch
# edit the patch file accordingly
git reset --hard ${commit_hash}^
git am < patch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接