I've gone and looked at the cluster.git history and realize that we're not
using git quite as we should.  We're polluting the cluster.git history
with unnecessary "merge commits".  It's not that git is being used wrongly
per se, just not "nicely".  Not to blame anyone, but pull up git web in
your browser and notice these kinds of entries in the history:

Lon Hohberger Merge branch 'master' of ssh://[EMAIL PROTECTED] ...

Ryan McCabe Merge branch 'master' of ssh://sources.redhat.com/git ...

Christine Caulfield Merge branch 'cman3'

Chris Feist Merge branch 'RHEL4' of ssh://sources.redhat.com/git ...


The short and easy answer for how to avoid this is that between these two
steps:
1. creating a new branch that you will add commits to and eventually push from
2. actually pushing from that branch

you should not do any merges within that branch.  That includes not doing
any git-pull's in that branch (pull does a merge).

If you google for "git avoiding merge commits" you'll find a number of git
howto's for various projects that explain this problem (and how to avoid
it) differently.

There are two main ways to use git:
- merging mode
- rebasing mode

Git was designed especially for the merging style where there's a lot of
pulling and a large heirarchy of maintainers, like the linux kernel.  A
large portion of the documentation focuses on how to use git in the
merging/pulling mode.  This is not for us; we have a completely flat
hierarchy.

In the "rebasing" style, git is largely just a fancy patch manager like
quilt.  This is the appropriate method for us.  It means that you only
really use git pull to update the branches that you don't use directly.
With the branches you *do* use (branched from the former ones that you
update by pulling), you only typically use git-commit, git-rebase, and
git-cherry-pick, which all simply apply commits one on top of another as
patches; they don't do merges.

git-branch
  master
* rhel5

(rhel5 was created via git checkout -b rhel5 origin/RHEL5, I don't ever
commit anything to rhel5)

git pull

(updates rhel5 branch with all the latest changes in the repository)

git checkout -b fix-bz1234 rhel5

(create a branch to do some work)

git commit

git push ssh://sources.redhat.com/git/cluster.git fix-bz1234:RHEL5

(if this fails, then someone has checked something into the RHEL5 branch
since I updated by copy via the pull)

To resolve this,

git checkout rhel5

git pull

(updates rhel5 branch with the new commit)

Now there are two ways to recreate your branch with fixes without doing a
merge.

Option 1, using git-rebase
--------------------------

(we were in the now updated rhel5 branch)

git checkout fix-bz1234

git format-patch -1 --stdout > /tmp/fix-bz1234.patch

(save work in case something goes wrong)

git rebase rhel5

(this places your commit on top of the latest rhel5 code without doing a
merge and a merge commit, which we are trying to avoid.  Do not use
git-pull to combine the latest rhel5 code with your fix-bz1234 branch, as
that will create an unnecessary merge commit.)

git push ssh://sources.redhat.com/git/cluster.git fix-bz1234:RHEL5

(should now work)

Option 2, using git-cherry-pick
-------------------------------

(we were in the now updated rhel5 branch)

git checkout -b fix-bz1234-try2

git log fix-bz1234
and copy the SHA1 of the commit you made

git-cherry-pick <SHA1 of your commit>

git push ssh://sources.redhat.com/git/cluster.git fix-bz1234-try2:RHEL5

(should now work)



There is another good use for git-pull, and that is to combine multiple
local branches together into a local collection that you want to test.
Say you have local branches fix-1234 and fix-5678, both based off the
rhel5 branch, and you want to combine the fixes to test them together.
You'd do something like this:

git checkout rhel5

git checkout -b ALL rhel5

git pull . fix-1234

git pull . fix-5678

Now you can test the ALL branch, but you shouldn't commit from it.


Reply via email to