我正在清理git仓库,以便更容易理解。到目前为止,它一直是私人的,所以我可以改变历史。
大多数情况下,我一直在将承诺压缩成有意义的集合。
问题在于,该项目在其历史早期是另外两个项目的合并。我在解压合并之前的提交时遇到了麻烦。
我的问题是:我该怎么做?
具体:我有
xxxxxx * master: Latest commit
xxxxxx * another commit
xxxxxx * Merge projectA and projectB
xxxxxx |\
0000A6 | * a minor commit in project A
0000A5 | * another minor commit
我想将0000A5和0000A6压制在一起。
当我尝试使用交互式rebase时,magit(我恰好使用的git的emacs前端)警告我"尽管在rebase范围内合并,仍继续进行?"当我继续时,它失败了以下(取自我的实际工作,而不是上面的简化例子)。我不确定在合并之前是否存在重新定位提交的问题,或其他内容("未跟踪的文件"行是可疑的,因为合并包括将客户端项目移动到& #34; client /"更大项目的子目录。
Last commands done (5 commands done):
pick fb5de84 Simplified schema:
squash 96ac7ac Revert schema to full complexity
Next commands to do (29 remaining commands):
pick 4ad389a Just indentation, for readability
pick 4241835 First pass at schema
You are currently editing a commit while rebasing branch 'master' on 'ad91ab4'.
Untracked files:
client/
No changes
You asked to amend the most recent commit, but doing so would make
it empty. You can repeat your command with --allow-empty, or you can
remove the commit entirely with "git reset HEAD^".
Could not apply 96ac7ac7753c03e83b8c1296d892ce9c5fea44c7... Revert schema to full complexity
答案 0 :(得分:2)
这似乎有几件事情在这里发生。我不熟悉您正在使用的前端,但看起来它正在尝试自动化rebase,并且如果暂停通常需要手动干预,则会挽救它不知道如何修复。
虽然通过合并进行调整可能很棘手,但我认为这与目前的问题无关。在我看来,96ac7ac只是fb5de84的一个版本,所以当你把它们压在一起时,你会得到一个空的提交。这是允许的,但需要人工干预。 (rebase会停止,你会说git commit --allow-empty
之类的东西,然后继续。)
您可以通过
确认96ac7ac是否真的是完美的还原git diff 96ac7ac fb5de84^
如果是,并且如果你的前端无法满足rebase所需的干预,那么你可以放弃这两个提交,而不是压缩它们。
您可能遇到的下一件事是,除非您提供--preserve-merges
选项,否则rebase将尝试使历史呈线性。我认为这是你的前端警告你的内容,一旦你告诉它继续,我不知道它是否通过了这个选项。
即使使用正确的选项,通过合并进行变基的问题在于,原始合并中的任何工作都会超出默认自动分辨率。如果需要手动解决冲突,那么git将再次停止并期望您执行解决方案(您的前端可能不会与之合作)。此外,如果自动解析成功并且合并包含手动应用的更改(幸运的是罕见但不是不可能),则更改可能会无声地丢失。
另一种选择是"解决问题"合并(如果没有太多的话)。如果你有
X --- A --- B --- M --- C <--(master)
\ /
D --- E --- F
你希望压缩E
和F
,然后你可以先
git checkout F
git checkout -b temp_branch
git rebase -i D
并设置壁球,给你
X --- A --- B --- M --- C <--(master)
\ /
D --- E --- F
\
EF <--(temp_branch)
然后重做合并
git checkout B
git merge temp_branch
在此合并期间,您必须复制原始合并M
中完成的所有工作。如果M
只是自动解析,那么合并(M'
)也是如此。您可以通过
git diff M M`
如果这显示出差异,则您必须手动应用它们(这可能也是M
所发生的情况)。您可以让工作树看起来正确并使用--amend
提交我相信。
当然,如果合并信号冲突,你必须解决它们;再次对M
进行分析应提供良好的指导。
完成后,你有
<*>- M --- C <--(master)
/
X --- A --- B --- M' <--((HEAD))
\ /
D --------- EF <--(temp_branch)
\
E --- F -<*>
(抱歉这个奇怪的符号,图表让我发疯; <*>
s应该是F
到M
的一行。但不要担心,我们即将解开它。)
清理并对合并后提交进行最后的变更:
git branch --delete temp_branch
git rebase --onto M` M master
产生
X --- A --- B --- M' --- C` <--(master)
\ /
D --------- EF
您可以看到这可能非常繁琐,特别是如果有许多合并和/或合并包含手动冲突解决方案或其他非自动更改。验证最终状态是关键。 (您可以使用reflog来帮助解决这个问题,或者在开始所有这些之前标记原始主HEAD。例如使用reflog:
git diff master master@{1}
如果您还想验证每个历史提交,那么这种表示法可能会变得混乱......)
另一种变体是,您可以压缩E
和F
,然后设置git filter-branch
--parent-filter
,而不是重新合并并将合并后的工作重新定位到其上。 1}}从M
重新B , F
到B , EF
。有关如何使用git filter-branch
的详细信息,请参阅--parent-filter
文档(尽管您必须稍微调整示例以处理合并)。这可能有效,因为您特别希望结果具有未更改的树。