メインコンテンツまでスキップ

Git Cheat Sheet

· 約4分
Mikyan
白い柴犬

問題の背景

チームで開発する際、よくあるパターンとして、

  • developブランチから、featureブランチAを切って実装、PullRequestを作成し、レビュー待ち
  • その間に、featureブランチAにfeatureブランチBを切って、新しい機能を実装します
  • featureブランチAのレビューを経て承認され、スカッシュマージによってdevelopブランチへ統合され
  • この時、featureブランチBのコミットがfeatureブランチAの元のコミットに含まれてしまうことがあって、developブランチと多くのマージコンフリクトが発生してしまいました。

問題発生の原因

  • スカッシュマージによって個々のコミットがまとめられたため、ブランチBには依然としてブランチAの個々の変更が残っていること
  • その結果、developブランチに既に存在するスカッシュコミットとブランチBの変更が重複して適用され、コンフリクトが発生したこと

解決策:リベースによる解決

ブランチBをブランチA由来のコミットを取り除いて、developブランチ上のスカッシュコミットに合わせてリベースすることで、効率よく解決できます。

具体的には、以下の手順で行います:

git checkout feature/branch-b
git rebase --onto develop HASH_BASE feature/branch-b

このコマンドは、ブランチ B の中で HASH_BASE より後のコミットだけを、develop ブランチ上に再適用します。 HASH_BASEは、ブランチ A が develop から分岐した時点のコミットハッシュにすると、元ブランチ A のコミットがブランチ B に含まれなくなります。

リベース中にコンフリクトが発生した場合、各コンフリクト箇所で適切に修正し、 以下のコマンドでリベースを続行します。

git add <修正済みファイル>
git rebase --continue

リベースが正常に完了したら、ブランチ B の変更を develop ブランチへPRを作成してマージしましょう。

この方法により、履歴がクリーンになり、将来的なマージやデバッグ作業が大幅に楽になります。

Remote ブランチにコミットしました

問題の背景

リモートブランチをLocalにFetchせずに、チェックアウトし、

git checkout origin/branch-a

をすると、そのまま作業し、コミットしたら、プッシュできない。下記のエラーメッセージ表示されました:

error: src refspec feature/branch does not match any
error: failed to push some refs to 'github.com:organization/project.git'

問題発生の原因

Fetchが忘れて、RemoteブランチをCheckoutするとき、実際のHEADはそのブランチではなく、detached HEADの状態です。 すると、ブランチに所属せず、特定のコミットを指している状態です。

git checkout origin/main
# または
git checkout <コミットID>
HEAD → origin/main の最新コミットを直接指す(ローカルブランチではない)

ブランチは指していない
→ この状態でコミットすると、その履歴はどのブランチにも属しません。

そのまま作業して、コミットできるか、そのコミットはブランチ属していない、浮いた状態です。 git log, git reflogで確認できますが、後で消える可能性がある あくまで一時的な作業や、過去のコミットを試す時に使うモード

解決策

  1. ブランチからそのコミットハッシュをcherry-pickしたら解決
git log
# copy the コミット hash abc1234
git checkout branch
git cherry-pick abc1234
git push origin branch
  1. このコミットから新しいブランチを作成で解決
git branch feature/tmp abc1234