With git, source code lives in a single working directory. When we switch from one branch to another, git rearranges our files for us. Usually this keeps things simple, but now and then I wish for two copies of the code.
Do you ever want to run a big fat suite of tests in one branch while working on code in another branch? I do! This requires two different versions of the code on the filesystem at the same time.
Before you go making another copy of the whole repository, consider this solution: write a version of the for-testing branch to a temporary place outside of your working directory. Run the tests over there, leaving the real local repository available for work as usual.
1. Create a temporary directory. Maybe /Users/me/somewhere
2. Go to your git repository, to the project root directory. Now run this command:
git archive branchypoo | tar –xC /Users/me/somewhere
git archive takes the whole source tree from branchypoo, tars it up, and writes the result to stdout.
tar –x extracts the files from stdin
-C means “do the extraction over in this directory.”
Now you’re clear to run tests over in /Users/me/somewhere, and your local repository is ready for real work.
Thanks to JørgenE for this trick!
The original post used three steps:
0. Commit or stash any changes you have lying around. (important!)
1. Create a temporary directory. Maybe /Users/me/some/where/else
2. Go to your git repository, to the project root directory. Now run this crazy command, and don’t forget the dot at the end:
git –work-tree=/Users/me/some/where/else checkout branch-of-interest — .
–work-tree=/Users/me/some/where/else tells git to act like your working directory is in some other location.
checkout writes the specified version of the specified files into your (modified) working directory. Note that checkout behaves differently when given a filepath; if you leave that out, checkout will change your current branch and not give you all the files.
branch-of-interest is a branch name, or any commit identifier.
— says “I’m done naming commits, here come some paths to files”
. chooses the current directory, including all subdirectories and so on.
The whole command means “Write all the files, as they currently exist on branch-of-interest, into this directory over here (and my staging area).” The staging-area bit is unfortunate. If there’s a way to tell checkout to skip that, I’d like to know it.
3. Fix your staging area. git status will tell you that you have a bunch of changes to be committed, and a bunch of other changes. Tell it to forget about that stuff in the staging area.
Now you’re clear to run tests over in /Users/me/some/where/else, and your local repository is ready for real work.
8 thoughts on “Git: Checkout multiple branches at the same time”
See also contrib/workdir/git-new-workdir in git.git; that's quite similar to what it does!
Hey Jessica.In these cases I usually just do a clone – Git will use 'alternates' to ensure it shares the same packs/objects and doesn't copy the entire .git dir, which means it's almost instant. The nice thing is that the second folder is a fully bona fide Git repository – so you can checkout other branches as you require.
(But 'clone' I mean 'git clone /Users/me/first/clone /Users/me/some/where/else')
How about:git archive branch-of-interest | tar -xC /Users/me/some/where/elseIt is more clean.
Does git use alternates automatically, or is that something to set up?
Love it. Will update post. Thanks!
Hmm. I thought it was on by default – I'm mistaken. But if you run 'git clone -s' on a local repository it will use alternates, other it uses hard-links. Either way it's pretty quick. 🙂
git-archive doesn't grab submodules. I don't think git-checkout does either. Use git-archive-all  if you use submodules.  https://github.com/Kentzo/git-archive-all
Comments are closed.