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?

歴史を一つのコミットにまとめたブランチと元のブランチを同期する

Last updated at Posted at 2025-07-19

概要

gitリポジトリの運用にあたって、ある地点より以前の歴史(commit、blobなど)を一つのコミットにまとめたブランチを作成した上で、そのブランチに元のブランチの内容をマージして同期する方法を説明します。

例えば、あるリポジトリの内容について、一定以前の歴史を一つにまとめることで、リポジトリのサイズを抑えたり、共有したくない歴史を隠すためのブランチを作成して、別のremoteリポジトリにpushし、そのブランチに対して元リポジトリの変更をマージし続けるといった運用を想定しています。(そんな需要は滅多にないと思いつつ...)

手順

過去の歴史を一つにまとめた新しいブランチの作成

では、masterブランチの内容から、過去の歴史を一つにまとめた新しいブランチを作成していきます。

これが現状のブランチです。
今からmasterのHEADの内容をそのままに、歴史を潰した新たなブランチを作成します。

~/work/tmp/git-repo master
$ git log --oneline                                                                                                                                
02c4027 (HEAD -> master) a-5
95f6a9f a-4
91439fb a-3
14bbaa5 a-2
92c187d a-1

HEADの内容から新規コミットを作るために git commit-tree を使います。このコマンドはツリーオブジェクトのハッシュを指定することで、指定されたtreeの内容から新規コミットを作成してくれます。( 02c4027^{tree} はコミットオブジェクト02c4027に紐づくツリーオブジェクトを指定する記法)

こうすることでファイルの内容はそのままに、歴史を消した一つのコミットにすることができます。ここでは a-5 02c4027 のコミットまでの歴史を一つにまとめてみます。

~/work/tmp/git-repo master
$ echo 'init' | git commit-tree 02c4027^{tree}                                                        
f9ba9385fa4d03f0d9b97fdf172bab077e9b9a9f

歴史をまとめた一つのコミット f9ba938 が作成されました。

作成したコミットから mirror ブランチを作成します。当然コミットは一つしかありません。またHEADのツリーオブジェクトの内容を引き継いでいるため、masterとの差分も存在しません。

~/work/tmp/git-repo master
$ git co -b mirror f9ba9385fa4d03f0d9b97fdf172bab077e9b9a9f                      
Switched to a new branch 'mirror'

# コミットは一つだけ。歴史が潰れている。
~/work/tmp/git-repo mirror
$ git log --oneline                                                       
f9ba938 (HEAD -> mirror) init

# 2wayでdiffを取っても差分が出力されない
~/work/tmp/git-repo mirror
$ git --no-pager diff master..mirror 

~/work/tmp/git-repo mirror

masterブランチに追加されたコミットを同期する

ここからが本題です。上記で作成したmirrorに、masterに新しくコミットされた内容を同期していきます。

まずはmasterに適当な内容で2つほどコミット b-1 b-2 を追加します。

~/work/tmp/git-repo master!
$ echo "hello" > sample.txt & git add sample.txt & git commit -m "b-1"                                                           
[master 0397b61] b-1
 1 file changed, 1 insertion(+)
 create mode 100644 sample.txt                                                       

~/work/tmp/git-repo master!
$ echo "world" > hoge.txt & git add hoge.txt & git commit -m "b-2"                                                           
[master 6c5b4d7] b-2
 1 file changed, 1 insertion(+)
 create mode 100644 hoge.txt

先ほどmirrorを作成した時点のHEAD a-5 02c4027 から2つコミットが増えました。ファイル差分も発生しています。

~/work/tmp/git-repo master
$ git log --oneline                                                       
6c5b4d7 (HEAD -> master) b-2
0397b61 b-1
02c4027 a-5
95f6a9f a-4
91439fb a-3
14bbaa5 a-2
92c187d a-1

~/work/tmp/git-repo master
$ git diff master..mirror                                                          
diff --git a/hoge.txt b/hoge.txt
deleted file mode 100644
index cc628cc..0000000
--- a/hoge.txt
+++ /dev/null
@@ -1 +0,0 @@
-world
diff --git a/sample.txt b/sample.txt
deleted file mode 100644
index ce01362..0000000
--- a/sample.txt
+++ /dev/null
@@ -1 +0,0 @@
-hello

ではこのmasterをmirrorに取り込んでいきます。

まずはマージ用のブランチ merge-to-mirror-1 を作成します。

~/work/tmp/git-repo master
$ git checkout -b merge-to-mirror-1
Switched to a new branch 'merge-to-mirror-1'

masterとmirrorは共通祖先コミットを持たない歴史の異なるブランチのため、そのままマージすることはできません。そこで git rebase --onto を利用します。

git rebase --onto {a} {b}a のコミットの上に b のコミットから先のコミットを積み上げた状態を作り出します。

ここでは先ほど git commit-tree で作成したコミット f9ba938 の上に、そのコミットのもとになった 02c4027 (a-5)を積み上げます。

~/work/tmp/git-repo merge-to-mirror-1
$ git rebase --onto f9ba938 02c4027 --committer-date-is-author-date                                 
Successfully rebased and updated refs/heads/merge-to-mirror-1.

これでmasterに積まれた2つのコミット b-1 b-2 が f9ba938 の上に積まれました。(masterとはparentが異なるため、2つのコミットのコミットハッシュは変わり、内容を同一にする新たな歴史となっています。)

~/work/tmp/git-repo merge-to-mirror-1
$ git log --oneline                                                       
147c0b7 (HEAD -> merge-to-mirror-1) b-2
1673726 b-1
f9ba938 (mirror) init

このブランチは f9ba938 が共通祖先となるためmirrorにマージが可能です。

