稼働中のGitリポジトリを外付けSSDやNASへ定期バックアップするとき、フォルダ全体をそのままrsyncすれば十分に見えます。しかし、コピー中にGitの保守処理や別の更新が走ると、.git内部で参照しているファイルと実際にコピーされたファイルの時点がずれ、不整合なスナップショットになる可能性があります。
結論は、作業中のファイルは.gitを除外してrsyncし、コミット履歴・ブランチ・タグはgit bundleで別に保存することです。作業ツリーとGit履歴を役割の違う二つの成果物に分け、最後に復元確認まで行うと、未コミット作業とリポジトリ履歴の両方を守りやすくなります。
安全な二本立て
- 作業ツリー:
.gitを除外してファイルを同期 - Git履歴:
git bundleでブランチ・タグ・オブジェクトを保存 - 検証: ファイル差分、bundle検証、復元テストを分けて実施
なぜ生きた.gitの直接rsyncは競合しやすいのか

.gitには、コミット、ツリー、ファイル内容を表すオブジェクト、ブランチ参照、インデックス、ログ、設定などが入っています。通常利用ではGit自身が整合性を管理しますが、rsyncはGitの状態を理解せず、見つけたファイルを順番にコピーします。
コピー中にgit gcやrepackが動くと、個別オブジェクトがpackfileへまとめられ、不要になったファイルが削除されることがあります。rsyncが先に参照したファイルが転送前に消えたり、参照だけ新しく履歴データが古い状態になったりすると、コピー先は一時点のリポジトリを正しく表さない可能性があります。
実運用でも、.gitを含む直接同期が保守処理と重なり、転送対象ファイルの消失でバックアップが失敗しました。そこで、作業ファイルのrsyncとGit履歴のbundleを分離したところ、同じ週次バックアップを完走できました。失敗の教訓は、rsyncそのものが悪いのではなく、変化中のGit内部を通常フォルダと同じ方法で扱わないことです。
| 対象 | 含まれるもの | 向く保存方法 | 主な注意 |
|---|---|---|---|
| 作業ツリー | 編集ファイル、未追跡ファイル、未コミット差分 | rsyncなどのファイル同期 | .gitを除外する |
| Git履歴 | コミット、ブランチ、タグ、オブジェクト | git bundle | 未コミット差分は入らない |
| 外部依存 | データベース、アップロード、秘密情報 | 対象別の正式なバックアップ | Gitだけでは復元できない |
作業ツリーとGit履歴を分ける理由
作業ツリーのバックアップは、今この瞬間にディスク上へあるファイルを守ります。まだコミットしていない下書き、設定変更、新規ファイルも対象にできます。一方、bundleはGitが到達可能な履歴を一つのファイルへまとめ、別の場所でcloneやfetchに使える形式です。
どちらか一方だけでは不足します。bundleだけでは未コミット差分や無視対象ファイルを復元できません。作業ツリーのコピーだけでは、過去コミット、ブランチ、タグ、差分履歴をGitリポジトリとして復元できません。二つを同じ実行日・同じ世代名で保存すると、役割が明確になります。
バックアップ対象を先に分類する
WordPressやWebアプリでは、Git管理外のアップロード、データベース、環境変数、外部ストレージが別にあります。リポジトリを保存しただけでサイト全体を復元できるとは限りません。コード、コンテンツ、データ、認証情報を別々に棚卸ししてください。
二本立てバックアップの基本手順

