ネットワークなどの理由でサーバにアクセスできないときにGit のコミット情報を送るときに使える便利機能 git bundleについて説明します。


Git で複数人で開発するときは、通常はサーバにリモートリポジトリを用意してみんなでそこへ git push, git pull してコードを共有すると思います。 しかしたとえば他社のかたと共同開発する場合にセキュリティの問題や契約の問題で、 リモートリポジトリを共有できないこともあると思います。 この場合に便利なgit bundle コマンドを紹介します。

いくつかの方法

リモートリポジトリを使わずにgitでのコード差分を共有する一番素朴な方法はgit diff の出力を共有することです。 しかしこの方法はコミット時の commiter や author の情報は失われてしまいます。 あまりおすすめできません。 もう少し賢い方法は、git format-patchを使うことです。 これは下記のようにメールで転送するようなヘッダ情報を付加してくれます。 このヘッダからパッチを当てるときにauthorを生成します。 ただし1つのコミットに1つのパッチファイルとなるので数十のコミットを共有するのには向きません。

1
2
3
4
5
6
7
8
9
From 733e90dfe942bd60e8c386b0be79093ffc72fa9a Mon Sep 17 00:00:00 2001
From: NAGAYASU Shinya
Date: Thu, 26 Jan 2023 00:03:14 +0900
Subject: [PATCH 1/2] =?UTF-8?q?elisp/=20elpa/=20=E3=82=92=E7=84=A1?=
 =?UTF-8?q?=E8=A6=96=E3=81=97=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB?=
 =?UTF-8?q?=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

さらに賢い方法は git bundleを使うことです。これは pushした場合に転送するデータと同じものを1つのファイルにまとめてくれます。 つまり通常のgit commit git push するときと同じようなことができます。 この記事ではこの git bundle を説明します。

git bundle

git bundle のかんたんな使い方を説明します。

バンドルファイルの作り方

まず共有したいコードを通常通り git commit します。 ここでは下記のようにorigin/masterから1つコミットしたとします(7e6e483)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
* commit 7e6e483 (HEAD)
| Author:     NAGAYASU Shinya
| AuthorDate: Fri Jan 27 23:15:23 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Fri Jan 27 23:15:23 2023 +0900
|
|     ime 追加
|
* commit dad82e3 (origin/master, origin/HEAD)
| Author:     NAGAYASU Shinya
| AuthorDate: Mon Jan 23 23:46:02 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Mon Jan 23 23:46:02 2023 +0900
|
|     いくつかの変数をダイナミックバインディングに変更

このコミットのバンドルファイルを作成します。 下記のコマンドでHEADからmasterまで、つまり最新のコミットをバンドル化できます。

1
git bundle create dot_emacs_20230127.bundle HEAD master

この作成したファイル dot_emacs_20230127.bundle をコードを共有したい人に何かしらの方法で送ります。 これでバンドルの作成は終わりです。

バンドルファイルの適用の仕方

受け取ったひとのコミットが下記のようになっていたとします。 バンドルをつくったひとより3つコミットが進んだ状態です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
* commit 733e90d (HEAD -> master, origin/master, origin/HEAD)
| Author:     NAGAYASU Shinya
| AuthorDate: Thu Jan 26 00:03:14 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Thu Jan 26 00:03:14 2023 +0900
|
|     elisp/ elpa/ を無視しないように修正
|
* commit d96b8b2
| Author:     NAGAYASU Shinya
| AuthorDate: Wed Jan 25 23:45:14 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Wed Jan 25 23:52:03 2023 +0900
|
|     C-h をバックスペースに変更
|
* commit 7fb8ef8
| Author:     NAGAYASU Shinya
| AuthorDate: Tue Jan 24 23:27:02 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Tue Jan 24 23:27:02 2023 +0900
|
|     magit を追加してみた
|
* commit dad82e3
| Author:     NAGAYASU Shinya
| AuthorDate: Mon Jan 23 23:46:02 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Mon Jan 23 23:46:02 2023 +0900
|
|     いくつかの変数をダイナミックバインディングに変更
|

まず、受け取ったバンドルファイルを適用できるかを git bundle verifyで確認します。 下記のように okay と表示されれば大丈夫です。

1
2
3
4
5
6
$ git bundle verify  ./dot_emacs_20230127.bundle
The bundle contains these 2 refs:
d62f68eb5a2b7cf036355aa8f1a16c9af35b8499 HEAD
d62f68eb5a2b7cf036355aa8f1a16c9af35b8499 refs/heads/master
The bundle records a complete history.
./dot_emacs_20230127.bundle is okay

git fetch でバンドルを取り込みます。 下記のようにFETCH_HEADが更新されます。

1
2
3
$ git fetch ./dot_emacs_20230127.bundle
From ./dot_emacs_20230127.bundle
 * branch            HEAD       -> FETCH_HEAD