~/work/tmp/git-repo mirror
$ git merge merge-to-mirror-1                                               
Updating f9ba938..147c0b7
Fast-forward
 hoge.txt   | 1 +
 sample.txt | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 hoge.txt
 create mode 100644 sample.txt

 ~/work/tmp/git-repo mirror
$ git log --oneline                                                       
147c0b7 (HEAD -> mirror, merge-to-mirror-1) b-2
1673726 b-1
f9ba938 init

これでmasterに積まれたコミットと同じ(内容の)コミットをmirrorに同期することができました。

さらに追加されたコミットを同期する

ここまでで本記事の説明はおよそ完了していますが、最後に、masterに積まれたコミットを同期し続けるために重要なことを説明します。

ひとまずmasterに更に2つのコミット c-1 c-2 を追加して解説を進めます。

~/work/tmp/git-repo master
$ git log --oneline
e80b38e (HEAD -> master) c-2
9c42817 c-1
6c5b4d7 b-2
0397b61 b-1
02c4027 a-5
95f6a9f a-4
91439fb a-3
14bbaa5 a-2
92c187d a-1

そして先程と同じように git rebase --onto を利用して、f9ba938 の上にコミットを積み替えます。

ここで、説明のために、先程はrebaseに指定してした --committer-date-is-author-date を外して実行します。

~/work/tmp/git-repo merge-to-mirror-2-test
$ git rebase --onto f9ba938 02c4027                                                         
Successfully rebased and updated refs/heads/merge-to-mirror-2-test.

このブランチのコミットを見てみるとどうでしょうか、先程mirrorに取り込み済みのb-1とb-2のコミットハッシュが変更されてしまいました。

a703e4b (HEAD -> merge-to-mirror-2-test) c-2
bd55655 c-1
e9f0a01 b-2 # 先ほどは 147c0b7 だった
cc9d156 b-1 # 先ほどは 1673726 だった
f9ba938 init

ここで原因調査のために、master、mirror、merge-to-mirror-2-testそれぞれのb-1コミットの中身を確認してみましょう。

master の b-1 (オリジナル)

$ git cat-file -p 0397b61                                                         
tree 0f114833b7e9fe060ebd024e464033024992f6d3
parent 02c4027167ca4f1a876eb897ecadad0a6af304c6
author genta <****@gmail.com> 1752892544 +0900
committer genta <****@gmail.com> 1752892544 +0900

b-1

mirror の b-1

parentはオリジナル異なりますが、それ以外は同じです。

$ git cat-file -p 1673726                                                         
tree 0f114833b7e9fe060ebd024e464033024992f6d3
parent f9ba9385fa4d03f0d9b97fdf172bab077e9b9a9f
author genta <****@gmail.com> 1752892544 +0900
committer genta <****@gmail.com> 1752892544 +0900

b-1

merge-to-mirror-2-test の b-1

mirrorのb-1とparentは等しいですが、committerのdateが変更されてしまっています。

$ git cat-file -p cc9d156                                                         
tree 0f114833b7e9fe060ebd024e464033024992f6d3
parent f9ba9385fa4d03f0d9b97fdf172bab077e9b9a9f
author genta <****@gmail.com> 1752892544 +0900
committer genta <****@gmail.com> 1752895604 +0900

b-1

どうやら、committerのdateが変更されてしまっているために同じコミットでもコミットハッシュが変わってしまっているようです。

git rebase のデフォルトの挙動は、committerのdateをrebaseした日付に書き換えてしまうため、このような問題が発生します。

こちらを回避するために git rebase --onto--committer-date-is-author-date を指定することでauthorのdateとcommitterのdateを揃えることができ、複数回rebaseを行ってもparentが同一であればコミットハッシュを維持することができます。

では、改めてmasterの内容をmirrorに取り込み直しましょう。

~/work/tmp/git-repo merge-to-mirror-2
# --committer-date-is-author-date を指定する!
$ git rebase --onto f9ba938 02c4027 --committer-date-is-author-date                                 
Successfully rebased and updated refs/heads/merge-to-mirror-2.

~/work/tmp/git-repo merge-to-mirror-2
$ git --no-pager log 
cfacc5d (HEAD -> merge-to-mirror-2) c-2
b128de2 c-1
147c0b7 (mirror, merge-to-mirror-1) b-2
1673726 b-1
f9ba938 init

どうでしょうか、b-1、b-2のコミットハッシュが維持されていますね。

これであれば、このままmerge-to-mirror-2をmirrorにマージすることができます。

~/work/tmp/git-repo mirror
$ git merge merge-to-mirror-2                                               
Updating 147c0b7..cfacc5d
Fast-forward
 README.md  | 1 +
 sample.txt | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
 create mode 100644 README.md

~/work/tmp/git-repo mirror
$ git log --oneline                                                       
cfacc5d (HEAD -> mirror, merge-to-mirror-2) c-2
b128de2 c-1
147c0b7 (merge-to-mirror-1) b-2
1673726 b-1
f9ba938 init

以降はmasterが進む度に、masterブランチに git rebase --onto f9ba938 02c4027 --committer-date-is-author-date を実行したブランチを作成することで、mirrorにマージするブランチを作り続けることができます。

これで本流のブランチ(master)から、ある地点以前の歴史を一つのコミットにまとめた新たな歴史のブランチ(mirror)に、元のブランチの変更を同期し続けることが実現できます。

参考記事

https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-Git-%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E7%BD%AE%E3%81%8D%E6%8F%9B%E3%81%88
https://git-scm.com/docs/git-commit-tree
https://www.abap34.com/posts/git_date.html

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?