69
66

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Git ブランチ作成からマージされるまでの流れ

Last updated at Posted at 2022-10-01

Issueが割り振られてから、マージされるまでの流れをご紹介します。
プロジェクトによって細かい部分は異なるかもしれませんが、概ねは大丈夫かなと思います。

概要

  • 実務におけるGitの作業フローをまとめています。
  • ブランチ戦略の話ではありません。
  • 主に個人のトピック(作業)ブランチに焦点をあてています。
  • SourceTree等のGUIツールは使用しません。Git CLIのみです。
  • リモートリポジトリをクローンして、ローカルリポジトリは作成済みの想定です。
  • デフォルトブランチが main ではなく develop など別のブランチになっている方は読み替えてください。

事前準備

ローカルの main ブランチを削除

ローカルの main ブランチはまったく使用しません。削除します。
古いローカルの main ブランチから新しくブランチを作成しないための予防策です。

$ git switch -d origin/main
$ git branch -D main

ローカルの main ブランチを使用しない運用については下記の記事で詳しく書いてます。

流れ

  1. 新しくブランチを作成する
  2. 作業してコミットをする
  3. 作業ブランチに最新のmainブランチを取り込む
  4. 作業ブランチを整理する
  5. リモートブランチへプッシュする
  6. プルリクエストを作成する
  7. レビューを受ける
  8. レビュー内容を反映したコミットを作る
  9. 変更点の再レビューを受ける
  10. 再度作業ブランチを整理する
  11. GitHub上でマージする
  12. ローカルのブランチを削除する

書き出してみましたが、多いので補足していきます。

新しくブランチを作成する

ブランチを作成する前に必ず、最新のリモートリポジトリの情報を取り込んでください。
これをしないと古いコミットからブランチを切り出してしまうことがあります。

$ git fetch

派生元の origin/main リモート追跡ブランチから新しく topic-123 ブランチを作成しています。
また、派生元のブランチを指定しない場合は現在のブランチから新しいブランチが作成されます。

$ git switch -c topic-123 origin/main

理由なくマージ済みのブランチを再利用したり、そこからブランチを生やさないでください。
最新に追いつくためのマージやコンフリクト解消するコストが発生します。

ブランチ名の命名ルールはプロジェクトのブランチ戦略によるのでプロジェクトに合わせてください。
導入しているタスク管理ツールによってはタスク番号をブランチに含めると自動で紐付くものもあるのでツールに合わせた命名ルールにすると良いです。

作業してコミットをする

作業した変更内容をコミットします。

$ git add .
$ git commit

vimエディタで開くのでコミットメッセージを入力します。

git commit の便利なオプション

補足ないと手抜き感あるのでここでgit commitの便利なオプションを紹介します。

$ git commit -m "A 機能を実装しました"

-m オプションを付けるとvimエディタを立ち上げずに1行コミットメッセージを入力できます。

$ git commit --amend

--amend 直前のコミットを変更できます。
git add してインデックス(ステージング)上がっている変更が直前のコミットに反映されます。
また、コミットメッセージの変更もできます。

$ git commit --amend --no-edit

コミットメッセージを変更する必要ない場合は --no-edit オプションを付けます。

作業ブランチに最新のmainブランチを取り込む

[リベース前]
      E---F---G topic-123
     /
A---B---C---D origin/main

[リベース後]
              E'---F'---G' topic-123
             /
A---B---C---D origin/main

チーム開発していくと main ブランチがどんどん更新されていき、作業ブランチが古くなってしまいます。
古くなると大量にコンフリクトが発生することもあるのでこまめに取り込みましょう。
git rebase で最新を取り込むとコミットハッシュ値が変わります。

プルリクエストを出す前にもコンフリクトしていないか確認をするために必ず最新を取り込んでください。
コンフリクトが発生したままプルリクエストを出すとレビュワーの負担と不必要なコミュニケーションコストが増えます。

$ git stash -u

作業途中のファイルがある場合は、スタッシュして一時保存するかコミットしてください。
-u オプションを付けると未追跡ファイル(untracked file)を含めてスタッシュしてくれます。

$ git fetch

最新のリモートブランチの情報を取得します。

$ git rebase origin/main

途中コンフリクトが発生したらエディタを開いてコンフリクトを解決してください。

$ git status

# 対象のファイルを開いてコンフリクトを解消する

$ git add .
$ git rebase --continue

途中でやり直ししたい場合は git rebase --abort してください。
リベースする前の状態に戻ります。

$ git stash pop

スタッシュに一時保存した変更を取り出します。
git rebase のわかりやすそうなサイトをご紹介します。
https://www.atlassian.com/ja/git/tutorials/rewriting-history/git-rebase

git rebase についてはハンズオン形式で紹介した記事です。

https://qiita.com/ucan-lab/items/0a128bb14528e4e52fd2

作業ブランチを整理する

コミットメッセージを間違えたり、同じメッセージのコミットが複数あったり、wipなど試行錯誤した作業コミットは残さないようにします。

1つのコミットは1つ1つ意味のあるまとまりにします。
Issueを細かく区切って1プルリクエスト1コミットになるのが理想です。

mainブランチのコミットが綺麗になっているとあとから保守する人が助かります。

$ git rebase -i origin/main

リモートブランチへプッシュする

$ git push -u origin HEAD

-u オプションを付けると次回以降は git push だけで良くなります。

push.default オプション

$ git config --global push.default current

このオプションを設定している場合は git push だけでOKです。

$ git push

https://qiita.com/ucan-lab/items/c65297c062b477be01e5

