“ git pull”可以自动隐藏并弹出未完成的更改吗?


121

我知道如何解决这个问题:

user@host$ git pull
Updating 9386059..6e3ffde
error: Your local changes to the following files would be overwritten by merge:
    foo.bar
Please, commit your changes or stash them before you can merge.
Aborting

但是,是不是有办法让git pullstashpop舞蹈给我吗?

如果此命令使用其他名称,则可以。

为创建外壳别名git stash; git pull; git stash pop是一种解决方案,但我在寻找更好的解决方案。


怎么样一个git的别名?
Яois

20
git stash; git pull; git stash pop编程方式运行是危险的,因为如果没有什么可隐藏的内容,git stash则将无操作,但git stash pop会弹出最后一个包含(如果有的话)的东西,这几乎肯定不是您想要的。用户torek在Stack Overflow上有一篇很好的文章,但是我找不到它……
jub0bs 2015年


1
@guettli我并不是在暗示您的问题是重复的,我只是在回答Jubobs的评论。
VonC 2015年

2
更进一步,仅当在拉动之后可以干净地应用藏物时,操作才能成功。如果存在冲突,则整个操作将自动失败,因此不会更改树。这就是我想做的:要么将更改与本地更改合并在一起,要么失败并显示错误,然后让我手动决定下一步。这种git“交易”可能吗?
Ed Avis

Answers:


184

对于Git 2.6+(2015年9月28日发布)

只要 git config 感兴趣的设置是:

rebase.autoStash

(使用Git 2.27,2020年第二季度,您现在还拥有merge.autostash,请参见下文)

设置为true时,在操作开始之前自动创建一个临时存储,并在操作结束之后应用它。
这意味着您可以在肮脏的工作树上运行rebase。

但是,请谨慎使用:成功重新设置基准之后的最终存储应用程序可能会导致非平凡的冲突。默认为false。

结合使用:

pull.rebase

为true时,在运行“ git pull”时,将分支重新放置在获取的分支之上,而不是从默认远程合并默认分支。

git config pull.rebase true
git config rebase.autoStash true

git pull即使在肮脏的树上,这也足以使简单的工作。
在这种情况下,无需别名。


