Git
capistrano3

Capistrano のデプロイ先から Git リポジトリを復元する

状況

消失したリポジトリを復元し、新しいホスティング先へ git-push したい。

  • Git リポジトリが消失し、ローカルにはソースファイルすらない
  • 残っているファイルは Capistrano のデプロイ先にあるもののみ
  • 本番環境の接続設定が ssh config の Host my-app で用意されている
  • Capistrano を使って my-app/path/to/app ディレクトリへデプロイされている

本番環境の様子

my-app/path/to/app が Capistrano でデプロイする環境であることを確認する

[ec2-user@my-app ~]$ ls -l /path/to/app
total 24
lrwxrwxrwx 1 ec2-user ec2-user   50 Feb 1  2017 current -> /path/to/app/releases/20170201000000
drwxrwxr-x 5 ec2-user ec2-user 4096 Feb 1  2017 releases
drwxrwxr-x 7 ec2-user ec2-user 4096 Feb 1  2017 repo
-rw-rw-r-- 1 ec2-user ec2-user 8595 Feb 1  2017 revisions.log
drwxrwxr-x 6 ec2-user ec2-user 4096 Feb 1  2017 shared

Git リポジトリを復元する

1. 本番環境の /path/to/app/current をローカルにコピーする

$ scp -r my-app:/path/to/app/current my-app

2. 本番環境の bare repository をローカルにコピーする

1の段階では .git ディレクトリがないため、本番環境の /path/to/app/repo.git としてダウンロードする。

$ scp -r my-app:/path/to/app/repo my-app/.git

3. ローカルの bare repository を non bare repository に変更する

my-app:/path/to/app/repo は bare repository であるため、このままではコミットなどの破壊的操作をすることができない。non bare repository に変更することで git-commit や git-push を実行できるようになる。

$ git config core.bare false
## git のステージをクリーンな状態にする
$ git reset HEAD

.git/config から mirror = true を削除する

.git/config
 [core]
     repositoryformatversion = 0 
     filemode = true
     bare = false
 [remote "origin"]
     fetch = +refs/*:refs/*
-    mirror = true
     url = git@github.com:taro-yamada/my-app.git

4. 新しいホスティング先を設定する

$ git remote set-url origin git@github.com:taro-yamada/my-app.git

5. 新しいコミットが push できることを確認する

$ git commit --allow-empty -m 'Done testing'
$ git push origin master:done-testing

本番環境から Git リポジトリを復元することができました。

5. 本番環境の /path/to/app/repo/config に新しいリポジトリを設定する

cap deploy を実行したときに新しいリポジトリが参照されるようにします。

/path/to/app/repo/config
 [core]                                                  
         repositoryformatversion = 0                     
         filemode = true                                 
         bare = true                                     
 [remote "origin"]                                       
         fetch = +refs/*:refs/*                          
         mirror = true
-        url = git@old-repository.example.com:taro-yamada/my-app.git
+        url = git@github.com:taro-yamada/my-app.git