git logFETCH_HEAD を確認します。 期待通りコミットが入ったのが確認できます。 ただしバンドル作成時と受取時でコミットの状態が異なったので枝分かれてしまっています。 merge してもいいのですが、ここではログが1本線になるようにrebaseをしてみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ git log --graph --decorate --pretty=fuller --all --abbrev-commit FETCH_HEAD
* commit d62f68e
| Author:     NAGAYASU Shinya
| AuthorDate: Fri Jan 27 16:15:23 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Fri Jan 27 16:15:23 2023 +0900
|
|     ime 追加
|
| * commit 733e90d (HEAD -> master, origin/master, origin/HEAD)
| | Author:     NAGAYASU Shinya
| | AuthorDate: Thu Jan 26 00:03:14 2023 +0900
| | Commit:     NAGAYASU Shinya
| | CommitDate: Thu Jan 26 00:03:14 2023 +0900
| |
| |     elisp/ elpa/ を無視しないように修正
| |
| * commit d96b8b2
| | Author:     NAGAYASU Shinya
| | AuthorDate: Wed Jan 25 23:45:14 2023 +0900
| | Commit:     NAGAYASU Shinya
| | CommitDate: Wed Jan 25 23:52:03 2023 +0900
| |
| |     C-h をバックスペースに変更
| |
| * commit 7fb8ef8
|/  Author:     NAGAYASU Shinya
|   AuthorDate: Tue Jan 24 23:27:02 2023 +0900
|   Commit:     NAGAYASU Shinya
|   CommitDate: Tue Jan 24 23:27:02 2023 +0900
|
|       magit を追加してみた
|
* commit dad82e3
| Author:     NAGAYASU Shinya
| AuthorDate: Mon Jan 23 23:46:02 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Mon Jan 23 23:46:02 2023 +0900
|
|     いくつかの変数をダイナミックバインディングに変更
|

まずは FETCH_HEAD に移動します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
$ git checkout FETCH_HEAD
$ git log --graph --decorate --pretty=fuller --all --abbrev-commit
* commit d62f68e (HEAD)
| Author:     NAGAYASU Shinya
| AuthorDate: Fri Jan 27 16:15:23 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Fri Jan 27 16:15:23 2023 +0900
|
|     ime 追加
|
| * commit 733e90d (origin/master, origin/HEAD, master)
| | Author:     NAGAYASU Shinya
| | AuthorDate: Thu Jan 26 00:03:14 2023 +0900
| | Commit:     NAGAYASU Shinya
| | CommitDate: Thu Jan 26 00:03:14 2023 +0900
| |
| |     elisp/ elpa/ を無視しないように修正
| |
| * commit d96b8b2
| | Author:     NAGAYASU Shinya
| | AuthorDate: Wed Jan 25 23:45:14 2023 +0900
| | Commit:     NAGAYASU Shinya
| | CommitDate: Wed Jan 25 23:52:03 2023 +0900
| |
| |     C-h をバックスペースに変更
| |
| * commit 7fb8ef8
|/  Author:     NAGAYASU Shinya
|   AuthorDate: Tue Jan 24 23:27:02 2023 +0900
|   Commit:     NAGAYASU Shinya
|   CommitDate: Tue Jan 24 23:27:02 2023 +0900
|
|       magit を追加してみた
|
* commit dad82e3
| Author:     NAGAYASU Shinya
| AuthorDate: Mon Jan 23 23:46:02 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Mon Jan 23 23:46:02 2023 +0900
|
|     いくつかの変数をダイナミックバインディングに変更
|

rebaseして分岐元をずらします。 期待通りログが一本化できました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
$ git rebase -i origin/master
$ git log --graph --decorate --pretty=fuller --all --abbrev-commit
* commit 0d325ce (HEAD)
| Author:     NAGAYASU Shinya
| AuthorDate: Fri Jan 27 16:15:23 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Sun Jan 29 19:27:48 2023 +0900
|
|     ime 追加
|
* commit 733e90d (origin/master, origin/HEAD, master)
| Author:     NAGAYASU Shinya
| AuthorDate: Thu Jan 26 00:03:14 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Thu Jan 26 00:03:14 2023 +0900
|
|     elisp/ elpa/ を無視しないように修正
|
* commit d96b8b2
| Author:     NAGAYASU Shinya
| AuthorDate: Wed Jan 25 23:45:14 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Wed Jan 25 23:52:03 2023 +0900
|
|     C-h をバックスペースに変更
|
* commit 7fb8ef8
| Author:     NAGAYASU Shinya
| AuthorDate: Tue Jan 24 23:27:02 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Tue Jan 24 23:27:02 2023 +0900
|
|     magit を追加してみた
|
* commit dad82e3
| Author:     NAGAYASU Shinya
| AuthorDate: Mon Jan 23 23:46:02 2023 +0900
| Commit:     NAGAYASU Shinya
| CommitDate: Mon Jan 23 23:46:02 2023 +0900
|
|     いくつかの変数をダイナミックバインディングに変更
|

まとめ

今回はGit でリモートリポジトリを共有できないときのコードの共有方法を説明しました。 git bundle でコミットした情報を1つのファイルにまとめそれを共有します。 あとは受け取り側でfetchすればコードが共有できます。 もしブランチが枝分かれしたりしたらrebaseなどで調整してください

詳細は 7.12 Git のさまざまなツール - バンドルファイルの作成 参照してみてください。