参见Kevin Daudt()的commit 53c76dc(2015年7月4日(由Junio C Hamano合并--commit e69b408中,2015年8月17日)Ikke
gitster

pullrebase.autostash启用时允许脏树

rebase学会了在遇到肮脏的工作树时隐藏更改,但是git pull --rebase没有。

仅在rebase.autostash未启用时验证工作树是否脏。


注意:如果您想在没有自动存储的情况下进行拉取(即使rebase.autoStash true已设置),则自git 2.9起(2016年6月):

 pull --rebase --no-autostash

请参阅Mehul Jain()的提交450dd1d提交1662297提交44a59ff提交5c82bcd提交6ddc97c提交eff960b提交efa195d提交 2016年4月2日)和提交f66398e提交c48d73b(2016年3月21日(由Junio C Hamano合并--commit 7c137bb中mehul2029
gitster,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 rebase”时将选项传递给底层的“ ”即可git pull --rebase


警告:在Git 2.14(2017年第三季度)之前,git pull --rebase --autostash当本地历史记录快进到上游时,“ ”没有自动隐藏。

参见Tyler Brazier()的commit f15e7cf(2017年6月1日(通过合并JUNIOÇ滨野- -提交35898ea,2017年6月5日)tylerbrazier
gitster

pull:ff --rebase --autostash在肮脏的仓库中工作

git pull --rebase --autostash在肮脏的存储库中导致快进时,没有任何东西被自动保存,并且拉取失败。
这是由于在我们可以快进时避免运行rebase的快捷方式,但是在该代码路径上自动隐藏被忽略了。


更新:马里乌什Pawelski要求在评论一个有趣的问题:

因此,每个人都在写关于autostash何时重新确定(或pull --rebase)的信息。

但是,当您使用合并进行常规拉动时,没有人会考虑自动存储。
所以没有自动开关吗?还是我想念什么?我更喜欢这样做,git pull --rebase但OP询问“ 标准 ” git pull

回答:

讨论此自动隐藏功能的原始线程,最初是针对git pull(merge)和实现的git pull --rebase

但是... Junio C Hamano(Git维护者)指出:

如果根据定义pull-merge,某些更改会引起触发该主题的“烦恼”,则本地更改与合并重叠,并且此内部“隐藏弹出”将触及合并所触摸的路径,并且很可能不会导致“删除” ”,但还有其他冲突有待解决。

我怀疑pull.autostash配置不是很好的补充,因为它会导致不良的,引起痛苦的工作流程。
在简单的情况下,它可能不会受到损害,但是当局部更改复杂时,它会比没有受到损害更为积极,并且配置失去了选择的动力。

对于“ pull-rebase”,方程式有所不同,因为“ rebase”坚持要求您从干净的工作树开始,因此“下载然后停止”烦恼会变得更大。我怀疑松动可能会更有效地解决实际问题。

因此,对于经典的合并,最好:

鼓励用户在运行“ git pull” 之前考虑工作树中WIP的性质
这是太复杂的野兽,可能会干扰其他人在做什么,还是他可以藏起来然后将其弹出来的小改变?

如果是前者,他会做得更好“ checkout -b”,继续工作直到局部变更变得更好并“提交”,然后再拉入原始分支。

如果是后者,他最好这样做:

  • git pull”,
  • 找到冲突后,运行
    • git stash
    • git merge FETCH_HEAD
    • git stash pop

话虽这么说,使用Git 2.27(Q2 2020)“ git pull”学会在没有警告pull.rebase的配置存在,既不--[no-]rebase也没有--ff-only给出(这将导致合并)。

参见Alex Henrie(提交d18c950(2020年3月10日(通过合并JUNIOÇ滨野- -提交1c56d6f 3月27日2020)alexhenrie
gitster

pull:警告用户是否未说要变基还是要合并

签名人: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日),以及fd6852c805d9ea(2020年3月21日)由Denton Liu(Denton-L提交
(通过合并JUNIOÇ滨野- gitster-提交bf10200 4月29日2020)

pull:通过--autostash合并

签字人:刘丹顿

之前,--autostash仅与合作git pull --rebase

但是,在最后一个补丁中,--autostash也要合并学习到的内容,因此没有理由再要限制此了。
教拉动传递--autostash以进行合并,就像重新设定基准一样。

和:

rebaseapply_autostash()从sequencer.c 使用

签字人:刘丹顿

apply_autostash()函数builtin/rebase.c是足够相似的apply_autostash()在功能上sequencer.c,他们是可以互换的,除了ARG的他们接受的类型。使sequencer.c版本为extern,并在变基中使用它。

rebase版本是在6defce2b02中引入的(“内建的rebase:支持--autostash选项”,2018-09-04,Git v2.20.0-rc0- 在批处理#8中合并),作为将Shell转换为C的一部分。 之所以选择复制该功能,是因为当时还有另一个正在进行的项目,也将交互式rebase也从shell转换为C,并且他们不想通过重构版本与它们冲突。 由于这两项工作都是长期的工作,因此我们现在可以将它们自由地组合在一起。
sequencer.capply_autostash()


从2.4.2版开始,此功能尚未实现。也许有一天。 rebase.autoStash仅在使用rebase时适用。 pull.rebase仅在使用拉动时适用。
Randal Schwartz

“即使在肮脏的树上,这也足以使简单的git pull起作用。” 正如Randal所说,这还不是真的。当前主机的pull.c仍然选择die_on_unclean_work_tree
2015年

1
@普拉汉我同意。该实现今天早上才刚刚掌握,应该在git 2.6上可用。我已经对答案进行了编辑以使其更清楚。
VonC

我已经确认autostash与git一起使用2.5.5
约书亚·霍布利特

1
因此,每个人在做rebase(或pull --rebase)时都在写有关自动存储的文章。但是,当您对pull合并进行正常处理时,没有人会考虑自动存储。所以没有自动开关吗?还是我想念什么?我更喜欢这样做,git pull --rebase但OP询问“标准”问题git pull
Mariusz Pawelski

41

为了为即将到来的浏览器节省几秒钟的时间,以下是摘要(感谢@VonC):

git pull --rebase --autostash

6
关键是:在git config pull.rebase true和之后 git config rebase.autoStash true,您只需要git pull。只是git pull。不需要其他选项。
VonC

3
看来您至少需要Git 2.9才能使用--autostash。从-c rebase.autoStash=trueGit 2.6起开始工作。
ntc2

15

如上面的注释所述,设置两个配置值当前不适用于git pull,因为autostash配置仅适用于实际的基准。这些git命令可以满足您的要求:

git fetch
git rebase --autostash FETCH_HEAD

或将其设置为别名:

git config alias.pullr '!git fetch; git rebase --autostash FETCH_HEAD'

然后做:

git pullr

当然,该别名可以根据需要重命名。


7

使用Git 2.6+,您可以使用以下功能:

alias gup='git -c rebase.autoStash=true pull --rebase'

--rebase使得使用git-pull rebase代替merge,因此设置/选项如--ff-only将不适用。

我使用别名--ff-only默认情况下使用(git pull --ff-only)拉取,然后可以使用gup(从上方)以防无法进行快速合并或隐藏了更改。


git pull --ff-onlygit pull pull --rebase --autostash
alper

0

正如您已经提到的,这是做到这一点的方法。您可以在别名中使用它来保存输入内容和使用快捷方式,也可以在一行中使用它(也可以是别名)

git stash && git pull --rebase && git stash pop

它将执行与您所做的相同的操作,但在一行(&&)中,并且将其设置为别名甚至会更短。

在拉/推之前,以下几行将显示传入/传出的更改

git log ^master origin/master
git log master ^origin/master

8
这种方法是不安全的:如果没有要stash pop隐藏的东西,那么第一个命令将什么也不做,然后将之前的东西随机存储。
John Zwinck

只是要特别清楚:即使git stash未隐藏任何内容,它也仍“返回”没有错误代码,因此&&仍将继续执行git pulland git stash pop并弹出先前的隐藏内容。所以最好不要使用它,除非您非常确定它会藏东西!
MoonLite
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.