10

您只能以编程方式编辑最后一条提交消息:

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 项目不是问题。

4

3 回答 3

10

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

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 在您只修改单个提交时所做的事情,除非没有显式的临时分支。

于 2018-05-31T21:20:21.227 回答
8

如果您只是更改一些提交,请使用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

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


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

git filter-branch --msg-filter "perl -ple 's{color}{colour}g'"
于 2018-05-31T21:38:01.250 回答
5

由于您想以编程方式进行更改,因此交互式 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
于 2019-02-04T22:17:50.743 回答