web-dev-qa-db-ja.com

ローカルGitリポジトリをバックアップする方法は?

比較的小さなプロジェクトでgitを使用していますが、.gitディレクトリのコンテンツを圧縮することは、プロジェクトをバックアップするための優れた方法である可能性があります。しかし、これはちょっと奇妙です。復元するときに最初にやらなければならないことはgit reset --hardだからです。

この方法でgitリポジトリをバックアップする際に問題はありますか?また、それを行うためのより良い方法はありますか?

151
Dan Rosenstark

Yarのスクリプトを少しハッキングし始めました。その結果は、manページとインストールスクリプトを含むgithubにあります。

https://github.com/najamelan/git-backup

インストール

git clone "https://github.com/najamelan/git-backup.git"
cd git-backup
Sudo ./install.sh

Githubですべての提案とプルリクエストを歓迎します。

#!/usr/bin/env Ruby
#
# For documentation please sea man git-backup(1)
#
# TODO:
# - make it a class rather than a function
# - check the standard format of git warnings to be conform
# - do better checking for git repo than calling git status
# - if multiple entries found in config file, specify which file
# - make it work with submodules
# - propose to make backup directory if it does not exists
# - depth feature in git config (eg. only keep 3 backups for a repo - like rotate...)
# - TESTING



# allow calling from other scripts
def git_backup


# constants:
git_dir_name    = '.git'          # just to avoid magic "strings"
filename_suffix = ".git.bundle"   # will be added to the filename of the created backup


# Test if we are inside a git repo
`git status 2>&1`

if $?.exitstatus != 0

   puts 'fatal: Not a git repository: .git or at least cannot get zero exit status from "git status"'
   exit 2


else # git status success

   until        File::directory?( Dir.pwd + '/' + git_dir_name )             \
            or  File::directory?( Dir.pwd                      ) == '/'


         Dir.chdir( '..' )
   end


   unless File::directory?( Dir.pwd + '/.git' )

      raise( 'fatal: Directory still not a git repo: ' + Dir.pwd )

   end

end


# git-config --get of version 1.7.10 does:
#
# if the key does not exist git config exits with 1
# if the key exists twice in the same file   with 2
# if the key exists exactly once             with 0
#
# if the key does not exist       , an empty string is send to stdin
# if the key exists multiple times, the last value  is send to stdin
# if exaclty one key is found once, it's value      is send to stdin
#


# get the setting for the backup directory
# ----------------------------------------

directory = `git config --get backup.directory`


# git config adds a newline, so remove it
directory.chomp!


# check exit status of git config
case $?.exitstatus

   when 1 : directory = Dir.pwd[ /(.+)\/[^\/]+/, 1]

            puts 'Warning: Could not find backup.directory in your git config file. Please set it. See "man git config" for more details on git configuration files. Defaulting to the same directroy your git repo is in: ' + directory

   when 2 : puts 'Warning: Multiple entries of backup.directory found in your git config file. Will use the last one: ' + directory

   else     unless $?.exitstatus == 0 then raise( 'fatal: unknown exit status from git-config: ' + $?.exitstatus ) end

end


# verify directory exists
unless File::directory?( directory )

   raise( 'fatal: backup directory does not exists: ' + directory )

end


# The date and time prefix
# ------------------------

prefix           = ''
prefix_date      = Time.now.strftime( '%F'       ) + ' - ' # %F = YYYY-MM-DD
prefix_time      = Time.now.strftime( '%H:%M:%S' ) + ' - '
add_date_default = true
add_time_default = false

prefix += prefix_date if git_config_bool( 'backup.prefix-date', add_date_default )
prefix += prefix_time if git_config_bool( 'backup.prefix-time', add_time_default )



# default bundle name is the name of the repo
bundle_name = Dir.pwd.split('/').last

# set the name of the file to the first command line argument if given
bundle_name = ARGV[0] if( ARGV[0] )


bundle_name = File::join( directory, prefix + bundle_name + filename_suffix )


puts "Backing up to bundle #{bundle_name.inspect}"


# git bundle will print it's own error messages if it fails
`git bundle create #{bundle_name.inspect} --all --remotes`


end # def git_backup



# helper function to call git config to retrieve a boolean setting
def git_config_bool( option, default_value )

   # get the setting for the prefix-time from git config
   config_value = `git config --get #{option.inspect}`

   # check exit status of git config
   case $?.exitstatus

      # when not set take default
      when 1 : return default_value

      when 0 : return true unless config_value =~ /(false|no|0)/i

      when 2 : puts 'Warning: Multiple entries of #{option.inspect} found in your git config file. Will use the last one: ' + config_value
               return true unless config_value =~ /(false|no|0)/i

      else     raise( 'fatal: unknown exit status from git-config: ' + $?.exitstatus )

   end
end

# function needs to be called if we are not included in another script
git_backup if __FILE__ == $0
24
user1115652

他の公式な方法は、git bundleを使用することです

これにより、2番目のリポジトリを更新するためにgit fetchおよびgit pullをサポートするファイルが作成されます。
増分バックアップと復元に役立ちます。

