UPDATE
I set up the two Git repositories following the directions from one of the answers below, but the back-up directory doesn't have copies of the files in the working directory. This is what I see in the back-up directory...
$ ls
total 0
drwxr-xr-x 10 Hristo staff 340 Feb 25 21:40 Kamma.git
... but I was expecting something like the following...
$ ls
total 16
drwxr-xr-x 6 Hristo staff 204 Dec 19 19:51 css
drwxr-xr-x 3 Hristo staff 102 Nov 13 18:00 images
-rw-r--r--@ 1 Hristo staff 4440 Feb 26 03:20 index.html
drwxr-xr-x 15 Hristo staff 510 Feb 24 14:19 js
Again, I want my main working directory, /Users/Hristo/Sites/Kamma
, to be the place where I make changes and do commits and reverts and such.
I want /Users/Hristo/Sites/Kamma_bak
to be the place where I periodically push important changes, like a new version of my project, where everything is a copy of my working directory, just not the most up to date copy.
I hope this makes sense.
Original Post
I would like to set up a local Git repository. So for example, I would like my main location to be /Users/Hristo/Sites/Kamma
which is where I would do all of my work.
I'm looking to be able to commit changes and revert back to previous versions, etc..., the way subversion works. B开发者_Python百科ut I would also like to have a back-up directory, /Users/Hristo/Sites/Kamma_bak
, as a fail safe, where I would "push" versions every once in a while.
In this back-up directory /Users/Hristo/Sites/Kamma_bak
, I would like all the files and such to exist as duplicate copies, as back-up copies, of the working directory /Users/Hristo/Sites/Kamma
How would I do this with Git? I have it already installed on my machine, running Snow Leopard.
Yes you can absolutely do that. Although I would recommend that your backup folder is on another computer.
Please read this thread, Using Git and Dropbox together effectively?
I think the instructions provide exactly what you are looking for; the "dropbox" part is of course optional (it's just a folder).
EDIT: Forget about the dropbox bit. Dropbox is just a local folder + a service that replicates it offsite. These instructions will work for you too WITH A LOCAL FOLDER.
The important bit it to create a (local) bare repo which you setup as a 'git remote' and push your changes to.
Let me copy and paste from quoted thread, and make the changes for you.
Something like this should work:
~/Sites/Kamma $ git init
~/Sites/Kamma $ git add .
~/Sites/Kamma $ git commit -m "first commit"
~/Sites/Kamma $ cd ~/Sites/Kamma_bak
~/Sites/Kamma_bak $ mkdir Kamma.git
~/Sites/Kamma_bak $ cd Kamma.git
~/Sites/Kamma_bak $ git init --bare
~/Sites/Kamma_bak $ cd ~/Sites/Kamma
~/Sites/Kamma $ git remote add origin ~/Sites/Kamma_bak/Kamma.git
~/Sites/Kamma $ git push origin master
Note: A “backup” copy on the same machine is not much of a backup (especially if it is on the same disk). To be reliable you really need to copy your data to one (or more!) different machines/media, preferably in different locations.
It sounds like your “backup” is a bare repository, but want it to be a non-bare repository (i.e. you want it to have its own working tree checked out).
The problem is that pushing to a non-bare repository is usually not a good idea. Effectively, such pushes are likely to update the branch that HEAD points to without updating the index or working tree. This can lead to very confusing situations in the receiving repository (e.g. added files shown with a deleted status, etc.). For this reason, Git versions 1.7.0 and later default to refusing to accept pushes to the currently checked out branch of non-bare repositories.
Note: When you push to a bare repository for backup purposes, all the files contained in the pushed commits are there, they are just not checked out (they are compressed and kept in Git the object store as “loose objects” and “pack files”). The pushed data represents a full copy of history of the content that you committed and pushed. You just can not access the content directly. Instead, you must clone it to a non-bare repository repository (and thus checkout a commit) or use git archive
to extract a set of files without an additional repository or full checkout.
I am not really convinced that you need something like what you describe.
If you need to examine an old snapshot of your repository (and you do not feel like doing it in your normal working repository), then you should just clone a temporary copy and checkout the desired, old commit. Local clones are cheap since they can hardlink the object store files instead of copying them. The historical commit graph is generally all you need to “go back in time”. While Git will let you rewrite the history graph at will, you are not really in much danger of making unrecoverable changes since it usually requires -f
/--force
switches and/or provides recovery mechanisms (reflogs, refs/original/, minimum age requirements before collecting unreferenced objects, etc.).
It is a good idea to have another repository (especially on another machine in another location) where you can push your commits for backup purposes (so that you can recover from (e.g.) rm -rf working_repo
), but a bare repository is usually entirely sufficient. When you need to recover, you just make a clone. When you want to examine some old snapshot without disturbing your normal working repository, you make a temporary clone somewhere. With good commit hygiene, git diff
, git log
(especially the -p
and -S
options), and git show
can often provide whatever “archeological” information you might want from old commits without needing to checkout anything at all (they even work in bare repositories).
However, if you are willing to accept the risk, you can do exactly what you want.
Git, like any other “sharp” tool, will let you risk “shooting yourself in the foot” (pardon the mixed metaphor).
Create and configure your backup repository and add it as a remote in the working repository.
# paths to the repositories WORKING=/path/to/working BACKUP=/path/to/backup # name for the backup repository in the working repository REMOTE=backup ! test -d "$BACKUP" || (echo "error: $BACKUP already exists"; exit 1) && git clone --origin working "$WORKING" "$BACKUP" && ( cd "$BACKUP" && git config receive.denyCurrentBranch false && git remote rm working ) && ( cd "$WORKING" && git remote add "$REMOTE" "$BACKUP" && git config remote."$REMOTE".push 'refs/heads/*:refs/heads/*' )
In the backup repository, setup a
post-receive
orpost-update
hook that does agit reset --hard
. This will keep the index and working tree up to date with the currently checked out branch.The Git FAQ “Why won't I see changes in the remote repo after "git push"?” points to an example
post-update
script that can do this relatively safely (it saves a stash if the working tree or the index are dirty—this can still lose untracked files if newly added files with the same pathnames are pushed).( H="$BACKUP"/.git/hooks/post-update && curl http://utsl.gen.nz/git/post-update >$H && chmod +x "$H" )
Push to the backup repository when you want to update it.
(cd "$WORKING" && git push "$REMOTE")
If you use a setup like this, you should absolutely avoid working in the backup working tree. Any commits you make there, any staged changes you leave there, and any untracked files you leave there are liable to be lost.
git init
will create a git repo. To make the backup, do a git clone --no-hardlinks
on the original repo to copy it. From there you can do a push from one repo to the other.
精彩评论