【问题标题】:Git reset behaviorGit 重置行为
【发布时间】:2015-02-21 17:24:49
【问题描述】:

我有以下情况:

ma​​ster 分支有一个稳定版本的应用程序。

开发人员 A 最近创建了一个名为 branch-a 的功能分支,其中包含多个提交(让它们成为 a-1a-2 , a-3)。此处实现的功能基于来自 ma​​ster 的最新代码,并且目前已经过充分测试。

开发者 B 有一个名为 branch-b 的功能分支,其中包含多个提交(例如,b-1b-2b-3)。由于某种原因,B 先生的功能分支中有一个过时的版本(基于 master 的一两周前的状态),根本没有测试代码。

两位开发人员将他们的功能分支合并为 master 使用:

  1. git checkout master
  2. git pull origin master
  3. git 合并分支-X(其中 X = a,b)
  4. git push origin master

没有使用变基命令。首先这个序列由 B 完成,接下来由 A 完成。

当我(开发人员 C)从 master 中提取时,我在 git log 中看到了类似的内容:

  • 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提交)。

现在我想重写历史并保存 b-1 + b-3 + a-1 + a- 2 + a-3 更改和撤消 b-2b-merge-conflictsa-merge。

我的想法是在 b-1 之前撤消几个最重要的提交,然后使用cherry-pick 补丁来应用 b-3a-1, a-2, a-3 提交给新的主人。

但是当我尝试时:

git reset --hard HEAD~7 我可以看到仅包含旧提交(在 master-stable 之前)的历史记录,而没有包含分支 a 和分支 b 的历史。

当我尝试时:

git reset --hard HEAD~2

我可以在历史记录中看到顶部只有 master-stable 提交,但不是我想要的 a-2

看起来 git reset 并没有将 HEAD 之后的数字转换为要重置的提交次数(正如我从文档中发现的那样),但是作为 git pull 的一些 HEAD 更改(在我的示例中有 2 )。

如何正确撤消前 7 次提交 b-2 .. a-merge 并重写从 b-1 开始的历史记录?

在 cmets 中询问更新

我用过(没有 --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

【问题讨论】:

  • 关于排序,用--topo-order再试一次。日志的通常顺序是日期顺序,如果您在 Windows 上,则各种机器上的时钟可能相当不同步。
  • 不要简单地运行git log,而是尝试运行git log --oneline --decorate --graph --all。这会让你更好地了解 repo 的状态。
  • 因为涉及到合并,提交的线性显示是不够的。您应该首先使用 gitk 或 TortoiseGit 之类的工具来显示提交的漂亮图表,并让我们知道它的外观。
  • 使用@Jubobs 的命令。给它起一个别名。它是所有 git 中最有用的显示的一个不错的候选。
  • >5min 我的git config --global alias.lgdo '!git log --graph --decorate --oneline "${@---all}"'so --all 只是默认值

标签: git merge rebase


【解决方案1】:

git log 在骗你。它以线性方式呈现 Git 历史记录,它按日期顺序向您显示提交。那不是很有用。 git log --graph --decorate 将通过向您展示提交的树(实际上是图表)为您提供更清晰的故事。据我所知,您的存储库如下所示。

                                       a1 - a2 - a3
                                      /            \
origin c1 - c2 - c3 - c4 - b-merge - b3 -------- a-merge [master]
        \                  /
         b1 -------------b2

如您所见,“返回七次提交”可以有多种解释。这就是为什么您应该避免将多个提交移回该符号,而是引用提交 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

这可能看起来像一团糟,但现在结帐 master 和 git reset --hard c4 以及 master 在 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 的孩子。

这只是实现您想要的一种方式。重要的是能够可视化存储库图、您希望它在哪里以及哪些命令会对其进行转换。

【讨论】:

  • soooooo,现在一切都清楚了。但是有没有办法撤消以线性方式(按日期排序)呈现的顶级提交?也许通过 rebase -i 删除 repo-braking 提交,以正确的方式重新排序并修复冲突?
  • @AndreyPesoshin 根据日期顺序考虑 Git 提交只是假装其历史是线性的另一种方式,这只会给您带来麻烦。如果你想要线性历史,你必须让它成为线性的。在 c4 上做一个分支,然后将 b1、b3、a1、a2 和 a3 摘到上面。但是应该保留分支历史,而不是线性化,以保持对提交相关的理解(即 b1 与 b3 一起,但 a1、a2 和 a3 是一个单独的组)。
【解决方案2】:

我不确定HEAD~,因为我通常使用HEAD^

不过,您不需要使用该符号。您可以只提供提交的十六进制 SHA-1 哈希,或者它的前 7 位左右的数字。

git reset --hard 72abfd4

【讨论】:

  • HEAD~HEAD^ 是等价的。
  • 它真的不起作用,因为当我结帐到 b-1(例如 72abfd4)时,我看到基于分支-b 的历史记录看起来像坏了
  • @Jubobs 那是因为 HEAD~ 总是跟随第一个父链,而 HEAD^ 只是默认它。 HEAD~7 和 HEAD^7 不等价。
  • 不,^^^是^的默认follow-first-parent的三个应用。 ^3 是一个明确的跟随第三父母。
  • Andrey,然后尝试重置为 master-stable 的哈希,然后从您的开发人员那里挑选所有提交。
猜你喜欢
  • 1970-01-01
  • 2011-02-27
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
  • 2012-06-27
  • 2021-12-07
  • 1970-01-01
相关资源
最近更新 更多