私は比較的小さなプロジェクトでgitを使用していますが、.gitディレクトリの内容を圧縮することは、プロジェクトをバックアップするための良い方法であることに気づきました。しかし、これは奇妙なことです。なぜなら、復元するときに最初に行う必要があるのはだからですgit reset --hard
。
この方法でgitリポジトリをバックアップすることに問題はありますか?また、それを行うためのより良い方法はありますか(たとえば、移植可能なgit形式または同様の何か?)?
git bundle
私は比較的小さなプロジェクトでgitを使用していますが、.gitディレクトリの内容を圧縮することは、プロジェクトをバックアップするための良い方法であることに気づきました。しかし、これは奇妙なことです。なぜなら、復元するときに最初に行う必要があるのはだからですgit reset --hard
。
この方法でgitリポジトリをバックアップすることに問題はありますか?また、それを行うためのより良い方法はありますか(たとえば、移植可能なgit形式または同様の何か?)?
git bundle
回答:
私はYarのスクリプトを少しハッキングし始め、結果はgithubにあり、manページとインストールスクリプトが含まれています。
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
警告:リポジトリを複製するPat Notzのソリューションはお勧めしません。
多くのファイルのバックアップは、バックアップや更新よりも常に注意が必要です。1つだけです。
あなたが見れば編集の歴史のOPヤールの 答えは、あなたはヤールは、最初のAで使用していることがわかりますclone --mirror
編集で、...:
Dropboxでこれを使用するのは、まったく厄介です。
同期エラーが発生し、DROPBOXでディレクトリをロールバックすることはできません。Dropboxにバックアップ
するgit bundle
場合に使用します。
Yarの現在のソリューションではを使用していgit bundle
ます。
私はケースを休ませる。
git bundle
。すべてのローカルリポジトリのグローバルzipでは不可能です。
これを行う方法は、リモート(ベア)リポジトリを(別のドライブ、USBキー、バックアップサーバー、またはgithubに)作成し、それを使用push --mirror
してそのリモートリポジトリをローカルのリポジトリとまったく同じに見えるようにすることです(リモートが裸の場合を除く)。リポジトリ)。
これにより、早送り以外の更新を含むすべての参照(ブランチとタグ)がプッシュされます。これを使用して、ローカルリポジトリのバックアップを作成します。
manページにはこのようにそれを説明します。
プッシュする各参照に名前を付ける代わりに、その下にあるすべての参照
$GIT_DIR/refs/
(、、およびが含まれますがrefs/heads/
、これらに限定されません)がリモートリポジトリにミラーリングされることを指定します。新しく作成されたローカル参照はリモートエンドにプッシュされ、ローカルで更新された参照はリモートエンドで強制的に更新され、削除された参照はリモートエンドから削除されます。これは、構成オプションが設定されている場合のデフォルトです。refs/remotes/
refs/tags/
remote.<remote>.mirror
私はエイリアスを作ってプッシュを行いました:
git config --add alias.bak "push --mirror github"
その後、git bak
バックアップを実行したいときに実行します。
--mirror
実際には、取得したオブジェクトに対していかなる種類の検証も実行しないことに注意してください。git fsck
破損を防ぐために、ある時点で実行する必要があります。
[これを私自身の参照のためにここに残しておくだけです。]
呼び出されたバンドルスクリプトは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
ので、必要な可能性のほとんどが得られます。
--global
オプションを使用しなかったため、このエイリアスはプロジェクトでのみ表示されます(.git/config
ファイルで定義されています)。より詳細で適切にフォーマットされた回答をありがとう。
この質問に対する答えはどちらも正しいですが、Githubリポジトリをローカルファイルにバックアップするための完全で短い解決策がまだありませんでした。要点は、フォークやニーズに合わせて自由に感じるここにあります。
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 git@github.com:$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 bundle create <filename> --all
次の方法で復元します。
$ git clone <filename> <folder>
この操作はアトミックなAFAIKです。詳細については、公式ドキュメントを確認してください。
「zip」について:gitバンドルは圧縮されており、.gitフォルダーのサイズに比べて驚くほど小さいです。
グーグル経由でこの質問に来ました。
これが私が最も簡単な方法でやったことです。
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 "--"
何かが台無しになった場合の最良の部分は、ソースブランチを削除してバックアップブランチに戻るだけです!!