esm アジャイル事業部 開発者ブログ

永和システムマネジメント アジャイル事業部の開発者ブログです。

Git 2.27.0 から git pull をすると表示されるようになった "Pulling without specifying how to reconcile divergent branches is discouraged." について

最近の趣味はもっぱら L7 より下のお勉強、な @yucao24hours です。

梅雨入りもどこ吹く風の暑いある日、いつものように git pull を実行すると、以下のような警告が出るようになりました。

$ 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 --version
git version 2.27.0

警告を見ると

Pulling without specifying how to reconcile divergent branches is discouraged.

ということで、「分岐したブランチの解決のしかたを指定しないで pull するのはやめましょう」といったことが示唆されています。

どうして警告が出るようになったのか?

こちらは、2020 年 6 月 1 日にリリースされた Git 2.27.0 で新たに表示されるようになった警告のようで、以下はリリースノートからの引用です。

  • "git pull" issues a warning message until the pull.rebase configuration variable is explicitly given, which some existing users may find annoying---those who prefer not to rebase need to set the variable to false to squelch the warning.

github.com

以下が対象のコミットです。

https://github.com/git/git/commit/d18c950a69f3a24e1e3add3d9fc427641f53e12b

コミットメッセージによれば:

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.

とのことで、 pull --rebasepull --ff-only のふるまいを期待しているにも関わらずそれらの指定をしないまま pull してしまったユーザが、意図しないマージコミットを作ってしまうケースを避けるための警告のようです。

git pull のふるまいを紐解いてみる

git pullを実行したとき、Git はまず git fetch を実行し、そのあとに current branch に対して 事前に git fetch で取得したヘッドをマージするように git merge を実行します。

このとき、Git の設定ファイルの中で pull.rebasetrue もしくは false と明示的に設定されているか、 実行時に --rebase などのオプションが指定されていれば、リモートブランチとの差があったときにはそれらに従って差分が解決されます。

従来は、 pull.rebase の設定がなくて且つ pull 実行時のオプションも指定されなかった場合にはマージコミットを作って解決するというふるまいだったのですが、慣れないユーザがこれを意図しないふるまいとして困らないように、今回の修正をもって明示的に差分の解決方法を Git に教えてあげる方針となったということのようです。

(Git に慣れていないころ、 git pull をしたら突然エディタが開かれてマージコミットのコミットメッセージを編集するよう促され、何が起きたかわからずびっくりした方もいらっしゃるのではないでしょうか。ちなみにわたしはそうでした。)

なお、git pull の詳しい動作については、公式ドキュメントをご覧ください。

git-scm.com

どうするとよい?

先の警告メッセージにもあるとおり、pull したときにリモートブランチと差があった場合のふるまいとして、以下のいずれかの設定を用いて指定するようにすれば警告は消え、Git の意図する状態となります。期待するふるまいにあったものを選びましょう。

git configの公式ドキュメントの pull.rebase の説明 にもありますが、 rebase の動作をじゅうぶんに理解しないまま pull.rebase 設定を使って暗黙的にリベースに関する指定をしておくことは危険な場合があるとされています。ちなみに、わたしは暗黙的な動作によって影響を把握しきれないといけないので pull.rebase false にしましたが、社内には pull.rebase true にしている人もいますし、後述の pull.ff only にしている人もいます。どのような設定が良いかは各自の理解度やユースケースに合わせて決めましょう。

--rebase したいときは実行時に明示するスタイルがいい

こちらを設定すると、デフォルトの pull の挙動のままになります。

$ git config pull.rebase false

実行時の --rebase なしで pull --rebase になってほしい

$ git config pull.rebase true

差分があったら fast forward してほしい (fast forward できないときは失敗してほしい)

$ git config pull.ff only

なお、ここで指定する設定内容をすべてのリポジトリにおいてデフォルトの設定にしたい場合は、 上記の git configgit config --global とすることでグローバルな設定とすることができます。

先ほどのコミットのコミットメッセージにも

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 を使い慣れている方々にとってはちょっと冗長に感じられるかも知れませんが、一度設定すればその後は気にしなくてよくなりますので、シュッと設定してしまいましょう!