'How can I have multiple working directories with Git?

I'm not sure if this is something supported by Git, but in theory it seems like it should work to me.

My workflow often involves my editing of files in multiple branches simultaneously. In other words, I often want to open a few files in one branch is while I edit the contents of another file in another branch.

My typical solution to this is to make two checkouts, but it's a shame I can't share branches and refs between them. What I would like is to just have two working directories managed by the same .git folder.

I'm aware of local git clone solutions (the default, which is to hardlink shared objects, and the --shared option, which sets up an alternate object store with the original repo), but these solutions only cut down on disk space usage, and especially in the case of --shared, seem fraught with peril.

Is there a way to use one .git folder, and have two working directories backed by it? Or is Git hardcoded to have just one working directory checked out at any time?

git


Solution 1:[1]

The git distribution comes with a contributed script called git-new-workdir. You would use it as follows:

git-new-workdir project-dir new-workdir branch

where project-dir is the name of the directory containing your .git repository. This scripts creates another .git directory with many symlinks to the original one except for files that cannot be shared (like the current branch), allowing you to work in two different branches.

It sounds a bit fragile, but it's an option.

Solution 2:[2]

I came across this question hoping for a solution I didn't find here. So now that I did find what I needed, I decided to post it here for others.

Caveat: This is probably not a good solution if you need to edit multiple branches simultaneously, like OP states. It is for having multiple branches checked out simultaneously that you don't intend to edit. (Multiple working directories backed by one .git folder.)

There were a few things I've learned since I came to this question the first time:

  1. What a "bare repository" is. It is essentially the contents of the .git directory, without being located in a working tree.

  2. The fact that you can specify the location of the repo you are using (the location of your .git dir) on the command line with the git option --git-dir=

  3. The fact that you can specify the location of your working copy with --work-tree=

  4. What a "mirror repo" is.

This last is a pretty important distinction. I don't actually want to work on the repo, I just need to have copies of different branches and/or tags checked out simultaneously. In actual fact, I need to guarantee that the branches don't end up different from my remote's branches. So a mirror is perfect for me.

So for my use case, I got what I needed by doing:

git clone --mirror <remoteurl> <localgitdir> # Where localgitdir doesn't exist yet
mkdir firstcopy
mkdir secondcopy
git --git-dir=<localgitdir> --work-tree=firstcopy checkout -f branch1
git --git-dir=<localgitdir> --work-tree=secondcopy checkout -f branch2

The big caveat about this is that there isn't a separate HEAD for the two copies. So after the above, running git --git-dir=<localgitdir> --work-tree=firstcopy status will show all the differences from branch2 to branch1 as uncommitted changes - because HEAD is pointing at branch2. (That's why I use the -f option to checkout, because I'm not actually planning to make any changes locally at all. I can checkout any tag or branch for any work-tree, as long as I use the -f option.)

For my use case of having multiple checkouts co-existing on the same computer without needing to edit them, this works perfectly. I don't know if there is any way to have multiple HEADs for the multiple work trees without a script such as is covered in the other answers, but I hope this is helpful to someone else anyway.

Solution 3:[3]

The only solution I can think of is to clone two directories and add them as remote repositories of each other. You can then keep pulling stuff from the changed one into the other without actually pushing anything to the remote repository.

I am assuming you want to have two working directories and not two clones of the remote because you don't want to push some branches to the remote. Otherwise, two clones of your remote would work just fine - you just need to do some pushes and pulls to keep all three in sync.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dem Pilafian
Solution 2 Community
Solution 3 vhallac