"git pull" 可以自动存储和弹出挂起的更改吗?
Can "git pull" automatically stash and pop pending changes?
我知道如何解决这个问题:
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 pull
为我跳stash
和pop
吗?
如果此命令有不同的名称,没关系。
为 git stash; git pull; git stash pop
创建一个 shell 别名是一个解决方案,但我正在寻找更好的解决方案。
对于 Git 2.6+(2015 年 9 月 28 日发布)
仅 git config
感兴趣的设置是:
rebase.autostash
(Git 2.27,2020 年第 2 季度,您现在还有 merge.autostash
,见下文)
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.
结合:
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.
在给定的存储库中:
git config pull.rebase true
git config rebase.autoStash true
这足以让一个简单的 git pull
即使在肮脏的树上也能工作。
在这种情况下不需要别名。
参见 commit 53c76dc (04 Jul 2015) by Kevin Daudt (Ikke
)。
(由 Junio C Hamano -- gitster
-- in commit e69b408 合并,2015 年 8 月 17 日)
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.
注意:如果你想在没有自动存储的情况下拉取(即使设置了rebase.autoStash true
),你已经从git 2.9(2016年6月)开始:
pull --rebase --no-autostash
参见 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
)。
(由 Junio C Hamano -- gitster
-- in commit 7c137bb 合并,2016 年 4 月 13 日)
Commit f66398e 特别包括:
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.
警告:在 Git 2.14(2017 年第 3 季度)之前,“git pull --rebase --autostash
”在本地历史快进到上游时不会自动隐藏。
参见 commit f15e7cf (01 Jun 2017) by Tyler Brazier (tylerbrazier
)。
(由 Junio C Hamano -- gitster
-- in commit 35898ea 合并,2017 年 6 月 5 日)
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.
更新:Mariusz Pawelski asks 一个有趣的问题:
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
答案:
original thread讨论了这个自动存储功能,它最初是为git pull
(合并)和git pull --rebase
实现的。
但是... Junio C Hamano(Git 维护者)指出:
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.
因此,对于经典的拉合并,最好是:
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
也就是说,在 Git 2.27(2020 年第 2 季度)中,“git pull
”学会了在 pull.rebase
配置不存在且 --[no-]rebase
和 --ff-only
给出(这将导致合并)。
参见 commit d18c950 (10 Mar 2020) by Alex Henrie (alexhenrie
)。
(由 Junio C Hamano -- gitster
-- in commit 1c56d6f 合并,2020 年 3 月 27 日)
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.
使用 Git 2.27(2020 年第二季度),“git merge
”学习“--autostash
”选项和新的 merge.autostash
设置。
参见 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
)。
(由 Junio C Hamano -- gitster
-- in commit bf10200 合并,2020 年 4 月 29 日)
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.
并且:
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.
随着 Git 2.30(2021 年第一季度),UI 得到改进:
参见 commit e01ae2a (19 Nov 2020) by Johannes Schindelin (dscho
)。
(由 Junio C Hamano -- gitster
-- in commit 290c940 合并,2020 年 11 月 30 日)
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.
随着 Git 2.33(2021 年第 3 季度),git pull --rebase 得到简化:
参见 commit a7d18a1, commit a751e02, commit 3400622 (17 Jun 2021) by Felipe Contreras (felipec
)。
(由 Junio C Hamano -- gitster
-- in commit 221ec24 合并,2021 年 7 月 8 日)
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 stash && git pull --rebase && git stash pop
它会做和你做的一样的事情,但在一行 (&&) 中,如果你设置为别名,它甚至会更短。
以下几行将显示 incoming/outgoing 之前的更改 pull/push
git log ^master origin/master
git log master ^origin/master
正如上面的评论所述,设置两个配置值目前不适用于 git pull
,因为自动存储配置仅适用于实际的变基。这些 git 命令可以满足您的需求:
git fetch
git rebase --autostash FETCH_HEAD
或设置为别名:
git config alias.pullr '!git fetch; git rebase --autostash FETCH_HEAD'
然后做:
git pullr
当然,这个别名可以根据需要重命名。
对于 Git 2.6+,您可以使用以下内容:
alias gup='git -c rebase.autoStash=true pull --rebase'
这个 --rebase
使得 git-pull 使用 rebase
而不是 merge
,所以 settings/options 和 --ff-only
一样不适用。
我默认使用别名 --ff-only
(git pull --ff-only
) 拉取,然后可以使用 gup
(从上面)以防快进合并不是可能或有隐藏的更改。
为了给即将到来的探索者节省几秒钟,这里是一个总结(感谢@VonC):
git pull --rebase --autostash
我知道如何解决这个问题:
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 pull
为我跳stash
和pop
吗?
如果此命令有不同的名称,没关系。
为 git stash; git pull; git stash pop
创建一个 shell 别名是一个解决方案,但我正在寻找更好的解决方案。
对于 Git 2.6+(2015 年 9 月 28 日发布)
仅 git config
感兴趣的设置是:
rebase.autostash
(Git 2.27,2020 年第 2 季度,您现在还有 merge.autostash
,见下文)
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.
结合:
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.
在给定的存储库中:
git config pull.rebase true
git config rebase.autoStash true
这足以让一个简单的 git pull
即使在肮脏的树上也能工作。
在这种情况下不需要别名。
参见 commit 53c76dc (04 Jul 2015) by Kevin Daudt (Ikke
)。
(由 Junio C Hamano -- gitster
-- in commit e69b408 合并,2015 年 8 月 17 日)
pull
: allow dirty tree whenrebase.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.
注意:如果你想在没有自动存储的情况下拉取(即使设置了rebase.autoStash true
),你已经从git 2.9(2016年6月)开始:
pull --rebase --no-autostash
参见 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
)。
(由 Junio C Hamano -- gitster
-- in commit 7c137bb 合并,2016 年 4 月 13 日)
Commit f66398e 特别包括:
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 ofrebase.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.
警告:在 Git 2.14(2017 年第 3 季度)之前,“git pull --rebase --autostash
”在本地历史快进到上游时不会自动隐藏。
参见 commit f15e7cf (01 Jun 2017) by Tyler Brazier (tylerbrazier
)。
(由 Junio C Hamano -- gitster
-- in commit 35898ea 合并,2017 年 6 月 5 日)
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.
更新:Mariusz Pawelski asks
So everybody is writing about
autostash
when you do rebase (orpull --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 doinggit pull --rebase
but OP asked about "standard" git pull
答案:
original thread讨论了这个自动存储功能,它最初是为git pull
(合并)和git pull --rebase
实现的。
但是... Junio C Hamano(Git 维护者)指出:
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.
因此,对于经典的拉合并,最好是:
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
andgit stash pop
也就是说,在 Git 2.27(2020 年第 2 季度)中,“git pull
”学会了在 pull.rebase
配置不存在且 --[no-]rebase
和 --ff-only
给出(这将导致合并)。
参见 commit d18c950 (10 Mar 2020) by Alex Henrie (alexhenrie
)。
(由 Junio C Hamano -- gitster
-- in commit 1c56d6f 合并,2020 年 3 月 27 日)
pull
: warn if the user didn't say whether to rebase or to mergeSigned-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.
Thepull.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 nopull.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.
使用 Git 2.27(2020 年第二季度),“git merge
”学习“--autostash
”选项和新的 merge.autostash
设置。
参见 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
)。
(由 Junio C Hamano -- gitster
-- in commit bf10200 合并,2020 年 4 月 29 日)
pull
: pass --autostash to mergeSigned-off-by: Denton Liu
Before,
--autostash
only worked withgit 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.
并且:
rebase
: useapply_autostash()
from sequencer.cSigned-off-by: Denton Liu
The
apply_autostash()
function inbuiltin/rebase.c
is similar enough to theapply_autostash()
function insequencer.c
that they are almost interchangeable, except for the type of arg they accept. Make thesequencer.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 refactoringsequencer.c
version ofapply_autostash()
.
Since both efforts are long done, we can freely combine them together now.
随着 Git 2.30(2021 年第一季度),UI 得到改进:
参见 commit e01ae2a (19 Nov 2020) by Johannes Schindelin (dscho
)。
(由 Junio C Hamano -- gitster
-- in commit 290c940 合并,2020 年 11 月 30 日)
pull
: colorize the hint about settingpull.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 thepull.rebase
setting.This warning was clearly intended to advise users, but as pointed out in this thread, it uses
warning()
instead ofadvise()
.One consequence is that the advice is not colorized in the same manner as other, similar messages.
So let's useadvise()
instead.
随着 Git 2.33(2021 年第 3 季度),git pull --rebase 得到简化:
参见 commit a7d18a1, commit a751e02, commit 3400622 (17 Jun 2021) by Felipe Contreras (felipec
)。
(由 Junio C Hamano -- gitster
-- in commit 221ec24 合并,2021 年 7 月 8 日)
pull
: cleanup autostash checkSigned-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 stash && git pull --rebase && git stash pop
它会做和你做的一样的事情,但在一行 (&&) 中,如果你设置为别名,它甚至会更短。
以下几行将显示 incoming/outgoing 之前的更改 pull/push
git log ^master origin/master
git log master ^origin/master
正如上面的评论所述,设置两个配置值目前不适用于 git pull
,因为自动存储配置仅适用于实际的变基。这些 git 命令可以满足您的需求:
git fetch
git rebase --autostash FETCH_HEAD
或设置为别名:
git config alias.pullr '!git fetch; git rebase --autostash FETCH_HEAD'
然后做:
git pullr
当然,这个别名可以根据需要重命名。
对于 Git 2.6+,您可以使用以下内容:
alias gup='git -c rebase.autoStash=true pull --rebase'
这个 --rebase
使得 git-pull 使用 rebase
而不是 merge
,所以 settings/options 和 --ff-only
一样不适用。
我默认使用别名 --ff-only
(git pull --ff-only
) 拉取,然后可以使用 gup
(从上面)以防快进合并不是可能或有隐藏的更改。
为了给即将到来的探索者节省几秒钟,这里是一个总结(感谢@VonC):
git pull --rebase --autostash