如何以编程方式编辑旧的git提交消息?

时间:2018-05-31 21:01:00

标签: git git-rebase git-commit amend

您可以以编程方式仅编辑最后一次提交消息:

git commit --amend -m 'xxxxxxx'

或以交互方式随机提交:

git rebase -i HEAD~n
# Vim opens up, select the commit you want to modify, and change the word "pick" for "edit"
git commit --amend -m "Changing an old commit message!"
git rebase --continue

我如何将两者结合起来?我想以编程方式更改消息,但是先前提交,而不仅仅是最后一次提交。

我想要修改的提交已经被推送到git服务器,但让其他人重新同步git项目并不是一个问题。

3 个答案:

答案 0 :(得分:6)

如果您只是更改了一些提交,请使用git rebase -i和“reword”选项。例如......

pick 6256642 mv file1 file2
pick 20c2e82 Add another line to file2

# Rebase 8236784..20c2e82 onto 8236784 (2 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit

pick切换为reword,您将获得一个编辑器来重写提交消息。

如果您需要对大量提交执行相同操作,请将git filter-branch--msg-filter一起使用。原始提交消息在stdin上,新的提交消息在stdout上。这是在当前分支的所有提交中将“颜色”更改为“颜色”的方法。

git filter-branch --msg-filter "perl -ple 's{color}{colour}g'"

答案 1 :(得分:4)

您不能简单地“修改”任意提交的原因是提交是不可变的。当您修改提交时,它实际上将当前提交替换为另一个提交并将您的分支移动到新提交。在您清理之前,旧消息,作者姓名等的提交仍然存在于历史中:

Before:

        master
          |
          v
A -- B -- C

After:

        master
          |
          v
A -- B -- C'
      \
       \- C

要模拟“修改”任意提交,您不仅要重写该提交,还要重写其后的整个历史记录,因为提交将其父项包含为其不可变数据的一部分:

Before:

        master
          |
          v
A -- B -- C

After:

         master
           |
           v
A -- B' -- C'
 \ 
  \- B --- C

您可以通过在您感兴趣的提交上创建分支,修改它,并将原始分支的提交范围重新定位到原始分支的尖端到新分支上来实现。以下示例显示您的目标:

Start:

             master
               |
               v
A -- B -- C -- D

New Branch:

             master
               |
               v
A -- B -- C -- D
     ^
     |
    temp

Amend:

             master
               |
               v
A -- B -- C -- D
 \
  \- B'
     ^
     |
    temp

Rebase:

A -- B  -- C  -- D
 \
  \- B' -- C' -- D'
     ^           ^
     |           |
    temp       master

Cleanup:

A -- B  -- C  -- D
 \
  \- B' -- C' -- D'
                 ^
                 |
               master

顺便说一句,除非没有显式的临时分支,否则当你只修改单个提交时,这几乎就是交互式rebase的作用。

答案 2 :(得分:0)

由于要以编程方式进行更改,因此不能选择交互式rebase(git rebase -i)。

无论出于何种原因,编辑旧的提交都将有效地重新建立所有提交的基础。如果您仅更改提交消息,则无需担心合并冲突。

您以目标提交作为其HEAD创建一个新的临时分支,编辑提交消息,将旧分支合并到新分支上,然后删除旧临时分支。

在shell脚本中:

CURBRANCH=`git rev-parse --abbrev-ref HEAD`
TMPBRANCH=tmp$$
git checkout $SHA -b $TMPBRANCH
MSG=`tempfile`
git log --format=%B -n 1 HEAD > $MSG
... edit the $MSG file
git commit --amend -F $MSG
SHA=`git rev-list -n 1 HEAD`   # Commit has change, so SHA has also changed
rm $MSG
git rebase --onto $TMPBRANCH HEAD $CURBRANCH
git branch -d $TMPBRANCH