Theodore Tso <tytso@xxxxxxx> wrote: > On Tue, Aug 28, 2007 at 12:10:59AM -0400, Shawn O. Pearce wrote: > > Its what happens when you use `git clone --shared A B` and the ... > This has been discussed before, and it wouldn't be *that* hard to have > "git clone --shared" create a backpointer from B to A, so that > "git-prune" could also search the B's refs and not prune anything that > is in A which is reachable from heads in A and B. Not if I already have a pointer from B to A's refs. repo.or.cz also has this same pointer: git clone --shared A B ln -s A/refs B/refs/forkee If we then do the backpointer we'll get a circular loop between these two repositories and the output of git-ls-remote will be horrid to look at. It will also be confusing when you push, as we'll try to match "refs/forkee/refs/forker/refs/forkee/heads/master"... ;-) The reason I (and repo.or.cz) create the pointer from B to A is so that push and fetch can see that B already has the objects in A and clients shouldn't transfer them, because B already has them. > > At day-job I have a hard rule that you cannot even push into an A, ... > Why don't you even allow people to push into A? That should be > safe.... Push new things yes. Rewind a branch or delete a branch, no. I actually don't allow pushing into A because it just doesn't make sense in my particular environment for this particular class of A. > > So it really comes down to a rule like the following: ... > This is morally the same, but it makes the hardlink step easier (only > one pack to link from A to B), and by using git-gc mit makes it > conceptually easier for people to understand what's going on. > > git --git-dir=A gc > ln A/.git/objects/pack/* B/.git/objects > git --git-dir=B gc --prune > git --git-dir=A prune No, it won't work. The problem is that during the first `git --git-dir=A gc` call you are deleting packfiles that may contain objects that B needs. *poof*. They are gone. B cannot traverse its object list to gc itself during the third command. That's why you have to do the hardlinking of *everything* stored in A (even if it is not reachable) into B before you can gc A. The shorter and safest approach is the following, but it will cost a lot of disk space and IO while running: git --git-dir=B repack -a -d ; # yes, really no -l ! git --git-dir=A repack -a -d git --git-dir=B repack -a -d -l ; # yes, now use -l The first repack of B will copy everything from A into B, so that if the repack of A removes the object it will reside in B and B's own repack can keep the object. But if A still has the object then B won't copy it during the final repack of B. You have to use repack here and not gc as gc defaults to including the -l flag. -- Shawn. - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html