[git] How to backup a local Git repository?

I am using git on a relatively small project and I find that zipping the .git directory's contents might be a fine way to back up the project. But this is kind of weird because, when I restore, the first thing I need to do is git reset --hard.

Are there any problems with backing up a git repo this way? Also, is there any better way to do it (e.g., a portable git format or something similar?)?

This question is related to git backup

The answer is


Found the simple official way after wading through the walls of text above that would make you think there is none.

Create a complete bundle with:

$ git bundle create <filename> --all

Restore it with:

$ git clone <filename> <folder>

This operation is atomic AFAIK. Check official docs for the gritty details.

Regarding "zip": git bundles are compressed and surprisingly small compared to the .git folder size.


[Just leaving this here for my own reference.]

My bundle script called git-backup looks like this

#!/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

Sometimes I use git backup and sometimes I use git backup different-name which gives me most of the possibilities I need.


came to this question via google.

Here is what i did in the simplest way.

git checkout branch_to_clone

then create a new git branch from this branch

git checkout -b new_cloned_branch
Switched to branch 'new_cloned_branch'

come back to original branch and continue:

git checkout branch_to_clone

Assuming you screwed up and need to restore something from backup branch :

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

Best part if anything is screwed up, you can just delete the source branch and move back to backup branch!!


The other offical way would be using git bundle

That will create a file that support git fetch and git pull in order to update your second repo.
Useful for incremental backup and restore.

But if you need to backup everything (because you do not have a second repo with some older content already in place), the backup is a bit more elaborate to do, as mentioned in my other answer, after Kent Fredric's comment:

$ 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

(It is an atomic operation, as opposed to making an archive from the .git folder, as commented by fantabolous)


Warning: I wouldn't recommend Pat Notz's solution, which is cloning the repo.
Backup many files is always more tricky than backing up or updating... just one.

If you look at the history of edits of the OP Yar answer, you would see that Yar used at first a clone --mirror, ... with the edit:

Using this with Dropbox is a total mess.
You will have sync errors, and you CANNOT ROLL A DIRECTORY BACK IN DROPBOX.
Use git bundle if you want to back up to your dropbox.

Yar's current solution uses git bundle.

I rest my case.


The way I do this is to create a remote (bare) repository (on a separate drive, USB Key, backup server or even github) and then use push --mirror to make that remote repo look exactly like my local one (except the remote is a bare repository).

This will push all refs (branches and tags) including non-fast-forward updates. I use this for creating backups of my local repository.

The man page describes it like this:

Instead of naming each ref to push, specifies that all refs under $GIT_DIR/refs/ (which includes but is not limited to refs/heads/, refs/remotes/, and refs/tags/) be mirrored to the remote repository. Newly created local refs will be pushed to the remote end, locally updated refs will be force updated on the remote end, and deleted refs will be removed from the remote end. This is the default if the configuration option remote.<remote>.mirror is set.

I made an alias to do the push:

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

Then, I just run git bak whenever I want to do a backup.


You can backup the git repo with git-copy . git-copy saved new project as a bare repo, it means minimum storage cost.

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

Then you can restore your project with git clone

git clone /backup/project.backup project

Both answers to this questions are correct, but I was still missing a complete, short solution to backup a Github repository into a local file. The gist is available here, feel free to fork or adapt to your needs.

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