비교적 작은 프로젝트에서 git을 사용하고 있으며 .git 디렉토리의 내용을 압축하면 프로젝트를 백업하는 좋은 방법 일 수 있습니다. 그러나 복원 할 때 가장 먼저해야 할 일은이므로 이는 이상 git reset --hard
합니다.
이런 식으로 git repo를 백업하는 데 문제가 있습니까? 또한 더 좋은 방법이 있습니까 (예 : 휴대용 git 형식 또는 이와 유사한 것)?
git bundle
비교적 작은 프로젝트에서 git을 사용하고 있으며 .git 디렉토리의 내용을 압축하면 프로젝트를 백업하는 좋은 방법 일 수 있습니다. 그러나 복원 할 때 가장 먼저해야 할 일은이므로 이는 이상 git reset --hard
합니다.
이런 식으로 git repo를 백업하는 데 문제가 있습니까? 또한 더 좋은 방법이 있습니까 (예 : 휴대용 git 형식 또는 이와 유사한 것)?
git bundle
답변:
나는 Yar의 스크립트에서 약간의 해킹을 시작했으며 그 결과는 매뉴얼 페이지 및 설치 스크립트를 포함하여 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을 사용하는 것입니다.
그러면 두 번째 리포지토리 를 지원 git fetch
하고 git pull
업데이트 하는 파일이 생성됩니다 .
증분 백업 및 복원에 유용합니다.
그러나 모든 오래된 것을 이미 백업 해야하는 경우 (이전에 오래된 콘텐츠가있는 두 번째 저장소가 없기 때문에) 다른 대답에서 언급했듯이 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
( fantabolous에 의해 언급 된 것처럼 폴더 에서 아카이브를 만드는 것과는 반대로 원자 작업입니다 . ).git
경고 : 나는 저장소를 복제하는 Pat Notz 의 솔루션을 권장하지 않습니다 .
많은 파일을 백업하는 것은 하나의 백업 또는 업데이트보다 항상 까다 롭습니다.
OP Yar answer 의 편집 히스토리 를 보면 Yar 이 처음에 편집 에 사용 된 것을 볼 수 있습니다.clone --mirror
이것을 Dropbox와 함께 사용하는 것은 완전히 혼란 입니다.
동기화 오류가 발생하여 DROPBOX에서 디렉토리를 롤백 할 수 없습니다. 보관 용 계정에 백업
하려면 사용하십시오git bundle
.
Yar의 현재 솔루션 은을 사용합니다 git bundle
.
난 내 경우를 휴식.
git bundle
. 모든 지역 리포지토리의 글로벌 우편으로는 불가능합니다.
나는이 작업을 수행하는 방법은 원격 (베어) 저장소를 생성하는 것입니다 (별도의 드라이브를 USB 키, 백업 서버 또는 GitHub의) 한 다음 사용 push --mirror
(가) 멀리 떨어진입니다 제외하고 (정확히 내 지역과 같은 해당 원격 REPO 모양을 만들기 위해 베어 저장소).
이렇게하면 빨리 감기가 아닌 업데이트를 포함한 모든 참조 (분기 및 태그)가 푸시됩니다. 로컬 리포지토리의 백업을 생성하는 데 사용합니다.
매뉴얼 페이지 이런 식으로 설명 :
대신 밀어 각 REF 네이밍, 심판 미만임을 지정
$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 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 "--"
무언가가 망가진 경우 가장 중요한 부분은 소스 브랜치를 삭제하고 백업 브랜치로 다시 이동할 수 있습니다 !!