4

On my development computer I've previously used git simply as an automatic backup / recovery system. I know this isn't quite how git is intended to be used, but it has been very effective for me. I have a simple script that runs every 5 minutes (a la Windows Task Scheduler) and checks to see if any files have changed. If so, it creates a new commit (with the message "Automatic Commit") and pushes it to a mirror I have on an external hard drive. I can extend this to push to mirrors in other locations, too.

I don't want to stop doing this, as the system has saved my life more than once. Between power failures, accidental file deletions, or a client suddenly deciding they liked how the project looked 2 months ago and they want to revert all the changes - the ability to roll everything back to any point in time has been invaluable.

Now the problem comes when I want to put one of these repositories on github for collaborative work. Every time I push to github it creates tens or hundreds or commits, often with incomplete code since I was in the middle of modifying a file when five minutes rolled around.

I would like to have a second repository of sorts residing in the same directory and watching over the same files, however I want it to only commit manually. This way when I push to github there are only meaningful commits and all my automatic backups are hidden from prying eyes.

Is this even possible?

Quick Edit -

Googling around, could the git rebase command be of any use? It seems like it may destroy all the automatic commits, which isn't exactly the ideal behavior.

Long Edit -

This little project has been a NIGHTMARE.

Following the advice from @janos I set set up a second repository in every folder. To set these up I simply used git clone on the current repository. I modified my autosave.bat file to utilize GIT_DIR and GIT_WORK_TREE and thought everything would be dandy... it wasn't

First, try the following on a Windows 7 PC for fun:

test.bat
--------

CD C:\SomeFolder
FOR /D %%i in (*) DO (
    CD %%i
    set GIT_WORK_TREE=%cd%
    echo %GIT_WORK_TREE%
    CD ..
)

The results of this should be obvious, right? We step through every sub-directory in SomeFolder, set it to the current GIT_WORK_TREE, then output GIT_WORK_TREE. The output:

C:\SomeFolder
C:\SomeFolder
C:\SomeFolder
C:\SomeFolder
....

It looks like batch scripts are executed out-of-order (set GIT_WORK_TREE=%cd% is processed before CD %%i has completed). You can only imagine the horror this wreaked on my backups when every single project was in every other project's repository.

I tried to get around this using git --git-dir=backup.git --work-tree=%cd% only to get errors when folders had a space in the name (I had to put %cd% in quotes)

I finally got that working and backup.git wasn't recognized as a git directory and was added to the repository! I added the following to my .gitignore to be safe:

# git is really making me angry today
/.git/
/backup.git/

With that I think it's finally working, but I shudder to test my remote backups and see if they're actually set up correctly.

stevendesu
  • 15,753
  • 22
  • 105
  • 182
  • Here's a SO question about it: http://stackoverflow.com/questions/2519446/multiple-git-repositories-in-one-directory – lincb Dec 30 '13 at 03:03
  • @lincb: That question doesn't quite address my own. Their issue was one of file permissions. Given a directory is 4 files, they wanted 2 of the files to be in one repo and 2 of the files to be in the other. I want all 4 files in BOTH repos, but want one repo to have 300 commits and the other to have a single massive commit containing all the changes. – stevendesu Dec 30 '13 at 03:07
  • Oh, sorry. I'll look for something else. – lincb Dec 30 '13 at 03:09

2 Answers2

5

I don't think your setup is bizarre. I know at least one guy who has an emacs hook to commit his repo every time he saves a file (he's an xemacs maintainer btw).

There is a perfectly clean way of doing what you want, thanks to the GIT_DIR and GIT_WORK_TREE variables. For example, given any Git repository, you can setup an "autocommit" repository that's independent from the "official" repository that you push to GitHub.

Initializing an autocommit repo

cd /path/to/project
export GIT_DIR=/tmp/autocommit.git
export GIT_WORK_TREE=$PWD
git init
git add .
git commit -m init

Updating an autocommit repo = autocommit.sh

#!/bin/sh
export GIT_DIR=/tmp/autocommit.git           ## same path as you initialized
export GIT_WORK_TREE=/path/to/real/project   ## same path as you initialized
git add --all                                ## --all takes care of deletes too
git commit -m auto-commit

That's it. The two repos don't even need to know of the existence of the other.

UPDATE

To answer to your follow-up questions:

if I used GIT_DIR to create a second repo in the same directory, would I also have to export GIT_DIR=/tmp/.git before committing my manual commits?

For your manual commits, don't use these variables at all. Use the Git repository as you normally would. The autocommit repo is completely independent, it doesn't affect your regular repo in any way. In short, no setup needed for your regular use.

I work mostly on Windows and I'm not sure if the GIT_DIR environment variable will work - can I use git --git-dir=... just as effectively?

I suggest to wrap the autocommiter into its own script, where it can setup the environment variables it needs. Since you have multiple autocommit repos, maybe you want to create a common autocommit.sh that takes parameters, which you call from wrapper scripts, one per repo. For example. This is just one way of doing it.

is it possible to change the git directory of an existing repo? Is it as easy as renaming the .git folder? Because I already have four or five projects auto-committing to the default repo instead of autocommit.git and I would like to change these.

I suggest to keep your regular repo as is. Create new clones for autocommit like this:

git clone --bare /path/to/proj1 /my/autocommits/proj1.git
janos
  • 120,954
  • 29
  • 226
  • 236
  • Two questions: First, if I used `GIT_DIR` to create a second repo in the same directory, would I also have to `export GIT_DIR=/tmp/.git` before committing my manual commits? Second, I work mostly on Windows and I'm not sure if the `GIT_DIR` environment variable will work - can I use `git --git-dir=... ` just as effectively? – stevendesu Dec 30 '13 at 12:08
  • Actually, third question really quickly - is it possible to change the git directory of an existing repo? Is it as easy as renaming the `.git` folder? Because I already have four or five projects auto-committing to the default repo instead of `autocommit.git` and I would like to change these. – stevendesu Dec 30 '13 at 12:09
  • Accepting this since it lead me in the right direction, but as per my edit there was a lot of unexpected work to be done - like the fact that git doesn't recognize `backup.git` as a git directory automatically. – stevendesu Dec 31 '13 at 14:03
  • @stevendesu Ouch. Sorry to hear your troubles. If you pinged me I could have given you some tips. For example, don't script in DOS. You can use Git Bash! I don't have a Windows with me now, but in the worst case you can have a DOS wrapper script that calls the bash script that does the real job, and that way things are a lot less painful. DOS is really awful to script, but if you have Git Bash there's no reason to be stuck with DOS. Btw I do this kind of scripting all the time at work, but I'm at home now that's why I can't give more specifics. – janos Dec 31 '13 at 14:54
1

I haven't tried this solution, but the concepts seem right. http://grahamc.com/blog/multiple-git-repositories-one-directory-dotfiles/ It seems to set the Git environment variable to one dir while having the repo in another dir.

lincb
  • 622
  • 5
  • 20
  • I've tried this, and it works wonders; you download the 4 files from the link above, put them anywhere within your path (the easiest place is the bin dir under your home, which the git bash window seems to automatically add to the path), and then run the following: git multi work ... this will create a new bash shell, which you can then use to do your normal tasks (e.g. git add, git commit, git pull, git push, etc). – Leo Oct 16 '14 at 15:01
  • This link is down. Can anyone help? – SwimBikeRun Jun 16 '15 at 17:50
  • @SwimBikeRun https://web.archive.org/web/20141221053421/http://grahamc.com:80/blog/multiple-git-repositories-one-directory-dotfiles/ – Flurrywinde Aug 30 '22 at 02:27