ただし、すべてをバックアップする必要がある場合(いくつかの古いコンテンツがすでに配置されている2番目のレポジトリがないため)、バックアップは、 Kent Fredric のコメントの後の私の別の答え:

$ git bundle create /tmp/foo master
$ git bundle create /tmp/foo-all --all
$ git bundle list-heads /tmp/foo
$ git bundle list-heads /tmp/foo-all

(これは、アトミック操作であり、.gitフォルダーからアーカイブを作成するのではなく、 commented by 幻想的


警告: Pat Notzsolution はお勧めしません。これはリポジトリのクローンです。
多くのファイルのバックアップは、バックアップや更新よりも常に注意が必要です... 1つだけです。

編集履歴OP Yaranswer を見ると、最初にYarがclone --mirrorを使用していることがわかります。 ...編集あり:

これをDropboxで使用すると、全体が混乱します
同期エラーが発生し、DROPBOXでディレクトリをロールバックできません。
Dropboxにバックアップする場合は、git bundleを使用します。

Yarの 現在のソリューションgit bundleを使用します。

ケースを休ませます。

142
VonC

これを行う方法は、リモート(ベア)リポジトリを(別のドライブ、USBキー、バックアップサーバー、またはgithubに)作成し、Push --mirrorを使用して、そのリモートリポジトリをローカルリポジトリとまったく同じようにします(ただし、リモートはbareリポジトリです。

これにより、非早送り更新を含むすべての参照(ブランチとタグ)がプッシュされます。これを使用して、ローカルリポジトリのバックアップを作成します。

manページ は次のように説明しています:

各参照の名前をPushにする代わりに、$GIT_DIR/refs/refs/heads/refs/remotes/、およびrefs/tags/を含むがこれらに限定されない)の下のすべての参照をリモートにミラ​​ーリングすることを指定します倉庫。新しく作成されたローカル参照はリモートエンドにプッシュされ、ローカルで更新された参照はリモートエンドで強制的に更新され、削除された参照はリモートエンドから削除されます。これは、構成オプションremote.<remote>.mirrorが設定されている場合のデフォルトです。

プッシュを行うためにエイリアスを作成しました。

git config --add alias.bak "Push --mirror github"

次に、バックアップを行いたいときはいつでもgit bakを実行します。

62
Pat Notz

[参照用にこれをここに残します。]

git-backupというバンドルスクリプトは次のようになります

#!/usr/bin/env Ruby
if __FILE__ == $0
        bundle_name = ARGV[0] if (ARGV[0])
        bundle_name = `pwd`.split('/').last.chomp if bundle_name.nil? 
        bundle_name += ".git.bundle"
        puts "Backing up to bundle #{bundle_name}"
        `git bundle create /data/Dropbox/backup/git-repos/#{bundle_name} --all`
end

git backupを使用する場合と、git backup different-nameを使用する場合があります。これにより、必要なほとんどの可能性が得られます。

35
Dan Rosenstark

この質問に対する答えはどちらも正しいですが、Githubリポジトリをローカルファイルにバックアップするための完全で短いソリューションがまだありませんでした。 Gist はここから入手できます。必要に応じて分岐または適応してください。

backup.sh:

#!/bin/bash
# Backup the repositories indicated in the command line
# Example:
# bin/backup user1/repo1 user1/repo2
set -e
for i in $@; do
  FILENAME=$(echo $i | sed 's/\//-/g')
  echo "== Backing up $i to $FILENAME.bak"
  git clone [email protected]:$i $FILENAME.git --mirror
  cd "$FILENAME.git"
  git bundle create ../$FILENAME.bak --all
  cd ..
  rm -rf $i.git
  echo "== Repository saved as $FILENAME.bak"
done

restore.sh:

#!/bin/bash
# Restore the repository indicated in the command line
# Example:
# bin/restore filename.bak
set -e

FOLDER_NAME=$(echo $1 | sed 's/.bak//')
git clone --bare $1 $FOLDER_NAME.git
9
Nacho Coloma

git-copy でgitリポジトリをバックアップできます。 git-copyは新しいプロジェクトを裸のレポとして保存しました。これは最小のストレージコストを意味します。

git copy /path/to/project /backup/project.backup

その後、git cloneを使用してプロジェクトを復元できます

git clone /backup/project.backup project
4
Quanlong

グーグル経由でこの質問に来ました。

これが私が最も簡単な方法でしたことです。

git checkout branch_to_clone

次に、このブランチから新しいgitブランチを作成します

git checkout -b new_cloned_branch
Switched to branch 'new_cloned_branch'

元のブランチに戻って続行します。

git checkout branch_to_clone

あなたが台無しにして、バックアップブランチから何かを復元する必要があると仮定します:

git checkout new_cloned_branch -- <filepath>  #notice the space before and after "--"

何かがめちゃくちゃになった場合の最良の部分は、ソースブランチを削除して、バックアップブランチに戻ることができます!!

1
NoobEditor