Git bundleで履歴を保存し、別フォルダへ復元する手順

git bundleでコミット・ブランチ・タグを保存し、別フォルダへのcloneで復元を確かめます。未コミットの変更と未追跡ファイルが戻らない例も、空の検証用リポジトリで試します。

目次
  1. 履歴の持ち出しに使うファイル
  2. 1. 保存する履歴と、保存されない変更を作る
  3. 2. bundleを作り、mainを指定して復元する
  4. 3. コミットIDとファイル内容を照合する
  5. 4. topicを開き、originの行き先を確かめる
  6. 実際のリポジトリを保存するときに別途必要なもの
  7. 参考資料

履歴の持ち出しに使うファイル

Git bundleは、Gitの履歴を1つのファイルへまとめる仕組みです。保存したファイルから新しいリポジトリを作れるため、ネットワークにつながずに履歴を別の端末へ渡せます。Git公式のgit-bundle資料には、保存とcloneによる復元の例があります。

ただし、編集中のファイルまで丸ごと保存するものではありません。ここではコミット済みの内容を復元し、未コミットの変更と未追跡ファイルが戻らないことも確かめます。既存の作業フォルダを使わず、専用の一時フォルダで実行してください。

以下はLinuxのBash向けのコマンドです。Git 2.28以降を前提とします。掲載手順の動作確認は2026年9月19日にWindows上のGit BashとGit 2.45.1.windows.1で実施しました。Linux環境そのものでは未検証です。

1. 保存する履歴と、保存されない変更を作る

新しいターミナルで次のコマンドを実行します。mktempが作ったフォルダ内にsourceを用意し、note.txtをコミットします。名前とメールアドレスは、この検証用リポジトリだけに設定する例示値です。

タグv1とブランチtopicを作った後、note.txtを書き換え、scratch.txtを追加します。末尾のstatusで「 M note.txt」と「?? scratch.txt」が表示されれば、未コミット変更と未追跡ファイルを用意できています。

trial=$(mktemp -d)
cd "$trial"
git init -b main source
git -C source config user.name 'Bundle Test'
git -C source config user.email 'bundle-test@example.invalid'
printf 'committed\n' > source/note.txt
git -C source add note.txt
git -C source commit -m 'Save note'
git -C source tag v1
git -C source branch topic
printf 'uncommitted\n' > source/note.txt
printf 'untracked\n' > source/scratch.txt
git -C source status --short

2. bundleを作り、mainを指定して復元する

同じターミナルで続けます。--allは、そのリポジトリにある参照と、そこからたどれる履歴を保存する指定です。verifyはファイルの形式や必要な前提コミットを確認します。成功しても、作業中のファイルが含まれる証明にはならないため、続けて別フォルダへ復元します。

cloneには-b mainを付け、復元直後に開くブランチを指定します。この例のmainとtopicは同じコミットを指しており、省略すると元と同じブランチ名が選ばれるとは限りません。各コマンドがエラーになった場合は、その段階で止めて表示内容を確認してください。

git -C source bundle create ../backup.bundle --all
git -C source bundle verify ../backup.bundle
git clone -b main backup.bundle restored

3. コミットIDとファイル内容を照合する

次の4行で表示されるコミットIDを、main同士、v1同士で比べます。IDの文字列自体は実行ごとに変わりますが、それぞれ保存元と復元先で一致することを確かめます。note.txtの中身はcommittedに戻り、scratch.txtは復元先にありません。

今回の検証では、mainとv1のIDがそれぞれ一致しました。復元先のnote.txtはcommittedで、scratch.txtは存在しませんでした。保存元の未コミット変更と未追跡ファイルはそのまま残りました。

git -C source rev-parse main
git -C restored rev-parse main
git -C source rev-parse v1
git -C restored rev-parse v1
cat restored/note.txt
if test -e restored/scratch.txt; then
  printf 'scratch.txt exists\n'
else
  printf 'scratch.txt absent\n'
fi

表は横にスクロールできます →

保存元にあるもの今回の復元結果
mainのコミットとタグv1保存元と復元先のIDが一致
note.txtのコミット済み内容committedを復元
note.txtの未コミット変更uncommittedは復元されない
未追跡のscratch.txt復元先には存在しない

4. topicを開き、originの行き先を確かめる

--allで保存しても、通常のcloneが全ブランチをローカルブランチとして作るわけではありません。今回のclone直後はmainがローカルブランチ、topicはorigin/topicとして存在しました。branch -aで確認し、topicを開くには次のようにローカルブランチを作ります。Git公式のgit-clone資料でも、元のブランチに対応するリモート追跡ブランチを作る動作が説明されています。

topicを作った後、2行のrev-parseが表示するコミットIDが保存元と復元先で一致することを確認します。

remote -vに出るoriginは、以前使っていたGitホスティングのURLではなくbackup.bundleのパスです。このファイルへpushして更新することはできません。実際の開発を再開する場合は、接続すべきリモートURLを別に確認する必要があります。

git -C restored branch -a
git -C restored switch -c topic --track origin/topic
git -C source rev-parse topic
git -C restored rev-parse topic
git -C restored remote -v

実際のリポジトリを保存するときに別途必要なもの

この手順は、浅いcloneや部分cloneではない、小さな通常のリポジトリで試しています。実際の保存前にはgit statusで未コミット変更を調べ、残したい作業ファイルを別に保存してください。ローカルの設定やhooksも、bundleからは復元されません。

Git LFSを使う場合、Gitの中には大きなファイルの実体に代わるポインターが入ります。Git LFS公式の説明にあるように実体は別に保管されるため、bundleだけで実体まで保存したとは扱えません。submoduleも独立した履歴を持つ別のリポジトリなので、それぞれの保存と復元が必要です。この2種類の復元は今回の検証には含めていません。

検証後も、端末故障への備えにはbundleを別の保存先へコピーする作業が必要です。同じディスクに置いただけでは、ディスク全体を失う場合に対応できません。元のリポジトリは、移した保存先からの復元確認が終わるまで残してください。

参考資料