1
0

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 log のコミット・グラフ例のリポジトリーを作る(その1)

Last updated at Posted at 2025-12-21

あなたはこんなアスキーアートを見たことがあるかもしれません。
git-logやgit-replayやgit-shortlogのman page の「Commit Limiting」に出てくるコミット・グラフを表した図です。

               .-A---M---N---O---P---Q
              /     /   /   /   /   /
             I     B   C   D   E   Y
              \   /   /   /   /   /
               `-------------'   X

この図と同じリポジトリを作成します。

スクリプト

AIのgrok君に頼んでおおまか作成してもらったスクリプトです。
適当に掘ったディレクトリ内で以下スクリプトを実行します。

使い方

mkdir repos
cd repos
# ここに git-hist-simple-sample.sh を置く
mkdir repo
cd repo
bash ../git-hist-simple-sample.sh

スクリプト本体

git-hist-simple-sample.sh
#!/usr/bin/env bash

set -euo pipefail

DOT_GIT=".git"

if [ -d "$DOT_GIT" ]; then
    echo "エラー: $DOT_GIT が存在するため、スクリプトを終了します。"
    echo "空のフォルダを用意してください。"
    exit 1
fi

git init --initial-branch=main

# コミット作成ヘルパー
commit() {
    echo "commit" $@
    local msg="$1"
    shift
    while [[ $# -gt 0 ]]; do
        echo -n "$2" > "$1"
        git add "$1"
        shift 2
    done
    git commit -m "$msg"
}

echo "公式ドキュメントの --ancestry-path 説明図を正確に再現中..."

# 1. 最初のコミット I(空ツリーからの初回コミット → !TREESAME)
commit "I"  foo "asdf"  quux "quux"
I=$(git rev-parse HEAD)

# 2. A(foo を "foo" に変更)
commit "A"  foo "foo"
A=$(git rev-parse HEAD)

# 3. B(A と同じ変更 → A と TREESAME)
git checkout -b side-B HEAD~1   # I に戻す
commit "B"  foo "foo"
B=$(git rev-parse HEAD)

# 4. C(foo を変更しない → 親 I と TREESAME)
git checkout -b side-C $I
git commit --allow-empty -m C	# 変更なし → TREESAME to I
C=$(git rev-parse HEAD)

# 5. D(foo を "baz" に変更)
# git checkout -q -b side-D $I
git checkout -b side-D $I
commit "D"  foo "baz"
D=$(git rev-parse HEAD)

# 6. E(quux を "xyzzy" に変更)
# git checkout -q -b side-E $I
git checkout -b side-E $I
commit "E"  quux "xyzzy"
E=$(git rev-parse HEAD)

# 7. X(新ファイル side を追加)
# git checkout -q -b side-X $I
git checkout --orphan side-X
git rm -rf . > /dev/null 2>&1
commit "X"  side "first"
X=$(git rev-parse HEAD)

# 8. Y(X に対して TREESAME )
# git checkout -q -b side-Y side-X
git checkout -b side-Y side-X
git commit --allow-empty -m Y	# 変更なし → TREESAME to X
Y=$(git rev-parse HEAD)

# メインラインに戻って順番にマージしていく(これが図の斜め線)
git checkout main

# M: A と B をマージ(trivial merge → M は両親に対して TREESAME)
echo "M:"
git merge side-B -m "M"
M=$(git rev-parse HEAD)

# N: M と C をマージ(C は変更なしだが、N で foo を "foobar" に変更)
echo "N:"
git merge --no-commit --no-ff side-C
echo -n "foobar" > foo
git add foo
git commit -m N
N=$(git rev-parse HEAD)
# O: N と D をマージ → foo が "foobarbaz" になる
# || ture は、コンフリクト発生すると exit code 1 を返すので無視する
echo "O:"
git merge --no-commit --no-ff side-D || true
echo -n "foobarbaz" > foo
git add foo
git commit -m O
O=$(git rev-parse HEAD)

# P: O と E をマージ → quux が "quux xyzzy" になる
# git merge -q side-E -m "P"
echo "P:"
git merge --no-commit --no-ff side-E || true
echo -n "quux xyzzy" > quux
git add quux
git commit -m P
P=$(git rev-parse HEAD)

# Q: P と Y をマージ → 新ファイル side が追加される
# git merge -q side-Y -m "Q"
echo "Q:"
git merge --allow-unrelated-histories -m "Q" side-Y 
Q=$(git rev-parse HEAD)

echo "完全に再現完了!"
echo "場所: $(pwd)"
echo
echo "重要なコミット(短縮ハッシュ)"
echo "  I : $(git rev-parse --short $I)"
echo "  A : $(git rev-parse --short $A)"
echo "  B : $(git rev-parse --short $B)"
echo "  M : $(git rev-parse --short $M)"
echo "  N : $(git rev-parse --short $N)"
echo "  O : $(git rev-parse --short $O)"
echo "  P : $(git rev-parse --short $P)"
echo "  Q : $(git rev-parse --short $Q)"
echo "  X : $(git rev-parse --short $X)"
echo "  Y : $(git rev-parse --short $Y)"
echo
echo "これで試してください(公式ドキュメントと全く同じ結果になります)"
echo
echo "  # 全体図"
echo "  git log --graph --oneline --decorate --all"
echo
echo "  # 普通の範囲指定(大量に出る)"
echo "  git log --oneline I..Q"
echo
echo "  # --ancestry-path を使うと、ドキュメント通りの結果!"
echo "  git log --graph --oneline --decorate --ancestry-path I..Q"
echo "  # → 表示されるのは M → N → O → P → Q の5コミットだけ!"
echo
echo "  # さらに --simplify-merges も試すと"
echo "  git log --graph --oneline --simplify-merges --ancestry-path I..Q"
echo "  # → N-O-P-Q の4コミットだけになり、まさにドキュメントの斜線部分になります"

実行例

全体表示

git log --graph --oneline --decorate --all

*   b068f04 (HEAD -> master) Q
|\  
| * 73adbb0 (side-Y) Y
| * f86655f (side-X) X
*   876db2f P
|\  
| * 979c03b (side-E) E
* |   41aae2c O
|\ \  
| * | e3df52e (side-D) D
| |/  
* |   6691af7 N
|\ \  
| * | fb91665 (side-C) C
| |/  
* |   99ccdf4 M
|\ \  
| * | d792583 (side-B) B
| |/  
* / a34e8f5 A
|/  
* 0fc8da2 I

デフォルトモード

git log --graph --oneline -- foo

*   41aae2c O
|\  
| * e3df52e D
* | 6691af7 N
|\| 
* | a34e8f5 A
|/  
* 0fc8da2 I

親の書き換え無し(--grah無し)--full-history

git log --pretty="format:%s" --full-history -- foo

Q
P
O
N
D
A
B
I

親の書き換えあり(--grahあり)--full-history

git log --graph --oneline --full-history -- foo

* b068f04 Q
*   876db2f P
|\  
* \   41aae2c O
|\ \  
| * | e3df52e D
| |/  
* | 6691af7 N
|\| 
* |   99ccdf4 M
|\ \  
| * | d792583 B
| |/  
* / a34e8f5 A
|/  
* 0fc8da2 I

--simplify-merges

git log --graph --oneline --simplify-merges -- foo

*   41aae2c O
|\  
| * e3df52e D
* | 6691af7 N
* |   99ccdf4 M
|\ \  
| * | d792583 B
| |/  
* / a34e8f5 A
|/  
* 0fc8da2 I
1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?