Как создать резервную копию локального репозитория Git?
Я использую git на относительно небольшом проекте, и я нахожу, что молнии.содержимое каталога git может быть прекрасным способом резервного копирования проекта. Но это немного странно, потому что, когда я восстанавливаю, первое, что мне нужно сделать, это git reset --hard.
есть ли проблемы с резервным копированием git РЕПО таким образом? Кроме того, есть ли лучший способ сделать это (например, портативный формат git или что-то подобное?)?
7 ответов:
Я начал немного взламывать скрипт 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__ ==
другой официальный способ будет использовать git bundle
это создаст файл, который поддерживает
git fetchиgit pullдля обновления вашего второго РЕПО.
Полезно для инкрементного резервного копирования и восстановления.но если вам нужно резервное копирование все (потому что у вас нет второго РЕПО с некоторым более старым контентом уже на месте), резервное копирование немного сложнее сделать, как упоминалось в моем другом ответе, после Кентом Фредрикомкомментарий:
$ 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(это атомарной операции, в отличие от создания архива из , а прокомментировал by fantabolous)
внимание: я бы не рекомендовал Пэт Нотз ' s решение, который клонирует РЕПО.
Резервное копирование много файлов всегда сложнее, чем резервное копирование или обновление... только один.если вы посмотрите на история правок на СОЧ Ярответ, вы бы увидели, что Яр использовал сначала a
clone --mirror, ... с помощью редактирования:использование этого с Dropbox-это полный беспорядок.
У вас будут ошибки синхронизации, и вы не можете откатить каталог обратно в DROPBOX.
Используйтеgit bundleесли вы хотите создать резервную копию в Dropbox.Яр текущее решение использует
git bundle.я оставляю свое дело.
я делаю это, чтобы создать удаленный (голый) репозиторий (на отдельном диске, USB-ключ, резервный сервер или даже github), а затем использовать
push --mirrorчтобы это удаленное РЕПО выглядело точно так же, как мой локальный (за исключением того, что удаленный-это голой репозитории).это подтолкнет все ссылки (ветви и теги), включая обновления без быстрой перемотки вперед. Я использую это для создания резервных копий моего локального репозитория.
The на странице описывает его как это:
вместо того, чтобы называть каждый ref для 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__ == 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 в локальный файл. Элемент суть доступно здесь, не стесняйтесь раскошелиться и адаптироваться к вашим потребностям.
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" donerestore.sh:
#!/bin/bash # Restore the repository indicated in the command line # Example: # bin/restore filename.bak set -e FOLDER_NAME=$(echo | sed 's/.bak//') git clone --bare $FOLDER_NAME.git
вы можете создать резервную копию git РЕПО с git-copy . git-copy сохраненный новый проект как голое РЕПО, это означает минимальную стоимость хранения.
git copy /path/to/project /backup/project.backupзатем вы можете восстановить свой проект с
git clonegit clone /backup/project.backup project
пришел к этому вопросу через google.
вот что я сделал самым простым способом.
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 "--"лучшая часть если что-то испорчено, вы можете просто удалить исходную ветвь и вернуться к резервной ветви!!
Comments