Git: 如何修改 HEAD^^ 提交的内容(不是提交信息)
Git: how to modify the content (not commit message) for the HEAD^^ commit
假设我工作于:
- 功能 1:文件 1 + 文件 3
- 功能 2:文件 2
我有以下提交
- 提交 2:功能 2 已完成。
- 提交 1:功能 1 已完成。
我做错了,我忘记将 file3 添加到提交 1。如何将 file3 的更改添加到提交 1?
一种方法是:
git reset --soft Commit 1
git add file3
git commit --amend
git add file2
git commit -m "feature 2 completed"
我不想这样是因为事实上我可能不仅有提交 2 而且还有提交 3,4,5,6...
还有其他简单的方法吗?
谢谢
从技术上讲,您不能修改任何 提交。即使 git commit --amend
也不会那样做。请记住,每个提交都由其哈希 ID 唯一标识。
你可以做的是获取一些现有的提交,提取它,然后用它来构建一个新的,不同的提交几乎 与原始提交相同,但无论您认为有缺陷的是什么,都已修复。然后你必须说服每个人——你自己,以及任何克隆了提交的人——停止使用旧的、有缺陷的提交,而是使用闪亮的新提交。新提交有一个新的、不同的 哈希 ID。
如果闪亮的新提交 而不是 在分支的顶端——如果它向后退了两步,例如在这种情况下——那么你还有一个额外的问题。请记住,像 master
和 develop
这样的分支名称标识 一个特定的提交 ,Git 调用 提示 分支的提交。每个提交还包含其 parent(先前)提交的哈希 ID,这就是 Git 从最新提交中查找较早提交的方式:
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
在这里,大写字母代表丑陋的大哈希 ID。名称 master
标识提交 G
:master
的 提示。名称 develop
标识提交 K
,develop
的提示。从提交 G
,Git 可以向后工作到 F
,然后是 E
,依此类推。从 K
、Git 可以倒推到 J
,最终到 E
等等。
如果提交 I
有问题,你可以做的是 Git 提取提交 I
,对 index-and-work-tree 对进行一些更改(只是就像你对任何其他提交所做的那样),然后进行 new 提交——我们称它为 I'
以表明它是 I
的替代品——其 parent 与 I
的 parent:
相同
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
\
I' <-- temporary
完成后,我们现在只需要 Git 将 J
复制到一个闪亮的新 J'
,其 parent 是 I'
并且其效果I'
与 J
对 I
的影响相同:
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
\
I'-J' <-- temporary
现在我们重复 K
的技巧,使 K'
:
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
\
I'-J'-K' <-- temporary
最后,我们告诉Git:删除临时名称。使名称 develop
标识闪亮的新提交 K'
而不是令人讨厌的旧 K
。 这给了我们:
...--D--E--F--G <-- master
\
H--I--J--K [abandoned]
\
I'-J'-K' <-- develop
并且如果我们停止绘制 废弃的分支,它看起来好像我们已经以某种方式更改了 三个提交。但我们没有:新的提交有新的、不同的哈希 ID。
...--D--E--F--G <-- master
\
H--I'-J'-K' <-- develop
这就是 git rebase -i
所做的。这听起来工作量很大,在某些情况下确实如此,但通常 git rebase -i
让 你 .
变得轻松无痛
请注意,如果您已将 develop
推送到其他地方,您现在必须 force-推送此新开发,以告知其他收到提交的 Git I
、J
和 K
它应该 忘记 那些提交(以及任何以后的提交!),而是使用闪亮的新替换.
如果其他用户选择了原始的 I-J-K
序列,您必须说服 他们 丢弃 他们的 I-J-K
副本也。如果他们在 K
之上构建了自己的提交,你必须让他们将他们的旧提交复制到你闪亮的新 K'
之上。对于所有其他用户来说,这可能是一项值得注意的工作量,因此请确保您真的想对他们执行此操作。
假设我工作于:
- 功能 1:文件 1 + 文件 3
- 功能 2:文件 2
我有以下提交
- 提交 2:功能 2 已完成。
- 提交 1:功能 1 已完成。
我做错了,我忘记将 file3 添加到提交 1。如何将 file3 的更改添加到提交 1?
一种方法是:
git reset --soft Commit 1
git add file3
git commit --amend
git add file2
git commit -m "feature 2 completed"
我不想这样是因为事实上我可能不仅有提交 2 而且还有提交 3,4,5,6...
还有其他简单的方法吗?
谢谢
从技术上讲,您不能修改任何 提交。即使 git commit --amend
也不会那样做。请记住,每个提交都由其哈希 ID 唯一标识。
你可以做的是获取一些现有的提交,提取它,然后用它来构建一个新的,不同的提交几乎 与原始提交相同,但无论您认为有缺陷的是什么,都已修复。然后你必须说服每个人——你自己,以及任何克隆了提交的人——停止使用旧的、有缺陷的提交,而是使用闪亮的新提交。新提交有一个新的、不同的 哈希 ID。
如果闪亮的新提交 而不是 在分支的顶端——如果它向后退了两步,例如在这种情况下——那么你还有一个额外的问题。请记住,像 master
和 develop
这样的分支名称标识 一个特定的提交 ,Git 调用 提示 分支的提交。每个提交还包含其 parent(先前)提交的哈希 ID,这就是 Git 从最新提交中查找较早提交的方式:
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
在这里,大写字母代表丑陋的大哈希 ID。名称 master
标识提交 G
:master
的 提示。名称 develop
标识提交 K
,develop
的提示。从提交 G
,Git 可以向后工作到 F
,然后是 E
,依此类推。从 K
、Git 可以倒推到 J
,最终到 E
等等。
如果提交 I
有问题,你可以做的是 Git 提取提交 I
,对 index-and-work-tree 对进行一些更改(只是就像你对任何其他提交所做的那样),然后进行 new 提交——我们称它为 I'
以表明它是 I
的替代品——其 parent 与 I
的 parent:
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
\
I' <-- temporary
完成后,我们现在只需要 Git 将 J
复制到一个闪亮的新 J'
,其 parent 是 I'
并且其效果I'
与 J
对 I
的影响相同:
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
\
I'-J' <-- temporary
现在我们重复 K
的技巧,使 K'
:
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
\
I'-J'-K' <-- temporary
最后,我们告诉Git:删除临时名称。使名称 develop
标识闪亮的新提交 K'
而不是令人讨厌的旧 K
。 这给了我们:
...--D--E--F--G <-- master
\
H--I--J--K [abandoned]
\
I'-J'-K' <-- develop
并且如果我们停止绘制 废弃的分支,它看起来好像我们已经以某种方式更改了 三个提交。但我们没有:新的提交有新的、不同的哈希 ID。
...--D--E--F--G <-- master
\
H--I'-J'-K' <-- develop
这就是 git rebase -i
所做的。这听起来工作量很大,在某些情况下确实如此,但通常 git rebase -i
让 你 .
请注意,如果您已将 develop
推送到其他地方,您现在必须 force-推送此新开发,以告知其他收到提交的 Git I
、J
和 K
它应该 忘记 那些提交(以及任何以后的提交!),而是使用闪亮的新替换.
如果其他用户选择了原始的 I-J-K
序列,您必须说服 他们 丢弃 他们的 I-J-K
副本也。如果他们在 K
之上构建了自己的提交,你必须让他们将他们的旧提交复制到你闪亮的新 K'
之上。对于所有其他用户来说,这可能是一项值得注意的工作量,因此请确保您真的想对他们执行此操作。