GIT: How to avoid duplicated commits while maintaining lots of forks?

530 views Asked by At

I have a base repository with a "base site" that I clone to make my clients sites, so I work, make commits, push to the client fork, then I realize that in the middle of my commits there is one or more that must be merge to the base repository. That's what I did:

git format-patch -1 SHA

Then I go to the "base site" repository and do:

git am -3 patch_file

It's ok. The problem is when I want to pull changes from the "base site" to the client repo the commit is duplicated.

Is there a way to avoid that? Maybe a different workflow?

EDIT:

In fact I'm still having problems, my explanation isn't so clear. Let me try again:

I have a base repository that contains a 'docs', 'layout', 'pub' and 'sql' folder, there is just a blank 'index.html' in the 'docs' and 'layout' folder. In the 'pub' folder I have Joomla installed.

When I have a new client I make his directory and init a repository, then I add a remote 'base' pointing to the base bare repository, fetch it, checkout base/master and then do 'checkout -b master' to create the master branch from the base's master branch. Then I make a 'clone --bare' in my local server and clone from it in local workstations. We save docs when needed, the designer makes the layout then all of it is commited and pushed to the client's bare repo. We always do a 'rebase origin/master' before pushing, to make sure the local repo is up to date.

So when the layout is done and pushed, I pull it and start to make the Joomla template. So I make a lots of commits, then I realise that I have to make changes in our Joomla components to something to work as it should. Ok, I change a component, commit and continue to making the template, commit, ...

Now I want to bring all the component's commits to the 'base repo' because I want all my clients to have the same changes. When I tried @jleedev solution, all my client's commits went to the top, rewriting it's SHA's that were already in the client's bare repo.

Any ideas?

Thanks!

1

There are 1 answers

6
Josh Lee On

Yes! The git-pull command performs a fetch followed by a merge. The merge yells at you since you have the same patch expressed as two commits with different names.

If you do git-pull --rebase, or the two-step equivalent of git fetch; git rebase origin/master, then it will rebase your local changes onto the upstream.

Let's say your repo looks like this; master contains the work you've done in client, and origin/master represents the upstream base onto which you've applied the emailed patch. After you fetch, you see two divergent branches, but the commit that you've exported is in both lines.

~/client-site$ git fetch origin master

It looks like this in GitX:

After the fetch http://grab.by/m1T

When you rebase, it takes all your commits on client that aren't in base, converts them from commits to patches, and applies them one by one onto the upstream head. When it notices that two commits express the same patch, they get smooshed into one (the upstream commit lives and the local one dies).

~/client-site$ git rebase origin/master

After the rebase http://grab.by/m1X

As @roe mentions, there are probably better ways to keep your repositories in sync, such as cherry-picking the commit you need and then pushing it. It's quite possible to run into issues when you rebase, but the way you described your workflow of exporting a patch using format-patch and am seems pretty safe.