git 变基,重复提交
git rebase, commits repeating
我正在处理我的存储库的另一个分支,需要从 master 分支引入更改。我习惯于 git rebase master
,一切正常。然而,在最近的几个项目中,我看到日志中重复提交,并且变基往往会抱怨(大声):
$ git log --graph --abbrev-commit --decorate ...
* 4988d49 - (2 hours ago) Merge branch 'branchname' of ... 3
|\
| * e979be1 - (2 days ago) change verbiage 10
| * 93a1c80 - (2 days ago) Merge branch 'branchname' of ... 2
| |\
| | * 4e4e790 - (2 weeks ago) Merge branch 'branchname' of ... 1
| | |\
| | | * 87cc232 - (8 weeks ago) change verbiage 3
| | | * 3d5cf09 - (8 weeks ago) change verbiage 2
| | | * aea4cbd - (9 weeks ago) change verbiage 1
| | * | a7043ef - (2 weeks ago) change verbiage 6
| | * | fa3413b - (2 weeks ago) change verbiage 5
| | * | be038a7 - (2 weeks ago) change verbiage 4
| | * | 37cb1e6 - (8 weeks ago) change verbiage 3
| | * | 1ab71c6 - (8 weeks ago) change verbiage 2
| | * | c4560f4 - (9 weeks ago) change verbiage 1
| * | | d3211fd - (2 weeks ago) change verbiage 6
| * | | 72a2a4a - (2 weeks ago) change verbiage 5
| * | | ae1c123 - (2 weeks ago) change verbiage 4
| * | | 8328c08 - (8 weeks ago) change verbiage 3
| * | | e52588f - (8 weeks ago) change verbiage 2
| * | | 114cbec - (9 weeks ago) change verbiage 1
* | | | 38bd6ce - (2 hours ago) change verbiage 9
* | | | 5aaf360 - (2 hours ago) change verbiage 8
* | | | 2745790 - (2 days ago) change verbiage 7
* | | | 7bb613f - (2 weeks ago) change verbiage 6
* | | | 726a312 - (2 weeks ago) change verbiage 5
* | | | 771dd7f - (2 weeks ago) change verbiage 4
* | | | b451926 - (8 weeks ago) change verbiage 3
* | | | 484d5dc - (8 weeks ago) change verbiage 2
* | | | 630df34 - (9 weeks ago) change verbiage 1
(为简单起见,我更改了提交消息。这里实际上只显示了一个分支,尽管有四个 "pipe lines"。)我对这个项目做了一些 rebase,我认为它们可以相当简单地根据(比如)更改措辞 1.
的重复次数来追踪
我以为我正在通过变基合并来对项目工作流程做 "best practices" 事情。我认为至少有一个以前的变基是用 -no-ff
完成的,但我看不出行为有什么不同。
重放提交时,它们会发生冲突(显然,将一个提交放在其自身之上是有问题的),因此我不得不进行交互式变基,删除所有重复的提交。
无法访问存储库本身,这是我工作流程的问题吗?是不是说明分支还有其他问题?
为什么?
看起来您使用 rebase 修改了旧提交,另一个分支也已经指向了。所以发生的事情是:
你有一个看起来像这样的狗:
* abc123 (master) Most recent commit
|
| * f00ba12 (foo, HEAD) Some feature you're working on
| |
|/
* 192837 Fix the things
|
* 348cc87 Remove Peter's garbage code
|
* 000a0a WOOOORRRDDDDDSSSS
所以您目前正在 foo
做一些事情,但您意识到您仍然遗留了一些 Peter 的垃圾代码并想将其删除。作为优秀的程序员,您希望这些更改与其他更改一起提交 348cc87
。所以你做了一个变基以回到那个点并修改更改。
这看起来不错吧?问题是,您已经更改了 348cc87
,所以它不再是 348cc87
。现在是 111222
,因为请记住,提交哈希值是根据项目的树计算的,等等。其中之一是父提交哈希 (000a0a
)。因此,由于 348cc87
现在是 111222
,“192837”被重新计算为 999999
,并且 f00ba12
更改为 ba12f00
。所以现在你的 HEAD 日志看起来像
* ba12f00 (foo, HEAD) Some feature you're working on
|
|
* 999999 Fix the things
|
* 111222 Remove Peter's garbage code
|
* 000a0a WOOOORRRDDDDDSSSS
这成为一个问题,因为 abc123
仍然指向 192837
,这是有效的,因为提交对象 192837
仍然存在于 git.这是因为从 git 的角度来看 192837
和 abc123
是截然不同的提交,只是碰巧有相同的日志消息。
现在你的 git dag 看起来像:
* abc123 (master) Most recent commit
|
| * f00ba12 (foo, HEAD) Some feature you're working on
| |
| * 999999 Fix the things
* | 192837 Fix the things
| |
| * 111222 Remove Peter's garbage code
* | 348cc87 Remove Peter's garbage code
|/
* 000a0a WOOOORRRDDDDDSSSS
现在,当您完成 foo
分支的工作并准备合并时,您将获得
* 5f93da (master) Merge 'foo' into 'master'
|\
* | abc123 Most recent commit
| |
| * f00ba12 (foo, HEAD) Some feature you're working on
| |
| * 999999 Fix the things
* | 192837 Fix the things
| |
| * 111222 Remove Peter's garbage code
* | 348cc87 Remove Peter's garbage code
|/
* 000a0a WOOOORRRDDDDDSSSS
经常这样做,你最终会陷入目前的境地。
但是凯尔,我该如何解决这个问题??抓紧你的马 r2evans,我到那儿了。
如何修复
有几种方法可以解决这个问题,我所知道的所有方法在特定情况下都会稍微复杂一些。
你可以把很多东西压在一起,这样提交就更少了,但是你会失去一些历史,我不喜欢这样。
你可以做更多的变基魔术来改变你的 'abc123' 提交,让更新的 999999
提交作为它的父提交。您可以为此使用 --onto 参数。根据这种情况下的提交数量,这可能具有挑战性。
你可以保持原样。只要大师的提示处于正确状态,这并不可怕,但回顾你的历史非常困难。
这是个问题吗?
是的。这看起来像是您的工作流程有问题。出于这个原因,编辑历史往往不是一个好主意,您通常应该避免它。
对我来说,master
跟踪什么是 public。我和我的队友都是根据这些代码进行更改的。我从不修改 master 中的提交。首先,因为我们的内部 git 回购不允许我推送这样的更改(即使使用 --force),其次,因为这会弄乱我队友的代码(并把他们放到你的位置)。
我为特定功能创建了 master
的功能分支,因此我将有分支 foo
、bar
、fizz
和 buzz
分开主分支,而不是彼此分开。这让我可以独立地处理每一个。我通常不会从功能分支分支出来,但是当我这样做时,我通常不会对提交历史进行任何编辑。那是因为我通常会在合并之前清理分支,所以我不需要。
我正在处理我的存储库的另一个分支,需要从 master 分支引入更改。我习惯于 git rebase master
,一切正常。然而,在最近的几个项目中,我看到日志中重复提交,并且变基往往会抱怨(大声):
$ git log --graph --abbrev-commit --decorate ...
* 4988d49 - (2 hours ago) Merge branch 'branchname' of ... 3
|\
| * e979be1 - (2 days ago) change verbiage 10
| * 93a1c80 - (2 days ago) Merge branch 'branchname' of ... 2
| |\
| | * 4e4e790 - (2 weeks ago) Merge branch 'branchname' of ... 1
| | |\
| | | * 87cc232 - (8 weeks ago) change verbiage 3
| | | * 3d5cf09 - (8 weeks ago) change verbiage 2
| | | * aea4cbd - (9 weeks ago) change verbiage 1
| | * | a7043ef - (2 weeks ago) change verbiage 6
| | * | fa3413b - (2 weeks ago) change verbiage 5
| | * | be038a7 - (2 weeks ago) change verbiage 4
| | * | 37cb1e6 - (8 weeks ago) change verbiage 3
| | * | 1ab71c6 - (8 weeks ago) change verbiage 2
| | * | c4560f4 - (9 weeks ago) change verbiage 1
| * | | d3211fd - (2 weeks ago) change verbiage 6
| * | | 72a2a4a - (2 weeks ago) change verbiage 5
| * | | ae1c123 - (2 weeks ago) change verbiage 4
| * | | 8328c08 - (8 weeks ago) change verbiage 3
| * | | e52588f - (8 weeks ago) change verbiage 2
| * | | 114cbec - (9 weeks ago) change verbiage 1
* | | | 38bd6ce - (2 hours ago) change verbiage 9
* | | | 5aaf360 - (2 hours ago) change verbiage 8
* | | | 2745790 - (2 days ago) change verbiage 7
* | | | 7bb613f - (2 weeks ago) change verbiage 6
* | | | 726a312 - (2 weeks ago) change verbiage 5
* | | | 771dd7f - (2 weeks ago) change verbiage 4
* | | | b451926 - (8 weeks ago) change verbiage 3
* | | | 484d5dc - (8 weeks ago) change verbiage 2
* | | | 630df34 - (9 weeks ago) change verbiage 1
(为简单起见,我更改了提交消息。这里实际上只显示了一个分支,尽管有四个 "pipe lines"。)我对这个项目做了一些 rebase,我认为它们可以相当简单地根据(比如)更改措辞 1.
的重复次数来追踪我以为我正在通过变基合并来对项目工作流程做 "best practices" 事情。我认为至少有一个以前的变基是用 -no-ff
完成的,但我看不出行为有什么不同。
重放提交时,它们会发生冲突(显然,将一个提交放在其自身之上是有问题的),因此我不得不进行交互式变基,删除所有重复的提交。
无法访问存储库本身,这是我工作流程的问题吗?是不是说明分支还有其他问题?
为什么?
看起来您使用 rebase 修改了旧提交,另一个分支也已经指向了。所以发生的事情是:
你有一个看起来像这样的狗:
* abc123 (master) Most recent commit
|
| * f00ba12 (foo, HEAD) Some feature you're working on
| |
|/
* 192837 Fix the things
|
* 348cc87 Remove Peter's garbage code
|
* 000a0a WOOOORRRDDDDDSSSS
所以您目前正在 foo
做一些事情,但您意识到您仍然遗留了一些 Peter 的垃圾代码并想将其删除。作为优秀的程序员,您希望这些更改与其他更改一起提交 348cc87
。所以你做了一个变基以回到那个点并修改更改。
这看起来不错吧?问题是,您已经更改了 348cc87
,所以它不再是 348cc87
。现在是 111222
,因为请记住,提交哈希值是根据项目的树计算的,等等。其中之一是父提交哈希 (000a0a
)。因此,由于 348cc87
现在是 111222
,“192837”被重新计算为 999999
,并且 f00ba12
更改为 ba12f00
。所以现在你的 HEAD 日志看起来像
* ba12f00 (foo, HEAD) Some feature you're working on
|
|
* 999999 Fix the things
|
* 111222 Remove Peter's garbage code
|
* 000a0a WOOOORRRDDDDDSSSS
这成为一个问题,因为 abc123
仍然指向 192837
,这是有效的,因为提交对象 192837
仍然存在于 git.这是因为从 git 的角度来看 192837
和 abc123
是截然不同的提交,只是碰巧有相同的日志消息。
现在你的 git dag 看起来像:
* abc123 (master) Most recent commit
|
| * f00ba12 (foo, HEAD) Some feature you're working on
| |
| * 999999 Fix the things
* | 192837 Fix the things
| |
| * 111222 Remove Peter's garbage code
* | 348cc87 Remove Peter's garbage code
|/
* 000a0a WOOOORRRDDDDDSSSS
现在,当您完成 foo
分支的工作并准备合并时,您将获得
* 5f93da (master) Merge 'foo' into 'master'
|\
* | abc123 Most recent commit
| |
| * f00ba12 (foo, HEAD) Some feature you're working on
| |
| * 999999 Fix the things
* | 192837 Fix the things
| |
| * 111222 Remove Peter's garbage code
* | 348cc87 Remove Peter's garbage code
|/
* 000a0a WOOOORRRDDDDDSSSS
经常这样做,你最终会陷入目前的境地。
但是凯尔,我该如何解决这个问题??抓紧你的马 r2evans,我到那儿了。
如何修复
有几种方法可以解决这个问题,我所知道的所有方法在特定情况下都会稍微复杂一些。
你可以把很多东西压在一起,这样提交就更少了,但是你会失去一些历史,我不喜欢这样。
你可以做更多的变基魔术来改变你的 'abc123' 提交,让更新的
999999
提交作为它的父提交。您可以为此使用 --onto 参数。根据这种情况下的提交数量,这可能具有挑战性。你可以保持原样。只要大师的提示处于正确状态,这并不可怕,但回顾你的历史非常困难。
这是个问题吗?
是的。这看起来像是您的工作流程有问题。出于这个原因,编辑历史往往不是一个好主意,您通常应该避免它。
对我来说,master
跟踪什么是 public。我和我的队友都是根据这些代码进行更改的。我从不修改 master 中的提交。首先,因为我们的内部 git 回购不允许我推送这样的更改(即使使用 --force),其次,因为这会弄乱我队友的代码(并把他们放到你的位置)。
我为特定功能创建了 master
的功能分支,因此我将有分支 foo
、bar
、fizz
和 buzz
分开主分支,而不是彼此分开。这让我可以独立地处理每一个。我通常不会从功能分支分支出来,但是当我这样做时,我通常不会对提交历史进行任何编辑。那是因为我通常会在合并之前清理分支,所以我不需要。