比較的小さなプロジェクトでgitを使用していますが、.gitディレクトリのコンテンツを圧縮することは、プロジェクトをバックアップするための優れた方法である可能性があります。しかし、これはちょっと奇妙です。復元するときに最初にやらなければならないことはgit reset --hard
だからです。
この方法でgitリポジトリをバックアップする際に問題はありますか?また、それを行うためのより良い方法はありますか?
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
他の公式な方法は、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 Notz の solution はお勧めしません。これはリポジトリのクローンです。
多くのファイルのバックアップは、バックアップや更新よりも常に注意が必要です... 1つだけです。
編集履歴 の OP Yaranswer を見ると、最初にYarがclone --mirror
を使用していることがわかります。 ...編集あり:
これをDropboxで使用すると、全体が混乱します。
同期エラーが発生し、DROPBOXでディレクトリをロールバックできません。
Dropboxにバックアップする場合は、git bundle
を使用します。
Yarの 現在のソリューション はgit bundle
を使用します。
ケースを休ませます。
これを行う方法は、リモート(ベア)リポジトリを(別のドライブ、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
を実行します。
[参照用にこれをここに残します。]
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
を使用する場合があります。これにより、必要なほとんどの可能性が得られます。
この質問に対する答えはどちらも正しいですが、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
git-copy でgitリポジトリをバックアップできます。 git-copyは新しいプロジェクトを裸のレポとして保存しました。これは最小のストレージコストを意味します。
git copy /path/to/project /backup/project.backup
その後、git clone
を使用してプロジェクトを復元できます
git clone /backup/project.backup project
グーグル経由でこの質問に来ました。
これが私が最も簡単な方法でしたことです。
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 "--"
何かがめちゃくちゃになった場合の最良の部分は、ソースブランチを削除して、バックアップブランチに戻ることができます!!