😇

Git Pull時のトラブルシューティング

に公開

発生した問題

最近、同じGitHubリポジトリで作業しているチームメンバーと私のGit間で、Pull Requestの「Files Changed」タブに表示される内容に違いが発生しました。
チームメンバーは作業ブランチ→PR間では作業した分のファイル数のみ表示されています。
しかし、私のPRではマージされたdevelopブランチのファイルチェンジ(自身以外の他メンバーのファイルもすべて表示)に表示されるようになりました。そのため、ファイルチェンジ数が100を超えるなど(もっと前に気付けよと自分にツッコミをいれました)とんでもないことになりました、、、、、

問題の詳細

同じ手順を踏んでいるにもかかわらず、異なる結果になっていました:

  1. 自分の作業ブランチAに移動
  2. git pull origin develop を実行
  3. git push origin ブランチA を実行

これにより、GitHub上のPull Request(PR)の「Files Changed」タブに表示される内容が:

  • チームメイト: 作業ブランチAで修正したファイルのみが表示される
  • : 作業ブランチAで修正したファイルと、developブランチで修正されたファイルも表示される

原因

問題の原因は、git pull コマンドの動作の違いでした。

  • チームメイト: マージ方式(デフォルト)を使用
  • : リベース方式を使用

調査の結果、私のグローバル設定ファイル(.gitconfig)に以下の設定があることがわかりました:

[pull]
    rebase = true

一方、チームメイトの設定ファイルには、この設定がありませんでした。
(.gitconfigファイルの[pull]セクションの設定を書き換えた記憶は全くありません、、、、)

マージ方式とリベース方式の違い

merge方式

git pull origin develop (--no-rebase オプション付きまたはpull.rebase = false)

特徴

  • 履歴がそのまま保持され、マージコミットが作成される
  • ブランチが分岐して再度合流する「ダイヤモンド型」の履歴になる
  • GitHub上のPRには、作業ブランチで行った変更のみが表示される
  • コンフリクトをマージ時に一度だけ解決

図解

A1 -- A2 -- A3 -- A4 -- M  (ブランチA)
      \               /
       D1 -- D2 -- D3     (Developブランチ)

M = マージコミット

rebase方式

git pull --rebase origin develop (または pull.rebase = true)

特徴

  • 作業ブランチのコミットが退避され、対象ブランチの上に再適用される
  • 直線的な履歴になる
  • GitHub上のPRには、developからブランチAまでの全ての変更が表示される
  • 各コミットを再適用する時点でそれぞれコンフリクト解決が必要になる場合がある

図解

D1 -- D2 -- D3 -- A1' -- A2' -- A3' -- A4'  (ブランチA)

A1', A2'... = リベースにより再適用されたコミット

解決方法

問題を解決するには、以下のいずれかの方法で設定を変更します:

グローバル設定を変更(すべてのリポジトリに適用)

git config --global pull.rebase false

または .gitconfig ファイル内の[pull]セクションを直接編集もしくは[pull]セクションを削除

[user]
    name = JohnDoe
    email = john.doe@example.com
~~~~~(一部省略)~~~~~
[pull]
    rebase = false

プロジェクト固有の設定を変更(現在のリポジトリのみ適用)

git config pull.rebase false

これにより、.git/config ファイルに以下の設定が追加されます:

[pull]
    rebase = false

macOSにおけるGitの設定階層

設定ファイルの優先順位(下に行くほど優先される)

  1. システム全体の設定 (/etc/gitconfig)
  2. グローバル設定 (~/.gitconfig)
  3. プロジェクト固有の設定 (.git/config)
  4. コマンドラインオプション (--rebase など)

プロジェクト固有の設定がない場合は、グローバル設定が適用されます。これが今回の問題の原因でした。

チームでの統一

チーム内での一貫性を確保するには:

  1. チームで標準的な設定を決める(マージ方式かリベース方式か)
  2. 新しいメンバーがチームに参加した際に設定を確認する
  3. 必要に応じてプロジェクト固有の設定を .git/config に含める

補足:Homebrew でより新しいバージョンのGitを使用する方法

macOSにはデフォルトでGitがインストールされていますが、より新しいバージョンを使いたい場合は:

# Homebrewのインストール
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Gitのインストール
brew install git

Homebrewでインストールしたgitを優先するには:

# zshの場合
echo 'export PATH="/opt/homebrew/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

# bashの場合
echo 'export PATH="/opt/homebrew/bin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile

Intel Macの場合は /opt/homebrew/bin の代わりに /usr/local/bin を使用します。


いや、想定外すぎる挙動すぎて最初は焦りました、、、、、
チーム開発では、このような設定の違いが予期せぬ問題を引き起こすことがあるため、設定を統一することが重要と痛感した機会でした。

Discussion