bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

git commit guidelines for gnulib


From: Jim Meyering
Subject: git commit guidelines for gnulib
Date: Mon, 17 Sep 2007 11:48:05 +0200

Simon Josefsson <address@hidden> wrote:
> Jim Meyering <address@hidden> writes:
>> Now that the cvs-to-git gateway is set up, I am ready to switch
>> gnulib development to git.
>
> I like it.
>
>> There are probably tools and services (web?) that rely on having
>> an actual CVS repository, but people who care about those can take
>> it upon themselves to adapt them to git -- or to the git/cvs
>> emulation, if needed.
>
> I'll change the daily autobuilder to use git.
>
>> Once we agree to make the switch, I'll add a CVS commit hook to
>> block all commits.  That will ensure that no one accidentally
>> commits a change from an old CVS work area.
>
> How would I commit things to the new git repository?  Are there any
> instructions available?

Hi Simon,

I'll post a new how-to separately, but you've prompted me to
write the following:

A few months ago, I posted some quick how-to things,
along with pointers to documentation.  Bruno posted some, too.
BTW, don't spend much (if any) time with cogito.  It's on the way out,
since its functionality has mostly been moved into git proper.
Also, once you use git, you needn't bother with stgit, guilt,
quilt, etc.[*]

However, I have one strong preference that I haven't yet mentioned:
=====================================
Be careful not to push merge commits.
=====================================

What that means is when using git, we should see a single string of
change sets on the trunk, just as we did in CVS.  Each "commit" should
have exactly one predecessor and one successor.

How can that go wrong?
If you update (pull/fetch/whatever), make a change,
and commit (locally), but don't push right away...
Then, someone else makes a change, commits, and pushes theirs.
After that, you pull (using cvs model), and that induces a merge,
but there were no conflicts, so you then push the result.
However, if you look at the resulting graph with e.g., gitk, you'll see
that the change set before yours now has two successors:

       Next
       / \
  other   yours
       \ /
       Prev

That's unnecessary and ugly.
You could have avoided it by using a topic branch.  Here's how:
Say you checked out gnulib like this:

  git clone git://git.sv.gnu.org/gnulib

then cd'd into it and ran:

  git checkout -b my-topic

that creates the my-topic branch and puts you on it.
To see which you're on, type "git branch".
Right after the clone, you were on "master" (aka the trunk).
To get back to the trunk, do this:

  git checkout master

Note 1:
    Be careful to run "git pull" only when on the "master" branch,
    not when on a branch.  I think that with the very latest
    version of git, you can't cause trouble if you forget, so
    be sure you're using 1.5.3.1 or newer. ]

Note 2:
    It's best not to try to switch from one branch to another if
    you have pending (uncommitted) changes.  Sometimes it works,
    sometimes the checkout will fail, telling you that your local
    modifications conflict with changes required to switch branches.

Anyhow, get back onto your just-created branch:

  git checkout my-topic

Now, modify some file and commit it:

  git commit some-file.c

I find it useful to put the ChangeLog entries *only* in
the commit log, initially, unless you plan to commit/push
right away.  Otherwise, you'll get more merge conflicts.

So, you've committed a change.  But it's only in your
local repository, and only on your "my-topic" branch.
Remembering our example, let's wait a day, and see that
someone else changed something and pushed it to the public
repository.  Now, you want to update your trunk and "rebase" your
changes on the branch so that they are once again relative to
the tip of the trunk.  Currently, your branch is attached to
the trunk at the next-to-last change set.

First: update the trunk from the public repo:
[you've first made sure that "git diff" produces no output]

  git checkout master
  git pull

Now, return to your branch, and "rebase" relative to trunk (master):

  git checkout my-topic
  git rebase master

If there are no conflicts, this requires no more work from you.
However, let's say there was one in ChangeLog, since you didn't
follow my advice and modified it anyway.
git rebase will tell you there was a conflict and in which
file, and instruct you to resolve it and then resume with
"git rebase --continue" once that's done.

So you resolve as usual, by editing ChangeLog (which has the
usual conflict markers), then type "git rebase --continue".
That will fail, with a diagnostic telling you to mark
the file as "conflict resolved" by doing this:

  git add ChangeLog

Then, finally, you can proceed (possibly onto more conflict resolution,
if there are conflicts in other files):

  git rebase --continue

Once it finishes, your changes on the branch are now relative to
the tip of the trunk.
------------------------------

Moving changes from your topic branch to the trunk:
===================================================

Here, I'm assuming you've just done the above, and your
changes on the desired branch are directly applicable to the trunk.

First, get on the trunk:

  git checkout master

Make sure there are no new changes:
[obviously there's a race here, so you
can't be 100% sure to avoid merges...]

  git pull

If the above *did* bring in new changes, go back to your branch
and rebase again.

Now, pull the just-rebased changes from your branch to ".", the current
branch (master):

  git pull . my-topic

If you did everything properly, there is no risk of conflict
with the above "pull".

Look at the result with "gitk" (or git-log) and make sure that
there is indeed no merge:

  gitk

If everything is ok, you can then do "git push" to publish
your change set.  Oops.  If you took my advice, and deferred
modifying the ChangeLog file, now is the time to copy your
commit log entry into ChangeLog.  Hmm.. but now what?
Commit your ChangeLog change as a separate change set?
I usually don't.  Instead, I "amend" the change set to which
it refers.

  git-add ChangeLog
  git commit --amend -e

The above is slightly risky, in general, since it modifies
an existing commit in your tree, rather than simply adding a new one.
You must not do this to a commit that you've already pushed.
If you do, you will be unable to push the result, because that would
cause trouble for everyone who might have refs to that displaced commit.
(it doesn't really modify a commit.  it adds a new one and uses it in
place of the old one).  I hesitated to mention this, because of the
risk, but it's just too useful.  Use with care.

The bottom line: that adjusts the "topmost" change set to include
whatever additional changes you want.  But you can do it only *before*
(not after) you've pushed.

One-line summary in log (followed by a blank line)
=================================================
Once you're happy with the result, (again, view with "gitk") and make
sure you have a good "one-line summary" as the first line of the log
message.  It's good to have a blank line in the log after that summary
line, or else some tools concatenate all following non-blank lines into an
annoyingly long string.

Finally, you can do:

  git-push

to publish your changes.

Jim

[*] if you use a new-enough version of git, you should no longer find
stgit, guilt, quilt, etc. necessary.  Instead, use "git rebase -i ..."
to maintain your private patch sets.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]