tags:

views:

1838

answers:

5

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?)?

+1  A: 

I would suggest a git clone.

ndim
+6  A: 

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
VonC
I just checked this and it's actually great. I'll have to try some bundling and unbundling and list-heads to be convinced... but I like it quite a bit. Thanks again, especially for the notes on the --all switch.
Yar
Somewhat related, is there anything wrong with just zipping my local repository? I need a single backup file, copying thousands of files on a external drive is incredibly slow. I'm just wondering if there is something more efficient because zip has to archive so many files in the .git folder.
faB
@faB: the only difference is that you can easily do *incremental* backup with `git bundle`. It is not possible with a global zip of the all local repo.
VonC
@VonC Git bundle supports incremental backup and restore? I thought it makes one big file... is this wrong?
Yar
@yar: it can also make a small file with only latest changes from x (x being a tag, a date, n revision in a branch, ...). `git bundle create mybundle --since=10.days master` for instance only backup master branch for the last 10 days, allowing you to fetch from that bundle once you are on the destination workstation where a repo already exist.
VonC
Thanks for that, I thought perhaps there was a way for `git bundle` to actually be aware of the last backup.
Yar
A: 

Funny, I thought Git was a backup tool. I use a script to find each of my git repos and either clone (if the path is new) or pull from each one.

ergosys
Funny, I don't know enough about Git to know what you mean. How would I set up the structure?
Yar
The file structure isn't so bad, but after reading some more about it, I see that clone/pull isn't going to get every branch, so it's not a good solution. It was working for me because I don't yet have any branches in my very simple git repos. Time to rewrite that one...
ergosys
Cool thanks for that. Check out Pat Notz's answer above.
Yar
+14  A: 

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.

Pat Notz
+1. Agreed. git bundle is nice to move a backup around (one file). But with a drive you can plug anywhere, the bare repo is fine too.
VonC
+1 awesme, I'll look into this. Thanks for the examples, too.
Yar
@Pat Notz, in the end I decided to go with your way of doing it, and I put an answer below here (score permanently held at zero :)
Yar
+4  A: 

[Just leaving this here for my own reference.]

I liked git bundle and it answered the question. However, it's slow and the bundle is big. using zip is slow and the bundle is small.

In the end, I decided to go with Pat Notz's answer. So it looks like this:

Setup a Bare Repo

mkdir /myBareRepo.git
cd /myBareRepo.git
git init --bare

Push to the Bare Repo

git push --mirror /myBareRepo.git

Make an Alias

git config --add alias.backup "push --mirror /myBareRepo.git"

Use The Alias Intead of the Push Above

git backup

However I think the aliases are system-wide, so a name like "backup" would be bad news. Not sure yet. (This is wrong! If you don't use --global you're fine.)

Edit: Using this solution with a DropBox has to be the cheapest way to get a small repository backed up all the time... you could probably even share it. Although http://www.indefero.net/plans/ looks cheap too. Hmm...

Yar
+1 Because you didn't use the `--global` option this alias will only be seen in your project (it's definded in your `.git/config` file) -- that's probably what you want. Thanks for the more detailed and nicely formatted answer.
Pat Notz
Sure thing @Pat Notz thanks for the inspiration and help.
Yar
@yar: do you know how to accomplish these tasks without the commandline and instead only use tortoisegit (am searching for solution for my non-command-line-windoze users)?
pastacool
@pastacool, sorry I don't know about git without the command-line at all. Perhaps check out a relevant IDE like RubyMine?
Yar