关于 Git 2.27 版本中 git pull 时的警告
简述
最近发现,在升级了Git版本后,每次执行git pull时都会出现以下警告。
warning: Pulling without specifying how to reconcile divergent branches is
discouraged. You can squelch this message by running one of the following
commands sometime before your next pull:
git config pull.rebase false # merge (the default strategy)
git config pull.rebase true # rebase
git config pull.ff only # fast-forward only
You can replace "git config" with "git config --global" to set a default
preference for all repositories. You can also pass --rebase, --no-rebase,
or --ff-only on the command line to override the configured default per
invocation.
早晚要好好处理这件事情,可时间已经过去了,所以现在我会认真对待。
根据搜索结果显示,这条消息似乎是在 Git 2.27.0 版本中引入的。
正如消息所述,只要实施以下三个设定之一,警告就会消失。
-
- git config pull.rebase false
-
- git config pull.rebase true
- git config pull.ff only
特别是,如果您对以前的操作没有任何不满,您可以运行git config –global pull.rebase false,这样以前的行为将保持不变,并且只会消除警告。
嗯,反正呢,既然有这个机会,就借此回顾一下,进一步加深理解吧。
理解 git merge 的选择
git pull 在基本上是将远程分支合并到本地分支的操作。
Git合并的策略有以下两种。
merge commit を作成 (3-way merge が行われる)
(必要なら merge 対象のブランチを rebase した上での) fast-forward (merge commit を作成しない)
比如说,假设在提交 a 之后,主分支(main branch)和开发分支(develop)产生了分叉。
在进行合并提交时,每个分支的历史记录将保持不变,同时会创建一个新的合并提交m。
如果要执行快速合并,那么就意味着不需创建合并提交,因此main分支在develop分岐之后不能有任何提交。(也就是说,如果main分支仍然停留在提交a的状态,那么可以直接使用快速合并将develop合并进去。)
如果不是这样的情况,首先要将develop重新基于main的HEAD提交d进行变更(rebase),使develop的分支源头成为commit d。
develop分支中的所有提交都将变为与原始提交不同的e’、f’、g’。
由于这样会修改历史记录,请注意可能出现的冲突。
此外,在Git上即使没有冲突,从代码的意义和实际操作上也可能出现冲突,因此一定要进行测试。(这一点在创建合并提交时也是一样的。)
然后进行快进操作。这只是将主分支的HEAD移动到提交g’。这样在历史上就成了一条直线。
对于 git pull 操作的选择理解
好的,那么在此之前,我想先考虑一下解决刚才的警告的三个选择。但在此之前,让我们确认一下 git pull 的 –rebase 选项。
如果不指定任何参数,与 –rebase false 相同,这是默认操作。如果指定了 –rebase,则与 –rebase true 相同。
还有其他用于精细控制 rebase 行为的选项,例如 –rebase merges、 –rebase preserve、 –rebase interactive,但这里就不提了。
一般情况下,执行git pull(不加–rebase参数)会先执行git fetch,然后再执行git merge。
在默认设置下,如果可以进行快速合并(fast-forward),则会进行快速合并;如果不能进行快速合并,就会像之前的示意图那样生成合并提交(merge commit)。
对此,执行 git pull –rebase 命令时,先执行 git fetch 命令,然后在本地分支(此示例中为主分支)执行 git rebase 命令。
在上述 fast-forward 合并的说明中,我们执行了 develop 分支的 rebase 操作,然后执行了 fast-forward 操作,但请注意,此处执行的是主分支的 rebase 操作。(尽管 main – develop 的关系变成了 origin/main – main 的关系,但本质上还是相同的事情。)
通过这样做,不会对远程分支产生任何影响。
关于git pull命令的–rebase选项的使用场景有主要以下两种。
-
- 同一ブランチに対して、複数人が同時並行で開発を行う場合
ローカルブランチを rebase した上で push することで、 merge commit が乱立することを防ぐことができます
Pull Request マージ前に、マージ先のデフォルトブランチを取り込んで、テストなどを行う場合
例えば、 Pull Request の feature ブランチにマージ先である main ブランチをあらかじめマージしても、 feature ブランチには merge commit が作られずに済みます (結果的に履歴が綺麗になります)
我也会查看与 git pull 的 fast-forward 相关的以下三个选项。 (git merge 也有完全相同的选项)
我将在下表中总结如下。 (默认选项为 –ff)
--ff
fast-forward で merge するmerge commit を生成する--no-ff
merge commit を生成するmerge commit を生成する--ff-only
fast-forward で merge するmerge せず、エラー終了する如果分别选择前面的三个选项後的行为
当达到这一点时,在没有附加选项的情况下执行git pull,我们可以了解到Git要求以下其中一项。
请将git配置pull.rebase设置为false。
这是默认的行为。执行git pull而没有添加–rebase选项的效果与没有执行–rebase的git pull相同。在默认情况下,如果可以进行fast-forward操作,它将执行fast-forward操作,否则将尝试生成合并提交。
将git配置pull.rebase设置为true。
进行 git pull –rebase 的效果与进行 git fetch 后再对本地分支进行 rebase 是相同的,因此可以保证提交历史呈直线排列,而不会创建合并提交。
只需要git config pull.ff。
只有在使用了–ff-only选项时,并且可以进行快速前进时,才会进行快速前进。
否则,不进行合并/变基操作,并以错误的方式终止。
最后结果
基本上,我認為合併/拉入策略是由每個團隊的方針而定的。以我的觀點,最好是在團隊內部達成一致,這樣在查看 Git 歷史時較容易操作。然而,當人數增加時,這一點可能變得更加困難。
合并/拉取的策略是关于如何整合代码历史记录的讨论,对当前的快照没有特别影响。(在Git操作中可能会遇到问题,但影响可能不大)
由于没有特别严重的问题,所以总的来说,当遇到困惑时,最好保持默认设置?
参考资料
-
- https://raw.githubusercontent.com/git/git/master/Documentation/RelNotes/2.27.0.txt
-
- How to deal with this git warning? “Pulling without specifying how to reconcile divergent branches is discouraged” – Stack Overflow
-
- Why You Should Use git pull –ff-only | sffc’s Tech Blog
-
- オプションなし git pull でデフォルトの挙動が未設定だと警告が出る – Qiita
-
- Git 2.27.0 から git pull をすると表示されるようになった “Pulling without specifying how to reconcile divergent branches is discouraged.” について – esm アジャイル事業部 開発者ブログ
-
- git pull エラー “Pulling without specifying how to reconcile divergent branches is discouraged.” | ハックノート
-
- ブランチの統合|サル先生のGit入門【プロジェクト管理ツールBacklog】
-
- Git – git-merge Documentation
-
- Git – git-pull Documentation
-
- Git – git-config Documentation
-
- Git – リベース
-
- fast-forwardマージから理解するgit rebase – Qiita
-
- Git のファストフォワードマージとは – yu8mada
-
- Git fast-forward な状態にして update branch で master を取り込んだ commit を残さずに済むための git rebase – かもメモ
-
- git pull と git pull –rebase の違いって?図を交えて説明します! – KRAY Inc.
-
- 3-way mergeについて調べた – Qiita
-
- GithubでのWeb上からのマージの仕方3種とその使いどころ – Qiita
- 何故 git rebase は駄目で git pull –rebase はいいのか « LANCARD.LAB|ランカードコムのスタッフブログ