可以“git pull"吗?自动隐藏和弹出挂起的更改? [英] Can "git pull" automatically stash and pop pending changes?

查看:23
本文介绍了可以“git pull"吗?自动隐藏和弹出挂起的更改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

user@host$ git pull更新 9386059..6e3ffde错误:您对以下文件的本地更改将被合并覆盖:foo.bar请在合并之前提交您的更改或隐藏它们.中止

但是有没有办法让 git pull 为我做 stashpop 跳舞?

如果这个命令有不同的名字,没关系.

git stash 创建一个 shell 别名;git拉;git stash pop 是一个解决方案,但我正在寻找更好的解决方案.

解决方案

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

唯一的 git config 感兴趣的设置是:

<块引用>

rebase.autostash

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

<块引用>

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

但是,请谨慎使用:成功 rebase 后的最终存储应用程序可能会导致重大冲突.默认为 false.

结合:

<块引用>

pull.rebase

<块引用>

如果为真,则在获取的分支之上重新建立分支,而不是在git pull"执行时从默认远程合并默认分支.正在运行.

在给定的存储库中:

git config pull.rebase truegit 配置 rebase.autoStash 真

这足以让简单的 git pull 即使在脏树中也能工作.
在这种情况下不需要别名.


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

<块引用>

pull:启用 rebase.autostash 时允许脏树

<块引用>

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

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


注意:如果你想拉而没有 autostash(即使设置了rebase.autoStash true),你从git 2.9(2016年6月)开始:

 pull --rebase --no-autostash

参见 commit 450dd1dcommit 1662297, commit 166229744a59ff、提交 5c82bcdcommit 6ddc97c, 提交 eff960b提交 efa195d(4 月 2 日)和 201href="https://github.com/git/git/commit/f66398eb57c627169429f47bbe4d943d2c975959" rel="noreferrer">提交 f66398ecommit 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 rebase"的选项;当git pull --rebase"被称为.


警告:在 Git 2.14(2017 年第三季度)之前,git pull --rebase --autostash";当本地历史快进到上游时没有自动存储.

参见 commit f15e7cf(2017 年 6 月 1 日)Tyler Brazier (tylerbrazier).
(由 Junio C Hamano 合并 -- gitster --commit 35898ea,2017 年 6 月 5 日)

<块引用>

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

<块引用>

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


更新:Mariusz Pawelski在评论中 一个有趣的问题:

<块引用>

所以当你做 rebase(或 pull --rebase)时,每个人都在写 autostash.

<块引用>

但是当您使用合并进行正常拉取时,没有人会考虑自动存储.
所以没有自动切换?或者我错过了什么?我更喜欢做 git pull --rebase 但 OP 询问了standard"git pull

答案:

原始线程 讨论此自动存储功能,它最初是为 git pull (merge) 和 git pull --rebase 实现的.

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

<块引用>

如果 pull-merge 是会引起烦恼"的东西触发这个话题,根据定义,本地变化重叠与合并,以及这个内部的stash pop"将触及路径合并触及,它可能不会导致Dropped"但离开进一步的冲突有待解决.

我怀疑 pull.autostash 配置不是一个好的补充,因为它助长了糟糕的、令人痛苦的工作流程.
在简单的情况下它可能不会受到伤害,但是当局部变化很复杂时,它会比没有它更积极,并且配置剥夺了选择的动力.

pull-rebase"的等式有些不同,因为rebase"与rebase"不同.坚持你从一个干净的工作树开始,所以下载并然后停止"烦恼感觉更大.我有一个怀疑放松这可能是解决实际问题的更有效的方法.

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

<块引用>

鼓励用户在运行git pull"之前考虑他在工作树中拥有的 WIP 的性质.
是不是太复杂的野兽可能会干扰其他人正在做的事情,或者他可以把它藏起来然后把它弹出来是一个微不足道的变化吗?

如果是前者,他会更好地执行checkout -b",保持工作直到局部变化变得更好,并且提交",在拉入原始分支之前.

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

<块引用>

  • "git pull",
  • 发现冲突后,运行
    • git stash,
    • git 合并 FETCH_HEAD
    • git stash pop


话虽如此,在 Git 2.27(2020 年第二季度)中,git pull"学会了在不存在 pull.rebase 配置时发出警告,并且既没有给出 --[no-]rebase 也没有给出 --ff-only (这将导致合并).

参见 commit d18c950(2020 年 3 月 10 日),作者 亚历克斯亨利 (alexhenrie).
(由 Junio C Hamano 合并 -- gitster --commit 1c56d6f,2020 年 3 月 27 日)

