Git Cheat Sheet
· 約4分
問題の背景
チームで開発する際、よくあるパターンとして、
- 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
で確認できますが、後で消える可能性がある
あくまで一時的な作業や、過去のコミットを試す時に使うモード
解決策
- ブランチからそのコミットハッシュをcherry-pickしたら解決
git log
# copy the コミット hash abc1234
git checkout branch
git cherry-pick abc1234
git push origin branch
- このコミットから新しいブランチを作成で解決
git branch feature/tmp abc1234