- 対象リポジトリとバックアップ先を固定する
- 作業ツリーを
.git除外で同期する - Git自身にbundleを生成させる
- 同期エラー、容量、更新日時を記録する
- bundleの整合性を確認する
- 別の一時場所へ復元し、主要ファイルと履歴を確認する
- 保存世代と次回実行日を記録する
作業ツリーの同期は、概念的には次のように.gitを除外します。実際の運用では、同期元と同期先を明示し、末尾のスラッシュ、削除同期の有無、シンボリックリンクの扱いを事前に確認してください。
rsync -a --exclude ".git" /path/to/project/ /path/to/backup/project/
Git履歴は、対象リポジトリで次のようにbundleへまとめられます。--allを使うと、ローカルにある全参照を含める構成にできます。必要なブランチだけを保存する運用では、対象参照を明示します。
git -C /path/to/project bundle create /path/to/backup/project-repo.bundle --all
定期処理では、完成前のbundleを本番名へ直接見せない工夫も有効です。一時名で生成し、検証に成功してから世代名へ切り替えると、途中終了したファイルを最新バックアップと誤認しにくくなります。既存bundleを上書きする前に、前世代を残す保持方針も決めます。
bundleは作成成功だけでなく復元できるか確認する
コマンドが終了コード0でも、運用上必要な参照が含まれているかは別です。git bundle verifyで形式と前提条件を確認し、一覧でブランチやタグを確認します。さらに、定期的に空の一時フォルダへcloneし、ログ、主要ブランチ、必要なタグが見えるか確認します。
git bundle verify /path/to/backup/project-repo.bundle
git clone /path/to/backup/project-repo.bundle /temporary/restore-check
作業ツリー側も、ファイル数や合計容量だけでなく、重要ファイルの存在、更新日時、必要に応じたハッシュを確認します。未コミット差分が重要なら、元リポジトリのgit statusとバックアップ側の対象ファイルを照合します。
| 確認項目 | 作業ツリー | bundle |
|---|---|---|
| 生成・同期の終了状態 | rsyncの終了コードとエラー | bundle createの終了コード |
| 内容 | 重要ファイル、差分、容量 | heads、tags、履歴 |
| 整合性 | 差分またはハッシュ | git bundle verify |
| 復元 | 必要ファイルを開けるか | 別場所へcloneできるか |
定期実行では同時実行と失敗通知を設計する
毎晩のコミット、週次のSSD同期、手動の大容量コピーが重なると、ディスク負荷だけでなく状態の境界も分かりにくくなります。ロックファイルや実行中判定で同じバックアップの重複起動を避け、開始時刻、終了時刻、対象、結果をログへ残します。
- バックアップ先が未接続なら、意図しないローカルフォルダへ書かず安全に停止する
- 前回処理が残っている時は二重起動しない
- 失敗した対象だけを記録し、成功扱いで上書きしない
- 容量不足、読み取り失敗、bundle失敗を別の理由として残す
- 世代数または保存期間を決め、最新一つだけに依存しない
転送速度を優先してログを捨てると、後から「何が保存できなかったか」が分かりません。正常時は短い要約、失敗時は対象と再実行条件を残します。バックアップの成否は、ファイルがあるかではなく、必要な状態へ戻せるかで判断します。
Webサイト運用ではGit以外の復元対象も確認する
WordPressでは、テーマやプラグインのコードがGitにあっても、投稿本文、設定、ユーザー、フォーム、WooCommerce注文、メディアはデータベースやuploadsにあります。Gitバックアップは重要ですが、サイト全体のバックアップではありません。更新作業の前後で、データベース、uploads、対象コード、変更前本文を分けて保存します。
更新に失敗した後の切り分けはWordPressプラグイン更新失敗の対処法、長期間止まったサイトを再開する確認はWordPressサイトを放置した時の再開手順も参考になります。バックアップ自動化や復元設計を含む実装が必要な場合は開発依頼、サイト全体の更新設計はWebサイト制作から相談できます。
向いているケース・向いていないケース
二本立てが向いている
- 稼働中リポジトリを定期同期する
- 未コミット作業も守りたい
- 外付けSSDやNASへ世代保存する
- 履歴をclone可能な形で残したい
追加設計が必要
- データベースやuploadsが中心
- 秘密情報を同じ場所へ平文保存する
- 複数リポジトリの整合時点が重要
- 停止できない大規模システム
よくある質問
Q. .gitをrsyncすると必ず壊れますか?
A. 必ずではありませんが、コピー中にgit gc、repack、commitなどで内部状態が変わると、整合しない時点のファイルを集める可能性があります。稼働中は作業ツリーとbundleを分ける方が安全です。
Q. git bundleだけで未コミット作業も保存できますか?
A. できません。bundleはGitが到達可能な履歴を保存します。未コミット差分、未追跡ファイル、Git管理外の必要ファイルは作業ツリー側で別に保存してください。
Q. bundleを作った後は何を確認しますか?
A. git bundle verifyで整合性と前提条件を確認し、必要なブランチやタグが含まれるか一覧で見ます。定期的に別の一時場所へcloneして復元できることも確認します。
Q. WordPressはGitバックアップだけで復元できますか?
A. 通常はできません。投稿や設定のデータベース、uploads、外部ストレージ、環境設定を別に保存する必要があります。復元対象をコードとデータに分けて棚卸ししてください。
まとめ
稼働中のGitリポジトリでは、.gitを含むフォルダ全体を通常ファイルとして同期するより、作業ツリーとGit履歴を分けます。作業ファイルは.git除外でrsyncし、履歴はgit bundleで保存します。終了コードだけでなく、差分、bundle検証、別場所への復元まで確認し、データベースやuploadsなどGit外の対象も別に守ってください。
この記事は役に立ちましたか?
ありがとうございます!