<块引用>

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 设置.

参见 commit d9f15d3commit f8a1785, 提交 804fe31commit 12b6e13, 提交 0dd562e提交 0816f1d提交 9bb3dea, 提交 4d4bc15, 提交 b309a97提交 f213f06commit 86ed00a, 提交 facca7f提交 be1bb60commit efcf6cf, 提交 c20de8b, 提交 bfa50c2, 提交 5b2f6d9(2020 年 4 月 7 日),commit 65c425a(2020 年 4 月 4 日),以及 commit 65c425a" rel="noreferrer">提交 fd6852c,提交 805d29ea2020 年)由 Denton Liu (Denton-L).
(由 Junio C Hamano 合并 -- gitster --提交 bf10200,2020 年 4 月 29 日)

<块引用>

pull:通过 --autostash 进行合并

签字人:Denton Liu

<块引用>

之前,--autostash 只适用于 git pull --rebase.

然而,在上一个补丁中,合并学习了--autostash,所以我们没有理由再有这个限制了.
教 pull 通过 --autostash 进行合并,就像 rebase 一样.

还有:

<块引用>

rebase:使用apply_autostash() 来自 sequencer.c

签字人:Denton Liu

<块引用>

<中的apply_autostash()函数code>builtin/rebase.csequencer.c 它们几乎可以互换,除了它们接受的 arg 类型.使 sequencer.c 版本外部和在 rebase 中使用它.

