Git 重置行为
Git reset behavior
我有以下情况:
master 分支有一个稳定的应用程序版本。
开发人员 A 最近创建了一个名为 branch-a 的功能分支,其中包含多个提交(假设它们是 a-1、a-2, a-3)。此处实现的功能基于 master 的最新代码,目前已经过良好测试。
开发人员 B 有一个名为 branch-b 的功能分支,其中包含多个提交(例如,b-1、b-2, b-3).由于某种原因,B 先生的功能分支中有一个过时的版本(基于一两周前的 master 状态)并且根本没有测试代码。
两位开发人员合并了他们的功能分支以掌握使用:
- git结帐大师
- git拉源主
- git 合并分支 X(其中 X = a,b)
- git push origin master
没有使用变基命令。这个序列首先由 B 完成,接下来由 A 完成。
当我(开发人员 C)从 master 拉取时,我在 git 日志 中看到类似这样的内容:
- a-merge: 由开发者 A
与 master 合并
- a-3
- a-2
- a-1
- b-3(是的,这个提交紧接在合并之后)
- b-merge-conflicts:由开发者 B 与 master 合并(数千个文件冲突)
- b-2
- b-1
- master-stable:之前的稳定提交
结果B先生不知何故在合并时强制旧版本的代码覆盖稳定版本(导致b-merge-conflicts commit)。
现在我想重写历史并保存 b-1 + b-3 + a-1 + a-2 + a-3 更改并撤销 b-2, b-merge-冲突 和 a-merge.
我的想法是撤消几个最高提交直到 b-1 然后使用 cherry-pick 补丁来应用 b-3 , a-1, a-2, a-3 提交给新的 master.
但是当我尝试时:
git重置--硬头~7
我可以看到只包含旧提交(在 master-stable 之前)的历史,而没有 branch-a 和 branch-b 的历史。
当我尝试时:
git reset --hard HEAD~2
我可以在历史记录中看到顶部只有 master-stable 提交,但不是我想要的 a-2。
看起来 git 重置不会在 HEAD 之后将 digit 转换为要重置的提交数(正如我从文档中理解的那样),但作为一些 HEAD-通过 git 拉动进行更改(在我的示例中有 2 个)。
如何正确撤消前 7 个提交 b-2 .. a-merge 并重写从 b-1 开始的历史记录?
更新在评论中询问
我使用了(没有 --all 来排除附加信息)
git log --oneline --decorate --graph
* ef7d93f Merge with master by Developer A
|\
| * 2b9dd31 b-4
| * 924a452 b-3
| * 1f9489d b-2
| * e3cd7a6 Merge by Developer B [2]: Merge branch 'master' from https://github.com ....
| |\
| * | aece506 Merge by Developer B [1]: merge branch
| * | 487e7ee b-1
* | | d9404f8 a-1
| |/
|/|
* | 9b202ce master-stable last commit
我不确定HEAD~
,因为我通常使用HEAD^
。
虽然您不需要使用该表示法。您可以只提供提交的十六进制 SHA-1 哈希值,或者它的前 7 位左右的数字。
git reset --hard 72abfd4
git log
在骗你。它呈现 Git 历史,就好像它是线性的,它按日期顺序向您展示提交。那不是很有用。 git log --graph --decorate
将通过向您展示提交树(实际上是图表)来为您提供更清晰的故事。据我所知,您的存储库如下所示。
a1 - a2 - a3
/ \
origin c1 - c2 - c3 - c4 - b-merge - b3 -------- a-merge [master]
\ /
b1 -------------b2
如您所见,"go back seven commits"可以有多种解释。这就是为什么您应该避免将多个提交移回的表示法,而是参考提交 ID。
你要的就是这个
a1 - a2 - a3 [branch-a]
/
c1 - c2 - c3 - c4 [master]
\
b1 - b3 [branch-b]
要到达那里,请在 c4 之外创建 A 和 B 分支,这样您就有了一个可以建造的地方。
git branch branch-a c4
git branch branch-b c4
[branch-b] a1 - a2 - a3
[branch-a] / \
c1 - c2 - c3 - c4 - b-merge - b3 -------- a-merge [master]
\ /
b1 -------------b2
现在检查那些分支,并挑选适当的更改到它们上,修复所有冲突。
b1b - b3b [branch B]
/
| a1a - a2a - a3a [branch A]
| /
| / a1 - a2 - a3
|/ / \
c1 - c2 - c3 - c4 - b-merge - b3 -------- a-merge [master]
\ /
b1 -------------b2
这可能看起来一团糟,但现在结账大师和 git reset --hard c4
以及大师在 a-merge 保持活力的所有混乱都会消失(这是一个善意的谎言,origin/master 将在您推送之前保持它可见,而且 Git 实际上不会在数周内丢弃提交)。
b1b - b3b [branch B]
/
| a1a - a2a - a3a [branch A]
|/
c1 - c2 - c3 - c4 [master]
现在可以正常合并A和B了。完成后,您必须 push --force
因为 master 不是 origin/master 的 child。
这只是完成您想要的事情的一种方法。重要的是能够可视化存储库图,你希望它在哪里,以及什么命令会转换它。
我有以下情况:
master 分支有一个稳定的应用程序版本。
开发人员 A 最近创建了一个名为 branch-a 的功能分支,其中包含多个提交(假设它们是 a-1、a-2, a-3)。此处实现的功能基于 master 的最新代码,目前已经过良好测试。
开发人员 B 有一个名为 branch-b 的功能分支,其中包含多个提交(例如,b-1、b-2, b-3).由于某种原因,B 先生的功能分支中有一个过时的版本(基于一两周前的 master 状态)并且根本没有测试代码。
两位开发人员合并了他们的功能分支以掌握使用:
- git结帐大师
- git拉源主
- git 合并分支 X(其中 X = a,b)
- git push origin master
没有使用变基命令。这个序列首先由 B 完成,接下来由 A 完成。
当我(开发人员 C)从 master 拉取时,我在 git 日志 中看到类似这样的内容:
- a-merge: 由开发者 A 与 master 合并
- a-3
- a-2
- a-1
- b-3(是的,这个提交紧接在合并之后)
- b-merge-conflicts:由开发者 B 与 master 合并(数千个文件冲突)
- b-2
- b-1
- master-stable:之前的稳定提交
结果B先生不知何故在合并时强制旧版本的代码覆盖稳定版本(导致b-merge-conflicts commit)。
现在我想重写历史并保存 b-1 + b-3 + a-1 + a-2 + a-3 更改并撤销 b-2, b-merge-冲突 和 a-merge.
我的想法是撤消几个最高提交直到 b-1 然后使用 cherry-pick 补丁来应用 b-3 , a-1, a-2, a-3 提交给新的 master.
但是当我尝试时:
git重置--硬头~7 我可以看到只包含旧提交(在 master-stable 之前)的历史,而没有 branch-a 和 branch-b 的历史。
当我尝试时:
git reset --hard HEAD~2
我可以在历史记录中看到顶部只有 master-stable 提交,但不是我想要的 a-2。
看起来 git 重置不会在 HEAD 之后将 digit 转换为要重置的提交数(正如我从文档中理解的那样),但作为一些 HEAD-通过 git 拉动进行更改(在我的示例中有 2 个)。
如何正确撤消前 7 个提交 b-2 .. a-merge 并重写从 b-1 开始的历史记录?
更新在评论中询问
我使用了(没有 --all 来排除附加信息)
git log --oneline --decorate --graph
* ef7d93f Merge with master by Developer A
|\
| * 2b9dd31 b-4
| * 924a452 b-3
| * 1f9489d b-2
| * e3cd7a6 Merge by Developer B [2]: Merge branch 'master' from https://github.com ....
| |\
| * | aece506 Merge by Developer B [1]: merge branch
| * | 487e7ee b-1
* | | d9404f8 a-1
| |/
|/|
* | 9b202ce master-stable last commit
我不确定HEAD~
,因为我通常使用HEAD^
。
虽然您不需要使用该表示法。您可以只提供提交的十六进制 SHA-1 哈希值,或者它的前 7 位左右的数字。
git reset --hard 72abfd4
git log
在骗你。它呈现 Git 历史,就好像它是线性的,它按日期顺序向您展示提交。那不是很有用。 git log --graph --decorate
将通过向您展示提交树(实际上是图表)来为您提供更清晰的故事。据我所知,您的存储库如下所示。
a1 - a2 - a3
/ \
origin c1 - c2 - c3 - c4 - b-merge - b3 -------- a-merge [master]
\ /
b1 -------------b2
如您所见,"go back seven commits"可以有多种解释。这就是为什么您应该避免将多个提交移回的表示法,而是参考提交 ID。
你要的就是这个
a1 - a2 - a3 [branch-a]
/
c1 - c2 - c3 - c4 [master]
\
b1 - b3 [branch-b]
要到达那里,请在 c4 之外创建 A 和 B 分支,这样您就有了一个可以建造的地方。
git branch branch-a c4
git branch branch-b c4
[branch-b] a1 - a2 - a3
[branch-a] / \
c1 - c2 - c3 - c4 - b-merge - b3 -------- a-merge [master]
\ /
b1 -------------b2
现在检查那些分支,并挑选适当的更改到它们上,修复所有冲突。
b1b - b3b [branch B]
/
| a1a - a2a - a3a [branch A]
| /
| / a1 - a2 - a3
|/ / \
c1 - c2 - c3 - c4 - b-merge - b3 -------- a-merge [master]
\ /
b1 -------------b2
这可能看起来一团糟,但现在结账大师和 git reset --hard c4
以及大师在 a-merge 保持活力的所有混乱都会消失(这是一个善意的谎言,origin/master 将在您推送之前保持它可见,而且 Git 实际上不会在数周内丢弃提交)。
b1b - b3b [branch B]
/
| a1a - a2a - a3a [branch A]
|/
c1 - c2 - c3 - c4 [master]
现在可以正常合并A和B了。完成后,您必须 push --force
因为 master 不是 origin/master 的 child。
这只是完成您想要的事情的一种方法。重要的是能够可视化存储库图,你希望它在哪里,以及什么命令会转换它。