Gitで以下の操作をした後にbranch_a上でgit logを実行した際のログが想定と違ったので、出力の意味を理解してみました。
行った操作
mainブランチからbranch_aとbranch_bを作成する- ※
mainブランチ上でgit switch -c branch_aとgit switch -c branch_bを実行
- ※
branch_aで任意のコミットをする(以下コミット1)branch_bで任意のコミットをする(以下コミット2)branch_aにbranch_bをマージbranch_a上でgit merge branch_bを実行
コミットグラフの図
gitGraph commit id: "root" branch branch_a branch branch_b checkout branch_a commit id: "コミット1" checkout branch_b commit id: "コミット2" checkout branch_a merge branch_b id: "マージコミット"
この状態でbranch_a上でgit logを実行します。
私は以下の順でログが出力されると思っていました。
- マージコミット(
branch_a) - コミット1(
branch_a)
実際には以下のログが出力されました。
- マージコミット(
branch_a) - コミット2(
branch_b) - コミット1(
branch_a)
理由
公式ドキュメントを読むと、git logコマンドは「リンクを辿って到達可能なコミットを一覧表示する」とあります。
List commits that are reachable by following the parent links from the given commit(s)
従って、特定のブランチのログではなく、マージ元のブランチも含めて到達可能なコミットを全て表示する仕様であると解釈できます。
加えて、『実用 Git』には「ログの要素は時系列順ではなく、コミットのトポロジカルソートになっている(p.18)」とあります。
以上より、git logでbranch_a上のコミットだけではなく、branch_b上のコミットも表示された理由がわかりました。
カレントブランチのログだけ表示したい場合
カレントブランチのログだけ表示したい場合は、git log --first-parentというオプションが使えます。
公式ドキュメントにも、まさにmergeによって入り込んだコミットを無視したい場合に使うオプションであると説明されています。
This option can give a better overview when viewing the evolution of a particular topic branch, because merges into a topic branch tend to be only about adjusting to updated upstream from time to time, and this option allows you to ignore the individual commits brought in to your history by such a merge.
https://git-scm.com/docs/git-log#Documentation/git-log.txt---first-parent
マージ前の状態に戻したい場合
以下で実現できます。
git log --first-parentでカレントブランチのマージコミットの直前のコミットを調べるgit reset --hard {1.で調べたコミットID}を実行