rebase 版本是在 6defce2b02 中引入的(builtin rebase: support --autostash 选项",2018-09-04,Git v2.20.0-rc0 -- merge 列在 batch #8) 作为 shell 的一部分C 转换.
它选择复制该函数,因为当时还有另一个正在进行的项目将交互式 rebase 从 shell 转换为 C,并且他们不想通过重构 sequencer.c 版本的apply_autostash().
由于这两种努力已经完成很久,我们现在可以自由地将它们组合在一起.


在 Git 2.30(2021 年第一季度)中,用户界面得到了改进:

参见 commit e01ae2a(2020 年 11 月 19 日)约翰内斯·辛德林 (dscho).
(由 Junio C Hamano 合并 -- gitster --提交 290c940,2020 年 11 月 30 日)

<块引用>

pull:为关于设置pull.rebase

指出:Ævar Arnfjörð Bjarmason
签字人:约翰内斯·辛德林

<块引用>

d18c950a69f 中(pull:警告用户没有说是rebase还是merge",2020-03-09,Git v2.27.0-rc0 -- 合并 列于 batch #2),一个新的引入提示是为了鼓励用户通过配置 pull.rebase 设置来有意识地决定他们是否希望他们的 pull 合并或 rebase.

此警告显然是为了向用户提供建议,但正如 中所指出的这个线程,它使用warning() 而不是advise().

一个后果是,通知的颜色与其他类似的消息不同.
所以让我们改用 advise().


在 Git 2.33(2021 年第 3 季度)中,简化了 git pull --rebase:

参见提交a7d18a1提交 a751e022fa565f74b9f>2frel="noreferrer">commit a751e02Felipe Contreras (felipec) 的 3400622(2021 年 6 月 17 日).
(由 Junio C Hamano 合并 -- gitster --commit 221ec24,2021 年 7 月 8 日)

<块引用>

pull:清理自动存储检查

签字人: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 在脏仓库中工作",2017-06-01,Git v2.14.0-rc0 -- 合并 列在 --autostash 选项 [a03b555 ("merge:teach --autostash option", 2020-04-07, Git v2.27.0-rc0 -- 合并列在)],git pull"(男人) [d9f15d3 ("pull: pass --autostash to merge", 2020-04-07, Git v2.27.0-rc0 -- merge 列在 合并>批次#5)].

因此,当使用 --rebase --autostash 调用时,不再需要跳过快进合并快捷方式.

让我们始终通过基本上恢复 f15e7cf 来走快进合并捷径.>

I know how to solve this:

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

But isn't there a way to let git pull do the stash and pop dance for me?

If this command has a different name, it's ok.

Creating a shell alias for git stash; git pull; git stash pop is a solution, but I search for a better solution.

解决方案

For Git 2.6+ (released 28 Sept 2015)

The only git config setting which would be of interest is:

rebase.autostash

(with Git 2.27, Q2 2020, you now also have merge.autostash, see below)

When set to true, automatically create a temporary stash before the operation begins, and apply it after the operation ends.
This means that you can run rebase on a dirty worktree.

However, use with care: the final stash application after a successful rebase might result in non-trivial conflicts. Defaults to false.

Combine that with:

pull.rebase

When true, rebase branches on top of the fetched branch, instead of merging the default branch from the default remote when "git pull" is run.

In a given repository:

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

That would be enough for a simple git pull to work even in a dirty tree.
No alias needed in that case.


See commit 53c76dc (04 Jul 2015) by Kevin Daudt (Ikke).
(Merged by Junio C Hamano -- gitster -- in commit e69b408, 17 Aug 2015)

pull: allow dirty tree when rebase.autostash enabled

rebase learned to stash changes when it encounters a dirty work tree, but git pull --rebase does not.

Only verify if the working tree is dirty when rebase.autostash is not enabled.


Note: if you want to pull without autostash (even though rebase.autoStash true is set), you have since git 2.9 (June 2016):

 pull --rebase --no-autostash

See commit 450dd1d, commit 1662297, commit 44a59ff, commit 5c82bcd, commit 6ddc97c, commit eff960b, commit efa195d (02 Apr 2016), and commit f66398e, commit c48d73b (21 Mar 2016) by Mehul Jain (mehul2029).
(Merged by Junio C Hamano -- gitster -- in commit 7c137bb, 13 Apr 2016)

Commit f66398e in particular includes:

pull --rebase: add --[no-]autostash flag

If rebase.autoStash configuration variable is set, there is no way to override it for "git pull --rebase" from the command line.

Teach "git pull --rebase" the --[no-]autostash command line flag which overrides the current value of rebase.autoStash, if set. As "git rebase" understands the --[no-]autostash option, it's just a matter of passing the option to underlying "git rebase" when "git pull --rebase" is called.


Warning: before Git 2.14 (Q3 2017), "git pull --rebase --autostash" didn't auto-stash when the local history fast-forwards to the upstream.

See commit f15e7cf (01 Jun 2017) by Tyler Brazier (tylerbrazier).
(Merged by Junio C Hamano -- gitster -- in commit 35898ea, 05 Jun 2017)

pull: ff --rebase --autostash works in dirty repo

When git pull --rebase --autostash in a dirty repository resulted in a fast-forward, nothing was being autostashed and the pull failed.
This was due to a shortcut to avoid running rebase when we can fast-forward, but autostash is ignored on that codepath.


Update: Mariusz Pawelski asks in the comments an interesting question:

So everybody is writing about autostash when you do rebase (or pull --rebase).

But no one is taking about autostashing when you do normal pull with merges.
So there is no automatic switch for that? Or I am missing something? I prefer doing git pull --rebase but OP asked about "standard" git pull

Answer:

The original thread discussing this autostash feature, it was implemented originally both for git pull (merge) and git pull --rebase.

But... Junio C Hamano (Git maintainer) noted that:

If the pull-merge were something that would induce the "annoyance" that triggered this topic, by definition, the local change overlaps with the merge, and this internal "stash pop" will touch the paths the merge touched and it is likely not result in "Dropped" but leave further conflicts to be resolved.

I suspect that pull.autostash configuration is not a good addition because it encourages a bad, pain-inducing workflow.
In simple cases it may not hurt, but when local changes are complex, it would actively hurt than not having it, and the configuration robs the incentive to choose.

The equation is somewhat different for "pull-rebase", as "rebase" insists you to start from a clean working tree, so "download and then stop" annoyance feels bigger. I have a suspicion that loosening that may be a more productive fix to the real problem.

So, regarding a classic pull-merge, it is better to:

encourage the user to think about the nature of WIP he has in the working tree before running "git pull".
Is it a too complex beast that may interfere with what others are doing, or is it a trivial change that he can stash away and pop it back?

If the former, he will be far better off doing "checkout -b", keep working until the local change gets into somewhat a better shape and "commit", before pulling into the original branch.

If the latter, he is better off doing:

  • "git pull",
  • after finding it conflicts, run
    • git stash,
    • git merge FETCH_HEAD and
    • git stash pop


That being said, with Git 2.27 (Q2 2020), "git pull" learned to warn when no pull.rebase configuration exists, and neither --[no-]rebase nor --ff-only is given (which would result a merge).

See commit d18c950 (10 Mar 2020) by Alex Henrie (alexhenrie).
(Merged by Junio C Hamano -- gitster -- in commit 1c56d6f, 27 Mar 2020)

pull: warn if the user didn't say whether to rebase or to merge

Signed-off-by: Alex Henrie

Often novice Git users forget to say "pull --rebase" and end up with an unnecessary merge from upstream.

What they usually want is either "pull --rebase" in the simpler cases, or "pull --ff-only" to update the copy of main integration branches, and rebase their work separately.
The pull.rebase configuration variable exists to help them in the simpler cases, but there is no mechanism to make these users aware of it.

Issue a warning message when no --[no-]rebase option from the command line and no pull.rebase configuration variable is given.
This will inconvenience those who never want to "pull --rebase", who haven't had to do anything special, but the cost of the inconvenience is paid only once per user, which should be a reasonable cost to help a number of new users.


With Git 2.27 (Q2 2020), "git merge" learns the "--autostash" option, and the new merge.autostash setting.

See commit d9f15d3, commit f8a1785, commit a03b555, commit 804fe31, commit 12b6e13, commit 0dd562e, commit 0816f1d, commit 9bb3dea, commit 4d4bc15, commit b309a97, commit f213f06, commit 86ed00a, commit facca7f, commit be1bb60, commit efcf6cf, commit c20de8b, commit bfa50c2, commit 3442c3d, commit 5b2f6d9 (07 Apr 2020), commit 65c425a (04 Apr 2020), and commit fd6852c, commit 805d9ea (21 Mar 2020) by Denton Liu (Denton-L).
(Merged by Junio C Hamano -- gitster -- in commit bf10200, 29 Apr 2020)

pull: pass --autostash to merge

Signed-off-by: Denton Liu

Before, --autostash only worked with git pull --rebase.

However, in the last patch, merge learned --autostash as well so there's no reason why we should have this restriction anymore.
Teach pull to pass --autostash to merge, just like it did for rebase.

And:

rebase: use apply_autostash() from sequencer.c

Signed-off-by: Denton Liu

The apply_autostash() function in builtin/rebase.c is similar enough to the apply_autostash() function in sequencer.c that they are almost interchangeable, except for the type of arg they accept. Make the sequencer.c version extern and use it in rebase.

The rebase version was introduced in 6defce2b02 ("builtin rebase: support --autostash option", 2018-09-04, Git v2.20.0-rc0 -- merge listed in batch #8) as part of the shell to C conversion.
It opted to duplicate the function because, at the time, there was another in-progress project converting interactive rebase from shell to C as well and they did not want to clash with them by refactoring sequencer.c version of apply_autostash().
Since both efforts are long done, we can freely combine them together now.


With Git 2.30 (Q1 2021), the UI is improved:

See commit e01ae2a (19 Nov 2020) by Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster -- in commit 290c940, 30 Nov 2020)

pull: colorize the hint about setting pull.rebase

Pointed-out-by: Ævar Arnfjörð Bjarmason
Signed-off-by: Johannes Schindelin

In 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), a new hint was introduced to encourage users to make a conscious decision about whether they want their pull to merge or to rebase by configuring the pull.rebase setting.

This warning was clearly intended to advise users, but as pointed out in this thread, it uses warning() instead of advise().

One consequence is that the advice is not colorized in the same manner as other, similar messages.
So let's use advise() instead.


With Git 2.33 (Q3 2021), git pull --rebase is simplified:

See commit a7d18a1, commit a751e02, commit 3400622 (17 Jun 2021) by Felipe Contreras (felipec).
(Merged by Junio C Hamano -- gitster -- in commit 221ec24, 08 Jul 2021)

pull: cleanup autostash check

Signed-off-by: Felipe Contreras

Currently "git pull --rebase"(man) takes a shortcut in the case a fast-forward merge is possible; run_merge() is called with --ff-only.

However, "git merge"(man) did ont have an --autostash option, so, when "git pull --rebase --autostash``"(man) was called and the fast-forward merge shortcut was taken, then the pull failed.

This was fixed in commit f15e7cf ("pull: ff --rebase --autostash works in dirty repo", 2017-06-01, Git v2.14.0-rc0 -- merge listed in batch #7) by simply skipping the fast-forward merge shortcut.

Later on "git merge" learned the --autostash option [a03b555 ("merge: teach --autostash option", 2020-04-07, Git v2.27.0-rc0 -- merge listed in batch #5)], and so did "git pull"(man) [d9f15d3 ("pull: pass --autostash to merge", 2020-04-07, Git v2.27.0-rc0 -- merge listed in batch #5)].

Therefore it's not necessary to skip the fast-forward merge shortcut anymore when called with --rebase --autostash.

Let's always take the fast-forward merge shortcut by essentially reverting f15e7cf.

这篇关于可以“git pull"吗?自动隐藏和弹出挂起的更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