Reputation: 223
Is there a way to copy the exact state of a local git repo (uncommitted changes and all) to another local repo?
The destination repo should be switched to the exact state of the source repo, including the branch, commit and any uncommitted changes since the last commit - edits, new files, deletions...
Short of copying the entire directory every time I need this functionality, I can't think how to do it.
Obviously checking the destination repo out to the same commit will be easy, however it's the uncommitted changes I'm not sure about.
Edit (why I want this!) I am building a local build system (for Unity games). Normally whilst a build is underway inside of Unity you can't use the program for anything else, so I have a system where another instance of Unity makes the build on a carbon copy of the project files. Each time I trigger a build I delete the old copy and make a new copy, however my thinking is that if the copy is on the same commit and say only two uncommitted files different it would be much quicker just to patch the state. I make builds of uncommitted work whilst testing so commiting changes isn't really an option!
Any suggestions greatly appreciated!
Cheers
Upvotes: 0
Views: 554
Reputation: 534893
Short of copying the entire directory every time I need this functionality, I can't think how to do it.
What’s wrong with copying the entire directory? If you really prefer not to (e.g. because it is huge), use any folder synchronization utility, such as rsync
. I use both those approaches very often.
Upvotes: 3
Reputation: 487755
You can use an archiver (tar
or whatever) to collect the entire repository-and-work-tree state and copying that to some other file-tree area:
cd /path/to
tar cf - repo | (cd /different/path; tar xf -)
for instance copies the entire file-tree from /path/to/repo
to /different/path/repo
. This copies both the repository itself—all the files in .git
—and the work-tree (all the files that aren't in .git
).
There are a few caveats here. The most important is that the .git
underneath the top level of the work-tree must really be a directory containing the repository, not just a file like those created by git worktree add
.
Using in-Git methods, such as git clone
, won't work: they only copy the repository. The work-tree is not part of the repository:
Short of copying the entire directory every time I need this functionality, I can't think how to do it.
That's because Git literally won't do it. The work-tree—your work-tree—is yours, not Git's, and it's not part of the Git repository. It's just there next to the repository, which is the stuff in the .git
subdirectory.
If you have Git 2.5 or later—preferably 2.15 or later, because there was a pretty nasty bug in it until then1—whatever you are thinking of doing like this is probably better handled through git worktree add
. That creates a separate work-tree, which again is yours and not Git's, in which Git does a git checkout
of some commit or branch of your choice at the time you run git worktree add
. That second work-tree doesn't have its own repository: it uses the original work-tree's repository, by creating a file named .git
instead of a directory named .git
.
(The actual repository acquires, at the point of git worktree add
, a lot of state files to track the existence of this added work-tree. The added work-tree requires adding a new index, new HEAD
, and so on, all of which are dedicated to the new work-tree and separate from the index and HEAD
and so on for the primary work-tree, which is still sitting next to the main repository. Note that if you later copy the actual repository using the above tar
trick, it will still think it has these added work-trees. If they do still exist, that's fine; if not, git worktree prune
will make the copied repository update its notion of how the outside world looks.)
1The bug is that git gc
failed to look in the added HEAD
and index and such files. This means that if you:
git add
updated files but don't commit, any new repository-level blob objects can be deleted (!)which results in a mess.
The standard default 14 day grace period means that if you get all your work done within 14 days and then discard the added work-tree, this bug never hits you, so if you have a Git version below 2.15, you can use git worktree add
safely as long as you do everything in the added work-tree within two weeks.
(The bug actually bit me, though. Fortunately the added work-tree was merely an experiment that I had abandoned but had not gotten around to removing, and I was able to clean things up.)
Upvotes: 1