对于 Git 2.6+(发布于2015年9月28日)
唯一有用的git config
设置是:
rebase.autostash
(with Git 2.27, Q2 2020,现在您还可以使用
merge.autostash
,请见下文)
当设置为true时,在操作开始前自动创建一个临时存储区,并在操作结束后应用它。这意味着您可以在脏工作树上运行rebase。
但是,请谨慎使用:成功完成rebase后最终的stash应用可能会导致非常复杂的冲突。默认值为false。
结合以下内容:
pull.rebase
当为真时,在运行“git pull”时,将分支变基到获取的分支之上,而不是合并默认远程存储库中的默认分支。
在给定的存储库中:
git config pull.rebase true
git config rebase.autoStash true
这对于在一个脏树中进行简单的 git pull
工作来说已经足够了。
在这种情况下不需要别名。
请查看提交53c76dc(2015年7月4日)由Kevin Daudt (Ikke
)提交。
(合并于提交e69b408,由Junio C Hamano -- gitster
--在2015年8月17日完成)
pull
:启用rebase.autostash
时允许脏树
当rebase遇到一个脏工作树时,它学会了储藏更改,但是
git pull --rebase
没有。只有在未启用
rebase.autostash
时才验证工作树是否脏。
注意:如果您想在不使用自动存储(即使设置了
rebase.autoStash true
)的情况下进行拉取操作,则自git 2.9(2016年6月)以来可以这样做:
pull --rebase --no-autostash
请参见
提交 450dd1d,
提交 1662297,
提交 44a59ff,
提交 5c82bcd,
提交 6ddc97c,
提交 eff960b,
提交 efa195d (2016年4月2日),以及
提交 f66398e,
提交 c48d73b (2016年3月21日) ,作者为
Mehul Jain (mehul2029
)。
(由 Junio C Hamano -- gitster
-- 合并于 提交 7c137bb,2016年4月13日)
提交 f66398e 特别包括:
pull --rebase
: 添加 --[no-]autostash
标志
如果设置了 rebase.autoStash
配置变量,则无法通过命令行为 "git pull --rebase
" 覆盖它。
教会 "git pull --rebase
" 命令行标志 --[no-]autostash
,如果设置,则覆盖当前值 rebase.autoStash
。由于 "git rebase
" 理解 --[no-]autostash
选项,所以只需要在调用 "git pull --rebase
" 时将该选项传递给底层的 "git rebase
"。
警告:在Git 2.14之前(2017年第三季度),"git pull --rebase --autostash
"当本地历史记录快进到上游时不会自动存储。
请参见提交f15e7cf(由Tyler Brazier (tylerbrazier
)于2017年6月1日提交)。
(由Junio C Hamano -- gitster
--合并于提交35898ea,2017年6月5日)
pull
:ff --rebase --autostash
在脏仓库中工作
当在一个脏的代码库中使用
git pull --rebase --autostash
命令时,如果结果是快进(fast-forward),则自动存储(autostash)不会被执行,导致拉取失败。
这是因为我们避免运行变基(rebase)的快捷方式,但是在该代码路径上忽略了自动存储(autostash)。
更新:Mariusz Pawelski 在评论中提出了一个有趣的问题:
所以当你使用rebase(或pull --rebase
)时,每个人都在写有关autostash
的文章。
但是当您进行带有合并的普通拉取时,没有人谈论自动存储。
那么这方面没有自动切换吗?还是我漏掉了什么?我更喜欢执行git pull --rebase
,但OP问的是“标准”git pull
回答:
讨论此autostash功能的原始线程最初实现了git pull
(合并)和git pull --rebase
。
但是... Git维护者Junio C Hamano指出:
如果“pull-merge”是会引发触发此主题的“烦恼”的东西,根据定义,本地更改与合并重叠,并且此内部“stash pop”将触及合并触及的路径,并且可能不会导致“已删除”,而是留下进一步需要解决的冲突。
我怀疑“pull.autostash”配置不是一个好的添加,因为它鼓励了一种糟糕的、令人痛苦的工作流程。
在简单情况下,它可能不会有影响,但当本地更改很复杂时,它会积极伤害而不是没有它,并且该配置剥夺了选择的动力。
对于“pull-rebase”,方程式有所不同,因为“rebase”坚持从干净的工作树开始,因此“下载然后停止”的烦恼感更大。我怀疑放松可能是解决实际问题的更有效的方法。
因此,关于经典的pull-merge,最好是:
在运行“
git pull
”之前,鼓励用户考虑工作树中WIP的性质。它是一个过于复杂的怪物,可能会干扰其他人正在做的事情,还是一个微不足道的更改,可以将其藏起来并弹出来?
如果是前者,他最好使用“
checkout -b
”,继续工作,直到本地更改变得更好,然后进行“提交”,再合并到原始分支。
如果是后者,他最好执行以下操作:
- “
git pull
”
- 找到冲突后,运行
git stash
,
git merge FETCH_HEAD
和
git stash pop
在Git 2.27(2020年第二季度)中,"
git pull
"学会了在不存在
pull.rebase
配置且没有给出
--[no-]rebase
或
--ff-only
(这将导致合并)时发出警告。请参见
提交d18c950(由
Alex Henrie (alexhenrie
)于2020年3月10日提交)。
(由Junio C Hamano -- gitster
--于2020年3月27日合并到提交1c56d6f)
pull
: 如果用户没有说明是rebase还是merge,则发出警告
签名:Alex Henrie
通常,新手Git用户会忘记使用“
pull --rebase
”,最终会从上游合并不必要的内容。他们通常想要的是在简单情况下使用“
pull --rebase
”,或者使用“
pull --ff-only
”更新主集成分支的副本,并单独对其工作进行变基。虽然
pull.rebase
配置变量可以帮助他们解决简单的情况,但没有机制让这些用户意识到它的存在。当命令行中没有
--[no-]rebase
选项和
pull.rebase
配置变量时,发出警告消息。这将给那些从不想“
pull --rebase
”的人带来不便,但这种不便只需每个用户支付一次,这应该是帮助许多新用户的合理代价。
使用 Git 2.27 (2020 年第二季度),“
git merge
” 学会了 “
--autostash
” 选项,并且新增了
merge.autostash
设置。
请参见 提交 d9f15d3, 提交 f8a1785, 提交 a03b555, 提交 804fe31, 提交 12b6e13, 提交 0dd562e, 提交 0816f1d, 提交 9bb3dea, 提交 4d4bc15, 提交 b309a97, 提交 f213f06, 提交 86ed00a, 提交 facca7f, 提交 be1bb60, 提交 efcf6cf, 提交 c20de8b, 提交 bfa50c2, 提交 3442c3d, 提交 5b2f6d9 (于2020年4月7日), 提交 65c425a (于2020年4月4日), 以及 提交 fd6852c, 提交 805d9ea (于2020年3月21日),这些提交是由Denton Liu (Denton-L
)执行的。
(由Junio C Hamano -- gitster
合并于 提交 bf10200, 2020年4月29日)
pull
: 传递 --autostash 给合并操作
签署者: Denton Liu
之前,--autostash
只能与 git pull --rebase
操作一起使用。
然而,在最新的补丁中,合并操作也学会了使用 --autostash
,因此我们没有理由再限制其使用了。
让 pull 操作像 rebase 操作一样将 --autostash
参数传递给合并操作。
rebase
: 使用 sequencer.c 中的 apply_autostash() 函数
签署者: Denton Liu
apply_autostash()
函数在builtin/rebase.c
中,与sequencer.c
中的apply_autostash()
函数非常相似,除了它们接受的arg类型不同。将sequencer.c
版本设置为extern,并在rebase中使用它。
rebase版本是在6defce2b02("内置rebase:支持--autostash
选项",2018-09-04,Git v2.20.0-rc0 - 合并列在batch #8中)中作为shell转换为C的一部分引入的。
它选择复制该函数,因为当时还有另一个正在进行的项目将交互式rebase从shell转换为C,他们不想通过重构apply_autostash()
的sequencer.c
版本来与该项目发生冲突。
由于两个项目都已完成,现在我们可以自由地将它们结合在一起。
随着Git 2.30(2021年第一季度)的发布,用户界面得到了改进:
请参见提交 e01ae2a(由Johannes Schindelin (dscho
)于2020年11月19日提交)。
(由Junio C Hamano -- gitster
--合并于提交 290c940,2020年11月30日)
pull
: 为设置 pull.rebase
的提示添加着色
指出者:Ævar Arnfjörð Bjarmason
签署者:Johannes Schindelin
在
d18c950a69f ("
pull
: warn if the user didn't say whether to rebase or to merge", 2020-03-09, Git v2.27.0-rc0 --
merge listed in
batch #2) 中,引入了一个新的提示来鼓励用户通过配置
pull.rebase
设置,有意识地决定他们想要将其拉取合并还是变基。
这个警告显然旨在为用户提供建议,但正如
this thread中指出的那样,它使用了
warning()
而不是
advise()
。
其中一个后果是建议没有像其他类似消息一样着色。
因此,让我们改用
advise()
。
随着 Git 2.33 (Q3 2021) 的到来,git pull --rebase
得到了简化:
请看 提交记录 a7d18a1, 提交记录 a751e02, 提交记录 3400622 (2021年6月17日) 由 Felipe Contreras (felipec
) 提交。
(由 Junio C Hamano -- gitster
-- 在 提交记录 221ec24 中合并, 2021年7月8日)
拉取
:清理自动存储检查
Signed-off-by: Felipe Contreras
目前 "
git pull --rebase
"
(man) 在可以进行快进合并的情况下采取了捷径;
run_merge()
被调用时使用了 --ff-only。
然而,"
git merge
"
(man) 没有
--autostash
选项,所以当 "
git
pull --rebase
--autostash``"
(man) 被调用时,并且采取了快进合并捷径,则拉取失败。
这在
commit f15e7cf ("
pull
: ff
--rebase
--autostash works in dirty repo", 2017-06-01, Git v2.14.0-rc0 --
merge listed in
batch #7) 中得到修复,方法是简单地跳过快进合并捷径。
后来 "
git merge
" 学会了
--autostash
选项 [
a03b555 ("
merge
: teach
--autostash
option", 2020-04-07, Git v2.27.0-rc0 --
merge listed in
batch #5)],因此 "
git pull
"
(man) 也学会了 [
d9f15d3 ("
pull
: pass
--autostash
to merge", 2020-04-07, Git v2.27.0-rc0 --
merge listed in
batch #5)]。
因此,在使用
--rebase --autostash
调用时,不再需要跳过快进合并捷径。
让我们始终采取快进合并捷径,实质上是撤销
f15e7cf。
"git merge --autostash
"(man)创建的自动暂存的本地更改被混合到了工作树中留下的冲突状态中,这个问题已经在Git 2.38(2022年第三季度)中得到了解决。
请查看提交d3a9295(2022年8月23日)由Elijah Newren (newren
)提交。
(由Junio C Hamano -- gitster
--于提交3a47790中合并,2022年9月1日)
merge
:仅在适当时应用自动存储
签署者:Elijah Newren
如果合并失败,我们会将冲突留在工作目录中供用户解决,此时不应尝试应用任何自动存储。另外,如果我们未能应用自动存储(因为合并失败或用户请求了
--no-commit
),那么我们应该告诉用户如何稍后应用它。添加一个测试用例以验证我们已经纠正了这个行为。
新指令:
完成后,请使用
git stash pop
应用存储的更改。
git stash; git pull; git stash pop
是危险的,因为如果没有需要暂存的内容,git stash
将无法执行任何操作,但是git stash pop
会弹出最后一个暂存(如果有的话),这几乎肯定 不 是您想要的。用户 torek 在 Stack Overflow 上发表了一篇很棒的帖子,但我找不到它... - jub0bs