On Sun, 23 Dec 2012 12:57:55 -0800 (PST)
Francesco Rugiano <frarug...@gmail.com> wrote:

> Now, in order to keep the local repositories small, i wanted to
> remove committs A, B and C. I wanted, however, to keep them on the
> remote repository, in order to be able to revert to them in the
> future. I mean having a situation like this:
> Remote repository - committs A->B->C->D->E
> Local repository on PC1 - committs D->E
> Local repository on PC2 - committs D->E
> Then, if PC2 committs something (after all the syncs):
> Remote repository - committs A->B->C->D->E->F
> Local repository on PC1 - committs D->E->F
> Local repository on PC2 - committs D->E->F
> Can i do this? if yes, how? if not, what are the alternatives?

I'm not sure it would work for you, but look at `git replace` [1].
Basically, using this feature, you might pretend that A->B->C
line exists in the PC1 and PC2 repos, but is in fact absent.
To do this, you first record an empty commit object and then
create a "replacement record" for it as described in the `git replace`
manual.  Such a record has to replace the SHA-1 name of the D's parent
with the SHA-1 name of your empty bogus commit.

To create an empty commit, you do this:

$ git checkout --orphan bogus  # (1)
$ git rm -rf --cached \*  # (2)
$ git commit --allow-empty  # (3)
$ git tag empty  # (4)

Now you can check your main branch back (using the "--force" option to
`git checkout` or it will refuse to overwrite files which are
now appear to be untracked to it), remove that orphan temporary branch
using `git branch -D orphan` and then use the SHA-1 name of the commit
pointed to by the tag "empty" as the replacement.

Explanation of the steps above:

(1) Checks out a new branch with no ancestry.  This is needed so that
    the commit we'll record on it has no parent.

(2) After creating of an orphan branch on step (1), the index still
    contains all the files it contained before we carried out that step,
    so now we have to empty the index.  Note how we backslash-escaped
    the asterisk to protect it from being interpreted by the shell.

(3) Record our new empty commit with no parent.  You should probably
    give it a descriptive commit message.

(4) Now we tag our new commit to get a convenient handle on it as we
    will later delete our scratch orphan branch.

A final word of caution: you should understand well that each commit in
Git is a snapshot of the repository state at the time the commit has
been recorded.  In your case this means that the replacement trick
being discussed could only work if your commit D does not contain those
huge files contained in commits you want to trim off, that is, the
hierarchy of the tree objects referenced by the commit D must not
reference those big files.

1. http://www.kernel.org/pub/software/scm/git/docs/git-replace.html


Reply via email to