我在使用--keep-empty
的{{1}}选项时遇到了一些问题,而且我很陌生
不确定我是否误解了这个选项的作用,或者是否存在错误。
这是一个最小的例子:
创建一个新的Git存储库和一个初始的,无关的提交。
git rebase
创建一个新的提交,添加两个新文件。
$ git init
$ echo something >base.txt
$ git add base.txt
$ git commit -m 'some base commit to not run into the root corner case'
修改其中一个文件。
$ echo A >a.txt; echo B >b.txt
$ git add a.txt b.txt
$ git commit -m 'add A and B'
修改其他文件。
$ echo A1 >a.txt
$ git add a.txt
$ git commit -m 'change A'
$ echo B1 >b.txt
$ git add b.txt
$ git commit -m 'change B'
...选择$ git checkout -b rebased master
$ git rebase --keep-empty -i :/base
添加edit
和A
的提交,并更改它以便仅添加B
(在实际情况中,原因可能是B
是机密的):
A
当然,现在修改$ git rm a.txt
$ git commit --amend
$ git rebase --continue
的下一次提交会产生冲突:
A
...选择不添加error: could not apply 182aaa1... change A
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
Could not apply 182aaa1701ad100fc02a5d5500cacebdd317a24b... change A
的修改版本:
a.txt
修改$ git mergetool
Merging:
a.txt
Deleted merge conflict for 'a.txt':
{local}: deleted
{remote}: modified file
Use (m)odified or (d)eleted file, or (a)bort? d
的提交现在为空:
A
......并完成了变革:
$ git diff --cached
# nothing
所以现在我的历史记录有两个版本,区别在于其中一个版本中没有$ git rebase --continue
Successfully rebased and updated refs/heads/rebased.
的痕迹。但是,因为我选择了A
选项,我仍然期望--keep-empty
中存在空提交,这会告诉我rebased
会被修改,如果它存在的话。
但显然情况并非如此:
A
这不是$ git log --oneline master
f893569 change B
182aaa1 change A
3340b71 add A and B
38cb5da some base commit to not run into the root corner case
$ git log --oneline rebased
73a2c05 change B
55f502b add A and B
38cb5da some base commit to not run into the root corner case
应该做的,或者它不起作用
正确?
相关:Rebase on the root and keep empty commits是一个非常相似的问题,但它涉及我在这里明确避免的--keep-empty
极端情况。它没有答案,只有一些评论表明我在这里展示的内容应该有效。另一个区别是,在另一个问题中,提交首先是空的,而在解决冲突后它只会变空。
答案 0 :(得分:5)
这是一种错误,因为某种功能。 : - )
当您运行交互式rebase并且它“暂停”时,实际上它完成,但是留下一些文件让 new git rebase
意识到毕竟,它更像是一种延续。这样就好了;你需要稍后运行git rebase --continue
来开始一个新的rebase并告诉它:你不是真的很新,去阅读状态并表现得就像你继续原来的rebase。 < / p>
而且,让我们来看看“互动式反思”。实际上,这主要是一系列的挑选操作:pick
命令逐字地指示旧的rebase shell脚本 - 现在正逐步淘汰 - 运行git cherry-pick
。
您标记了提交“编辑”。它实际上提交了樱桃选择,并停止让你修改提交或以其他方式大惊小怪。
或者,有一个问题 - 例如合并冲突 - 迫使停止。
如果是(1),当你运行git rebase --continue
时,Git应该不进行自己的提交。
在情况(2)中,当您运行git rebase --continue
时,Git 应该进行自己的提交。也就是说,它应该除非 - 这是功能部分 - 您首先进行自己的提交。在这种情况下,对于case(2),Git应该不进行自己的提交。
Git可以,也许应该,记录停止的原因,以便将这两种情况分开......但事实并非如此。相反,它只是查看--continue
上的状态。
对于非 - 交互式rebase,Git知道它只会在冲突时停止,因此它知道尝试进行提交,并且如果没有提交则会抱怨。这是--keep-empty
或-k
标志有用的地方。 (在内部,非交互式案例默认使用git format-patch
和git am
,但您可以强制它使用带--preserve-merges
的交互式机制。我在这里提到它,因为它是< em>实现原因 Git必须知道你是否是“互动的”:正如经常发生的那样,Git让实现决定了行为。如果Git不需要这种区别,那么{{1}可以只使用相同的代码进行交互式和非交互式rebase,但Git 需要区分,因此不使用相同的代码。)
但是,对于交互式rebase,Git 允许在运行--continue
之前(例如,功能部分)在情况(2)中进行自己的提交。如果是这样,git rebase --continue
步骤应该继续进行下一次提交。所以--continue
只是检查是否有东西要提交,而不是早期的交互式rebase是否退出case(1)vs case(2)。这个简单的实现技巧支持该功能,但也意味着--continue
无法在这里工作:Git只是不知道其中的区别。
解决方法是在解决合并后执行自己的--keep-empty
。换句话说,使用“您可以自己提交”功能将case(2)转换为模拟案例(1)。
答案 1 :(得分:4)
但是,因为我选择了
--keep-empty
选项,我仍然期望在rebased中存在空提交,这会告诉我A会被修改,如果它已经存在。但显然情况并非如此:
仔细检查Git 2.18(2018年第二季度),如果另一方包含空提交(由于“git rebase --keep-empty
”检查,“does an equivalent patch exist already?
”仍然删除空提交, 已更正。
commit 3d94616见commit 76ea235,commit bb2ac4f,Phillip Wood (phillipwood
)(2018年3月20日)。
(Junio C Hamano -- gitster
--合并于commit d892bee,2018年4月25日)
rebase -i --keep-empty
:不修剪空提交如果
$upstream...HEAD
左侧有空提交,则我们要保留的右侧空提交将被--cherry-pick
修剪。
通过使用--cherry-mark
代替--cherry-pick
并保持空的提交或未标记为樱桃选择来解决此问题。
和
rebase --keep-empty
:始终使用交互式rebase
rebase --merge
接受--keep-empty
,但只是忽略它,使用
隐式交互式rebase用户仍然可以进行重命名检测
基于合并的rebase但具有--keep-empty
支持。
如果没有
--keep-empty
或--interactive
的rebase--merge
停止 用户解决合并冲突,然后“git rebase --continue
”将 失败。这是因为它使用了不同的代码路径 创建$git_dir/rebase-apply
。
由于rebase --keep-empty
是使用cherry-pick
实现的,因此它从未支持am选项,现在交互式rebase支持--signoff
,使用隐式交互式rebase不会丢失任何功能。
注意:这是Git 2.18中添加到git rebase
的更大功能的一部分:
请参阅“What exactly does Git's “rebase --preserve-merges
” do (and why?)”
使用git --rebase-merges
(最终将替换旧的git --preserve-merges
),您现在可以在其他地方重新定义提交图的整个拓扑。
答案 2 :(得分:0)
我也遇到了这个问题。
当我使用cmd“git rebase -i --root --keep-empty” 没有提交“3fd2d95 - init empty commit”
所以我强行在第一行插入一行“pick 3fd2d95 init empty commit”。