MIXI DEVELOPERS NOTE
🪓

アウトローGit術

2022/12/10に公開

この記事は MIXI DEVELOPERS Advent Calendar 2022 - Qiita の10日目の記事です。

はじめに

みなさん、Git使ってますか? 使ってますよね。

ところでGitの運用にはある種のお作法のようなものがあるように思います。
Gitの初学者は一般的に「行儀の良い」お作法を身につけることが求められますが、此度少しだけ、ほんの少しだけワルになってみるのはいかがでしょうか。

対象読者

  • Gitに面倒くささ、息苦しさ、窮屈さを感じている人

アウトローにも超えちゃいけねえ一線があります

本記事で紹介する操作にはコミットログを書き換えるものが多く、書き換えたコミットをプッシュする際には強制プッシュが必要になります。
しかし、強制プッシュがリモートリポジトリを破壊する危険を伴うのはご存知の通りです。
まさか他人のコミットを消し飛ばした日にはアウトローの名折れですので、以下のことを意識することを強くおすすめします。

  • 複数人が使用しているブランチに強制プッシュをしない
  • 常に -f ではなく --force-with-lease オプションを使用する

他人が見ているブランチに強制プッシュすると大抵めんどくさいことになりますので、自分しか見ていないブランチでのみ使用するのが安心です。
--force-with-lease オプションを使うことで他人のコミットを消しそうになった時にエラーになる場面が多くなりますが、絶対ではないのでプッシュ先ブランチをよく確認しましょう。

参考: git push --force-with-leaseはいつも安全? - Qiita

誤字やミスを気づかれる前になかったことにしたい

人はメールの送信ボタンを押した瞬間に注意力が跳ね上がることで有名です。
さらに同様の場面としてコードをコミットした瞬間、PRを出した瞬間などが挙げられます。
コミットしてしまったコード、もしくはコミットメッセージに発見した誤字やミスを他人に気づかれる前に修正するには

git commit --amend

を使用します。

誤字やミスを発見したらおもむろに修正をステージングした後、上記のコマンドを実行することで最新のコミットを書き換えることができます。

参考: 1. commit --amend|サル先生のGit入門【プロジェクト管理ツールBacklog】

計画的にコミットするのを諦める

コミットの単位を意識しながらプログラムを書くのがしんどい場合は、一旦適当にコミットしながら進めた後で

git rebase -i

を使用して複数のコミットをひとつにまとめる方法もあります。

また他にも、

git reset <戻る先のコミットID> --soft

で一旦コミットを消し、

git add -p

などを活用して都合の良いコミットログを創造することもできます。
後者の方法は一度も実行したことのないコミットを作り出すこともできてしまうため、うっかりコンパイルが通らないなどのコミットが爆誕するおそれがあるので注意が必要です。

参考:

PRのレビューを待ちながら作業を進めたい

PRのレビューを待ちながら、その実装に依存する作業を進めたいシーンは多々あるかと思います。
そんな時はそのPRのブランチから新しいブランチを生やして作業をすることになるわけですが、そのまま新しくPRを立てるとコミットが必要以上に多く見えてしまいます。
そんな時は依存先のPRがマージされ次第、

git rebase <マージ先ブランチ名>

を使用することで、あたかもマージを待ってからブランチを作成したように装うことができます。

rebaseの具体例

feature/pr1 がレビュー待ちのブランチで、 feature/pr2 がそれに依存するブランチです。

* commit 010df705666589c8a847b7ac4377d57014b9e518 (HEAD -> develop)
| Author: hissa
| Date:   Fri Dec 9 16:34:36 2022 +0900
|
|     Second commit
|
| * commit 5b7c26c316959c132c5d82d0400392811552c059 (feature/pr2)
| | Author: hissa
| | Date:   Fri Dec 9 16:28:48 2022 +0900
| |
| |     Add .DS_Store
| |
| * commit 9a0346500625b056cec85b8abd1297c11b7652d9 (feature/pr1)
|/  Author: hissa
|   Date:   Fri Dec 9 16:26:49 2022 +0900
|
|       Ignore .gitignore
|
* commit 11de83299eacafadf9eb230ccff82ba0bb76c620 (main)
  Author: hissa
  Date:   Fri Dec 9 16:22:28 2022 +0900

      First commit