プルリクエストを作成する

GitHubを開いてプルリクエストを作成します。

レビューを受ける

先輩からの手厚いレビューを受けます

Ev7kuJUUUAI9yBz (1).png

レビュー内容を反映したコミットを作る

$ git add .
$ git commit -m "レビュー内容の反映"
$ git push

レビューが通るまで繰り返します💪

変更点の再レビューを受ける

Approveされたら、作業ブランチを整理してマージ作業を行います。

EoHxDS-UcAEDyjd.jpg

再度作業ブランチを整理する

レビューが完了したら、
レビューを通すために試行錯誤したコミットを見直したり、レビュー中にmainブランチが進んでいる場合があるので最新を取り込みます。
(レビュー依頼したらrebase禁止で運用しているプロジェクトもあります。その場合はスキップしてください)

$ git rebase origin/main
$ git rebase -i origin/main
$ git push --force-with-lease --force-if-includes
  • git rebase したのでコミットハッシュ値が変わり、強制プッシュが必要
  • git push --force-with-lease --force-if-includes ブランチを強制プッシュします
    • 個人で使用している作業ブランチのみ強制プッシュ

--force or --force-with-lease --force-if-includes の違い

リモートリポジトリのブランチにプッシュする場合、リモートリポジトリの最終コミットとローカルリポジトリの最終コミットが親子関係になっていないとエラーとなり通常はpushできません。

--force オプションを付けるとその制限を回避できます。
こうするとGitはリモート履歴を完全に無視して、無条件にブランチを上書きします。

しかし、他の人がそのブランチを変更していた場合はその変更が失われてしまいます。

--force-with-lease オプションは
リモートリポジトリの特定のブランチが最後にfetchまたはpullした時から更新されていないことを確認することで安全な強制プッシュを実現します。
もし誰かがリモートブランチへ新しいコミットをプッシュしていた場合は、プッシュが拒否されます。

--force-if-includes オプションは
リモートリポジトリにあるコミットがローカルのプッシュしようとしているブランチの履歴に含まれている場合のみ、強制プッシュを許可します。このオプションにより直前にfetchしているとpushが成功してしまう問題が解消します。

https://zenn.dev/mary_pp/articles/eaac544eaf600a

# エイリアス登録
$ git config --global alias.pushf 'push --force-with-lease --force-if-includes'
# 強制プッシュ実行
$ git pushf

GitHub上でマージする

GitHub上で作業者自身(レビューイ)が Create a merge commit を選択し Merge pull request を押してマージします。
(レビュワーがマージするとコミット整理中にマージされてしまう場合がある)

ScreenShot 2022-10-03 17.04.03.png

その際にリモートブランチも削除するオプションを指定してください。

マージの種類についての補足

  • Create a merge commit
    • マージコミットが残ります。
    • 作業ブランチのコミットはそのまま残ります。
    • プルリクエスト単位でリバートしやすい。
  • Squash and merge
    • マージコミットが残ります。
    • 作業ブランチのコミットが1つにまとめられます。
    • まとめる前のコミットには戻せない。
    • プルリクエスト単位でリバートしやすい。
  • Rebase and merge
    • マージコミットは作成されず、履歴が一本化されます。
    • 作業ブランチのコミットはそのまま残ります。
    • プルリクエスト単位でリバートしたい場合に困る。

コミット自体はリベースで整理されていることと、何かあったときにプルリクエスト単位でリバートしたいので、個人的には Create a merge commit が推しです。

誤って別のマージを選択してしまうのを防止するため、使用しないマージボタンを無効化できます。
https://qiita.com/ucan-lab/items/d594404d0d2c64a85a38#settings--options--merge-button

ローカルのブランチを削除する

$ git fetch -p

-p を付けると削除されたリモートブランチも反映されます。

$ git branch -D topic-123

ローカルのブランチを削除する。

マージ済みブランチを再度利用することはないので削除します。
古いブランチが溜まると単純に見辛かったり、git fetchが遅くなる場合があります。
また、古いブランチを残して再利用すると最新に追いつくためのマージやコンフリクト解消がコストになります。


補足: 最新の main ブランチに切り替える

$ git fetch
$ git switch -d origin/main

ローカルの main ブランチは削除しているので、 -d のdetached HEAD状態で切り替えます。

補足: git fetch -p オプションを常に有効化する

$ git config --global fetch.prune true

この設定をしておくと以降は -p オプションを付ける必要はありません。

$ git fetch

補足: --update-refs オプション

Git 2.38.0 以降は --update-refs オプションを使用できます。

$ git rebase --update-refs -i origin/main

とすると標準モードで取り込み、対話モードでコミットの整理が行えます。

$ git rebase origin/main
$ git rebase -i origin/main

一つのコマンドでできるようになったのでとても便利です。

毎回オプションを指定するのは面倒なのでグローバル設定しておくと良いです。

$ git config --global rebase.updateRefs true

以降は対話モードのリベースのみで標準モードの取り込みも合わせて行ってくれます。

$ git rebase -i origin/main

使わないコマンド

使用しないコマンド: git checkout

Git 2.23.0から git checkoutgit switchgit resotre に機能が分割されました。

使用しないコマンド: git pull

git fetchgit rebase で事足りるので、git pull は使用しません。

使用しないコマンド: git merge

git rebaseを使うか、git mergeを使うかはプロジェクトの運用ルールによると思います。
コミットログが綺麗になるので個人的には git rebase がオススメです。

関連記事

69
66
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
69
66

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?