5

我有一个远程“开发”分支,并且正在本地处理它。

我使用提交消息“my_feature”在“dev”上进行了第一次提交,将我的本地分支放在远程之前 1 个提交。

然后我开发了一些新东西并制作了一个git add -u,准备提交。然后我意识到我想将之前的提交消息改写为“my_feature (1/2)”,以使我当前的提交消息为“my_feature (2/2)”,将我的本地分支放在远程之前 2 个提交。

所以我做了一个git commit --amend(认为它只会编辑上一个提交的消息),将“my_feature”提交消息编辑为“my_feature (1/2)”,然后......最终得到一个标记为“my_feature (1/2)”的提交"进行所有更改(第一次提交 + 暂存文件差异)——我的索引现在是干净的。

所以如果我做对了,我的命令实际上做了一个提交,还提交了暂存文件,它产生了一个(合并的?)提交?

我没想到 Git 会做这样的事情。我只是想编辑我的旧提交消息,而不是将旧提交消息与我当前的暂存文件合并。(现在我想它rebase本来可以更好。)

虽然我可以理解为什么git commit --amend可以提交(即使我只想编辑提交消息),但我很难理解 Git 如何使用命令将我的两个提交合并为一个commit

任何人都可以向我澄清这一点吗?

$ git --version
git version 1.7.10.4
4

3 回答 3

7

如果您已暂存文件并执行

git commit --amend

您将使用先前提交中的所有内容以及已暂存的所有内容创建一个新提交,并且此新提交将替换先前提交作为您已签出的分支的尖端。

git commit --amend没有任何暂存文件可用于更改提交消息,但请注意,即使在没有暂存文件的情况下,您也会获得一个新的 sha1,换句话说就是一个新的提交。

文档中:

用于修改当前分支的尖端。像往常一样准备要替换最新提交的树对象(这包括通常的 -i/-o 和显式路径),并使用来自当前分支尖端的提交消息播种提交日志编辑器。你创建的提交替换了当前的提示——如果它是一个合并,它将把当前提示的父节点作为父节点——所以当前的顶部提交被丢弃。

于 2015-02-20T14:29:59.057 回答
3

这是预期的行为。从git commit文档中。

- 修正

通过创建一个新的提交来替换当前分支的尖端。记录的树像往常一样准备好(包括-iand-o选项和显式路径规范的效果),当没有从命令行指定其他消息时,使用原始提交的消息作为起点,而不是空消息通过诸如-m, -F,-c等选项。新提交与当前提交具有​​相同的父母和作者(该--reset-author选项可以抵消这一点)。

这是一个粗略的等价物:

$ git reset --soft HEAD^
$ ... do something else to come up with the right tree ...
$ git commit -c ORIG_HEAD

但可用于修改合并提交。

如果您修改已发布的提交,您应该了解重写历史的含义。(请参阅git-rebase[1]中的“从上游 REBASE 恢复”部分。)


要理解的重要部分是git reset --soft HEAD^。这将从您的历史记录中“删除”提交,但不会更改您的工作树或索引。

看一下. git reset强调我的。

- 柔软的

根本不接触索引文件或工作树(但将头部重置为 ,就像所有模式一样)。正如git status所说,这会使您所有更改的文件都“提交更改” 。

于 2015-02-20T14:37:03.953 回答
2

git commit --amend将为最近的提交添加阶段性更改。由于它合并了你的两个,我怀疑没有两个提交,而是一个。

手册页解释了这一点:

--amend
    Replace the tip of the current branch by creating a new commit. The
    recorded tree is prepared as usual (including the effect of the -i and
    -o options and explicit pathspec), and the message from the original
    commit is used as the starting point, instead of an empty message, when
    no other message is specified from the command line via options such as
    -m, -F, -c, etc. The new commit has the same parents and author as the
    current one (the --reset-author option can countermand this).

    It is a rough equivalent for:

        $ git reset --soft HEAD^
        $ ... do something else to come up with the right tree ...
        $ git commit -c ORIG_HEAD

    but can be used to amend a merge commit.

    You should understand the implications of rewriting history if you
    amend a commit that has already been published. (See the "RECOVERING
    FROM UPSTREAM REBASE" section in git-rebase[1].)

因为您描述了处理多个提交,所以我将解释上述描述的工作流程如何改为:

A--B (origin/dev) (dev)

编辑文件,然后添加暂存 ( git add -u):

$ git commit # edit a good message (see below)

A--B (origin/dev)
    \
     C (dev)

现在重复:

$ git commit # edit another awesome message (see below)

A--B (origin/dev)
    \
     C--D (dev)

但是现在你意识到提交 C 有一个错误的提交信息。所以我们做一个变基:

$ git rebase -i origin/dev

在编辑器中,您将看到提交 C 和 D 及其主题行和关键字pick。找到您要修复的提交并将其更改pickreword然后保存文件。

git 将打开另一个编辑器并让您修复提交消息。保存并继续。

关于提交消息的注释(因为我试图传播这个词):

https://thoughtbot.com/blog/5-useful-tips-for-a-better-commit-message

Capitalized, short (50 chars or less) summary

More detailed explanatory text, if necessary.  Wrap it to about 72
characters or so.  In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body.  The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.

Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
or "Fixes bug."  This convention matches up with commit messages generated
by commands like git merge and git revert.

Further paragraphs come after blank lines.

- Bullet points are okay, too

- Typically a hyphen or asterisk is used for the bullet, followed by a
  single space, with blank lines in between, but conventions vary here

- Use a hanging indent
于 2015-02-20T14:34:39.523 回答