レビューが通って feature/pr1 がdevelopにマージされたとするとこうなります。

*   commit aced6994e9cf7e698f6ac6b86d503910c47bdffb (HEAD -> develop)
|\  Merge: 010df70 9a03465
| | Author: hissa
| | Date:   Fri Dec 9 16:42:15 2022 +0900
| |
| |     Merge branch 'feature/pr1' into develop
| |
* | commit 010df705666589c8a847b7ac4377d57014b9e518
| | Author: hissa
| | Date:   Fri Dec 9 16:34:36 2022 +0900
| |
| |     Second commit
| |
| | * commit 5b7c26c316959c132c5d82d0400392811552c059 (feature/pr2)
| |/  Author: hissa
| |   Date:   Fri Dec 9 16:28:48 2022 +0900
| |
| |       Add .DS_Store
| |
| * commit 9a0346500625b056cec85b8abd1297c11b7652d9 (feature/pr1)
|/  Author: hissa
|   Date:   Fri Dec 9 16:26:49 2022 +0900
|
|       Ignore .gitignore
|
* commit 11de83299eacafadf9eb230ccff82ba0bb76c620 (main)
  Author: hissa
  Date:   Fri Dec 9 16:22:28 2022 +0900

      First commit

ここで feature/pr2 をチェックアウトし、 git rebase develop を実行すると以下のようになります。

* commit 5e1d2287267d1695d5f48fdfb1338cfa30402c65 (HEAD -> feature/pr2)
| Author: hissa
| Date:   Fri Dec 9 16:28:48 2022 +0900
|
|     Add .DS_Store
|
*   commit aced6994e9cf7e698f6ac6b86d503910c47bdffb (develop)
|\  Merge: 010df70 9a03465
| | Author: hissa
| | Date:   Fri Dec 9 16:42:15 2022 +0900
| |
| |     Merge branch 'feature/pr1' into develop
| |
| * commit 9a0346500625b056cec85b8abd1297c11b7652d9 (feature/pr1)
| | Author: hissa
| | Date:   Fri Dec 9 16:26:49 2022 +0900
| |
| |     Ignore .gitignore
| |
* | commit 010df705666589c8a847b7ac4377d57014b9e518
|/  Author: hissa
|   Date:   Fri Dec 9 16:34:36 2022 +0900
|
|       Second commit
|
* commit 11de83299eacafadf9eb230ccff82ba0bb76c620 (main)
  Author: hissa
  Date:   Fri Dec 9 16:22:28 2022 +0900

      First commit

まるでdevelopからブランチを生やしたかのようなログになりました!

参考: 7. rebaseでマージする|サル先生のGit入門【プロジェクト管理ツールBacklog】

この力は人を救うためにあります

あなたのアウトローな振る舞いが誰かを混乱させてしまうことがあるかもしれません。
それを救うのもまた、我々のアウトローGit術なのです。熱いぜ。
本記事内で「コミットを消す」と表現している箇所がありますが、実際にはコミットは消えるのではなく、コミットIDを知る手段がなくなるだけです。
詰んだ、と思ったら思い出してください。

git reflog

直近で辿ったコミットの履歴が出力されます。
探し物はきっと見つかるでしょう。

参考: Gitを使ってやらかした時、git reflogさえ使えればわりかしなんとかなる - Qiita

おわりに

ここまでお読みいただきありがとうございます。
今回は場面を想起しやすいよう、シチュエーションとコマンドを並べることにしましたが、しっかりとGitの挙動を理解するには私の大好きなスライドである「こわくない Git - SlideShare」を是非ご覧ください。

今回紹介したアウトローGit術はプロジェクトによって使えないものもあるかもしれません。
例えばPRが既にオープンされたブランチへの強制プッシュの是非もプロジェクトによって違ってくるように思います。

自分自身、そして周りを幸せにする為にこのアウトローGit術がお役に立てば幸いです。
リポジトリ管理者の方々におかれましては、私のような者が開発メンバーに潜むのを見越してブランチ保護を適切に設定するようお願いいたします(傲慢)。

MIXI DEVELOPERS NOTE
MIXI DEVELOPERS NOTE

Discussion