git logのrange指定

git logのRevisionを指定するとき、指定した範囲よりも前のRevisionからBranchを切っていて、そのBranchをMergeしたのが指定した範囲内だった場合にどう動くのだろうか?と思ったので調べてみた。

サンプルとして適当なリポジトリを作成した。コミットツリーは以下のようになっている。

*   5a04c30 Merge branch 'release/v0.2.0'  (HEAD, master)
|\
| * fc78c4c add release_0.2.0.txt  (release/v0.2.0)
| *   0172707 Merge branch 'release/v0.1.0' into develop  (develop)
| |\
| * \   f278bcf Merge branch 'feature/func21' into develop
| |\ \
| | * | 10f9fa6 add func21.txt  (feature/func21)
| * | |   fe556d4 Merge branch 'feature/func12' into develop
| |\ \ \
| | |/ /
| |/| |
| | * | ee7ffeb modify func12.txt  (feature/func12)
| | * | 3a1bbcd modify func12.txt
| | * | 1e68c15 add func12.txt
* | | |   40a4a56 Merge branch 'release/v0.1.0'
|\ \ \ \
| | |_|/
| |/| |
| * | | a74118d release v0.1.0  (release/v0.1.0)
| |/ /
| * |   4f26e7d Merge branch 'feature/func11' into develop
| |\ \
| | * | 335ceba modify func11.txt  (feature/func11)
| * | |   df346c9 Merge branch 'feature/func13' into develop
| |\ \ \
| | * | | ca391a4 add func13.txt  (feature/func13)
| * | | |   c8fd460 Merge branch 'feature/func11' into develop
| |\ \ \ \
| | |/ / /
| |/| / /
| | |/ /
| | * | 0836fd6 add func11.txt
| | |/
| * | 00f05c1 modify funtions.txt
| |/
| * 2ec9d3d add functions.txt
|/
* 0b696bf Update base.txt
* b22f709 First Commit

少し長々としているが、想定状況はこんな感じ。

  • RepositoryはGit flowのルールで運用している。
  • 以前にv0.1.0をリリースしており、現在はv0.2.0をリリースしたばかり。

v0.2.0で開発したCommit一覧を取得したいけれど、v0.2.0にはv0.1.0時代からの修正(v0.1.0時点からのBranch)であるfeature/func12をMergeしている。このとき、feature/func12のCommitは一覧にあらわれるか否か?

$ git log --oneline release/v0.1.0..release/v0.2.0
fc78c4c add release_0.2.0.txt
0172707 Merge branch 'release/v0.1.0' into develop
f278bcf Merge branch 'feature/func21' into develop
fe556d4 Merge branch 'feature/func12' into develop
ee7ffeb modify func12.txt
10f9fa6 add func21.txt
3a1bbcd modify func12.txt
1e68c15 add func12.txt

「 ですよねー」という結果になりましたが、もちろん現れます。

git log a..bとしたとき、aからbまでのCommit一覧なので、bに含まれていてaに含まれていないCommitを表示します。

feature/func11は途中で一度mergeしているので、もう少しわかりやすい例としてこれを使います。

$ git log --oneline c8fd460..4f26e7d
4f26e7d Merge branch 'feature/func11' into develop
df346c9 Merge branch 'feature/func13' into develop
335ceba modify func11.txt
ca391a4 add func13.txt

$ git log --oneline 00f05c1..4f26e7d
4f26e7d Merge branch 'feature/func11' into develop
df346c9 Merge branch 'feature/func13' into develop
335ceba modify func11.txt
c8fd460 Merge branch 'feature/func11' into develop
ca391a4 add func13.txt
0836fd6 add func11.txt

c8fd460は「0836fd6 add func11.txt」を知っているので一覧に表示されませんが、c8fd460の1つ前である00f05c1は0836fd6を知らないので一覧に表示されます。

git diffでも同様です。v0.1.0で修正したファイルの一覧が欲しい場合やv0.2.0での修正ファイル一覧が欲しい場合は以下のようになります。

$ git diff 2ec9d3d..release/v0.1.0 --name-status
A       func11.txt
A       func13.txt
M       functions.txt
A       release_0.1.0.txt

$ git diff release/v0.1.0..release/v0.2.0 --name-status
A       func12.txt
A       func21.txt
A       release_0.2.0.txt

これだけ長々と書いてあれなのですが、この仕様についてGitドキュメントのgitrevisionのページににしっかり書いていますね。

<rev1>..<rev2>

Include commits that are reachable from <rev2> but exclude those that are reachable from <rev1>. When either <rev1> or <rev2> is omitted, it defaults to HEAD.

では。