最近某OSSに出されたPRが、git merge --squash <branch>
でマージされたことにより、コミットのAuthorが書き換えられてしまったことが一部界隈で話題になっていました。この件にはマージを行った人に悪意はなかったようなのですが、gitの理解不足により生じてしまった案件だとすると悲しい話なので一応メモ
何が起きたか
-
コミッターが複数の内容が含まれたPRを送った
-
管理者はその中の一部の内容だけをマージするために、管理者はgit merge --squashを実施し、コミットを改変した上でmergeを実施した ←これが問題
-
コードの内容はコミッターのものなのに、Authorだけ管理者にすげ変わってしまいコミッターのモチベを損ねた
そもそもsquashするとどうなるの
ここに分かりやすくまとまっています。
アジャイルSEを目指すブログ 図で分かるgit-mergeの--ff, --no-ff, --squashの違い
上の図のように、他ブランチを取り込んだ状態の差分をワークツリーとインデックスに反映させるコマンドです。
この状態はまだ未コミットの状態であるため以下のような操作が可能となります。
- 複数のコミットによる差分を1つのコミットにまとめた形でコミットできる
- まだ未コミットの状態なので、**取り入れた差分を編集できる
しかし、下記の理由で自分以外のコミットに対してはsquashは望ましくないと考えられます。
- デフォルトではsquash後の差分をコミットした人がAuthorになってしまう。→本来のコミッタのcontributionを消してしまう
- Author云々の前に、人のコミットした歴史を別の人が改変するのは望ましくない
どうすればよいか
とはいえ、他人のコミットマージしたいけど一部はマージしたくないよ、って時はどうすれば良いのか。
色んな方法があると思いますが、見たことがあるのを4つくらいあげてみます。
git cherry-pick <commit id>
を使う
コミット単位でマージするかしないかが切り分けられる場合はcherry-pickを使う方法があります。
git cherry-pick <commit id>
は別ブランチの特定のコミットをマージする機能です。
git cherry-pick fadb18b1771895b5fd8f11114514dd951decb67d #指定のコミットをマージ
git cherry-pick develop~3..develop #範囲指定 最新から3つ目までのコミットをマージ
これは勿論既に存在するcommitをマージした形にするので、authorなどが書き換わるなども当然ないです。
[技術][Git]git-cherry-pickを掘り下げる
rebase --interactiveを使う
@wataashさんのコメントを受けて追加
git rebase --interactiveを使うと、squashコミットの最初の著者になるそうです。
どうしてもsquashしたい際はこれがよさそう。
詳しくは@wataashさんの記事を
git rebase --interactive で誰がauthorになるか問題
コミッターにsquashしてもらう
どうしても1つのコミットにまとめたいんだって話であったり、コミット単位じゃマージするかしないかが切り分けられないよって話であればコントリビュータにお願いしてsquashしてもらうのも1つです。
某OSSでは、コントリビュータである@mattnさん側から指示通りにsquashするよ〜って提案をしてらっしゃいますね。
mergeした後に自分で編集してコミットする
まぁ正攻法ですかね。commitを1つにまとまられなかったり、ログが汚くなってしまうかもしれませんがそれも1つの歴史なので無理やり改変しなくてもいいのではと思える人はこちらの選択肢も。
co-author機能を使う
そこまでする必要あるかという話もありますが、話のたねに。
一応githubにはco-author機能というものがあり、コミットメッセージにco-authorの情報を記述すればcontributionの一覧にそのユーザを明記することができます。
git commit -m "Refactor usability tests.
>
>
Co-authored-by: name <name@example.com>
Co-authored-by: another-name <another-name@example.com>"
詳しくは↓を
https://help.github.com/articles/creating-a-commit-with-multiple-authors/
ポエム
なんか色々面倒だし、authorとか誰でもいいしとりあえずログを綺麗にしたいぜ!って人もいるかもしれませんが、個人的にはコントリビュータには最大限の敬意を払ったほうが良いと思うし、他人の成果を横取りする人間だと誤解されたくもないので注意しても損ではないかなと思ったり思わなかったり。
参考になる記事:
git rebase --interactive で誰がauthorになるか問題
GitHubの3種類のマージを理解する