Thread: Multi-branch committing in git, revisited

Multi-branch committing in git, revisited

From
Tom Lane
Date:
Okay, so now that I've actually done a couple of multi-branch commits...

I'm using the multiple-work-directory arrangement suggested on our wiki
page.  The work flow seems to boil down to:

* Prepare patch in master
* Stage patch with git add
* git diff --staged >/tmp/patch-head
* cd into REL9_0_STABLE workdir
* patch -p0 </tmp/patch-head
* Adjust patch if needed
* Stage patch with git add
* git diff --staged >/tmp/patch-90
* cd into REL8_4_STABLE workdir
* patch -p0 </tmp/patch-90
* ... lather, rinse, repeat ...
* cd back to master
* git commit -F /tmp/commitmsg
* cd into REL9_0_STABLE workdir
* git commit -F /tmp/commitmsg
* cd into REL8_4_STABLE workdir
* git commit -F /tmp/commitmsg
* ... lather, rinse, repeat ...
* git push

While this isn't much worse than what I was used to with CVS, it's
definitely not better.  I think that I could simplify transferring the
patch back to older branches if I could use git cherry-pick.  However,
that only works on already-committed patches.  If I commit in master
before I start working on 9.0, and so on back, then the commits will be
separated in time by a significant amount, thus destroying any chance of
having git_topo_order recognize them as related.  So we're back up
against the problem of git not really understanding the relationships of
patches in different branches.

One idea that comes to me is to do each patch in a temporary side branch
off that maintenance branch, and then only the final commits merging
that work back to the public branches need be closely spaced.  But being
still a git novice, it's not exactly clear to me how to do that, and
anyway it seems like there's still possibility for trouble if there's
unexpected merging failures on some of the branches.  (That would only
be an issue if the back-patching took long enough for some of the
branches to change underneath me, which isn't too likely, but if it
did happen how do I recover and still keep the commits close together?)

So it seems like maybe we still need some more thought about how to
recognize related commits in different branches.  Or at the very least,
we need a best-practice document explaining how to manage this --- we
shouldn't expect every committer to reinvent this wheel for himself.

Comments?
        regards, tom lane


Re: Multi-branch committing in git, revisited

From
Andrew Dunstan
Date:
<br /><br /> On 09/21/2010 09:20 PM, Tom Lane wrote: <blockquote cite="mid:13289.1285118406@sss.pgh.pa.us"
type="cite"><prewrap="">Okay, so now that I've actually done a couple of multi-branch commits...
 

I'm using the multiple-work-directory arrangement suggested on our wiki
page.  The work flow seems to boil down to:

* Prepare patch in master
* Stage patch with git add
* git diff --staged >/tmp/patch-head
* cd into REL9_0_STABLE workdir
* patch -p0 </tmp/patch-head
* Adjust patch if needed
* Stage patch with git add
* git diff --staged >/tmp/patch-90
* cd into REL8_4_STABLE workdir
* patch -p0 </tmp/patch-90
* ... lather, rinse, repeat ...
* cd back to master
* git commit -F /tmp/commitmsg
* cd into REL9_0_STABLE workdir
* git commit -F /tmp/commitmsg
* cd into REL8_4_STABLE workdir
* git commit -F /tmp/commitmsg
* ... lather, rinse, repeat ...
* git push

While this isn't much worse than what I was used to with CVS, it's
definitely not better.  I think that I could simplify transferring the
patch back to older branches if I could use git cherry-pick.  However,
that only works on already-committed patches.  If I commit in master
before I start working on 9.0, and so on back, then the commits will be
separated in time by a significant amount, thus destroying any chance of
having git_topo_order recognize them as related.  So we're back up
against the problem of git not really understanding the relationships of
patches in different branches.

One idea that comes to me is to do each patch in a temporary side branch
off that maintenance branch, and then only the final commits merging
that work back to the public branches need be closely spaced.  But being
still a git novice, it's not exactly clear to me how to do that, and
anyway it seems like there's still possibility for trouble if there's
unexpected merging failures on some of the branches.  (That would only
be an issue if the back-patching took long enough for some of the
branches to change underneath me, which isn't too likely, but if it
did happen how do I recover and still keep the commits close together?)
</pre></blockquote><br /> I suspect you should indeed be working on topic branches for everything non-trivial. You can
safelycommit on them, cherry-pick from them, squash from them onto the main branch, and then discard them. You can
resolveproblems before committing on the main branch by doing:<br /><blockquote>git checkout mainbranch<br /> git merge
--squash--no-commit topicbranch<br /></blockquote> Unless I'm missing something there's no reason you should ever have
tohave a significant delay between branches in commits/pushes.<br /><br /> I know git has something of a learning
curve,but I'm betting that in a month or so you'll be better at using it than most of us ;-)<br /><br /> cheers<br
/><br/> andrew<br /> 

Re: Multi-branch committing in git, revisited

From
"David E. Wheeler"
Date:
On Sep 21, 2010, at 6:20 PM, Tom Lane wrote:

> While this isn't much worse than what I was used to with CVS, it's
> definitely not better.  I think that I could simplify transferring the
> patch back to older branches if I could use git cherry-pick.  However,
> that only works on already-committed patches.  If I commit in master
> before I start working on 9.0, and so on back, then the commits will be
> separated in time by a significant amount, thus destroying any chance of
> having git_topo_order recognize them as related.  So we're back up
> against the problem of git not really understanding the relationships of
> patches in different branches.

You could commit in each one as you go, cherry-pick, and then in each one
   git reset --soft HEAD^

Then they'd all be patched and staged.

Best,

David



Re: Multi-branch committing in git, revisited

From
Bruce Momjian
Date:
David E. Wheeler wrote:
> On Sep 21, 2010, at 6:20 PM, Tom Lane wrote:
> 
> > While this isn't much worse than what I was used to with CVS, it's
> > definitely not better.  I think that I could simplify transferring the
> > patch back to older branches if I could use git cherry-pick.  However,
> > that only works on already-committed patches.  If I commit in master
> > before I start working on 9.0, and so on back, then the commits will be
> > separated in time by a significant amount, thus destroying any chance of
> > having git_topo_order recognize them as related.  So we're back up
> > against the problem of git not really understanding the relationships of
> > patches in different branches.
> 
> You could commit in each one as you go, cherry-pick, and then in each one
> 
>     git reset --soft HEAD^
> 
> Then they'd all be patched and staged.

If I understand correctly, that 'git reset' will mark all branch changes
as staged but not committed, and then you can commit all branches at
once and push it.  Is that right?

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +


Re: Multi-branch committing in git, revisited

From
David Christensen
Date:
> If I commit in master
> before I start working on 9.0, and so on back, then the commits will be
> separated in time by a significant amount, thus destroying any chance of
> having git_topo_order recognize them as related.  So we're back up
> against the problem of git not really understanding the relationships of
> patches in different branches.


Is the issue here the clock time spent between the commits, i.e., the possibility that someone is going to push to the
specificbranches in between or the date/time that the commit itself displays?  Because if it's specifically commit time
that'sat issue, I believe `git cherry-pick` preserves the original commit time from the original commit, which should
makethat a non-issue.  Even if you need to fix up a commit to get the cherry-pick to apply, you can always `git commit
-C<ref-of-cherry-pick>` to preserve the authorship/commit time for the commit in question. 

Regards,

David
--
David Christensen
End Point Corporation
david@endpoint.com






Re: Multi-branch committing in git, revisited

From
"David E. Wheeler"
Date:
On Sep 21, 2010, at 8:01 PM, Bruce Momjian wrote:

>> Then they'd all be patched and staged.
> 
> If I understand correctly, that 'git reset' will mark all branch changes
> as staged but not committed, and then you can commit all branches at
> once and push it.  Is that right?

Right.

David



Re: Multi-branch committing in git, revisited

From
Bruce Momjian
Date:
David Christensen wrote:
> > If I commit in master
> > before I start working on 9.0, and so on back, then the commits will be
> > separated in time by a significant amount, thus destroying any chance of
> > having git_topo_order recognize them as related.  So we're back up
> > against the problem of git not really understanding the relationships of
> > patches in different branches.
> 
> 
> Is the issue here the clock time spent between the commits, i.e., the
> possibility that someone is going to push to the specific branches in
> between or the date/time that the commit itself displays?  Because if
> it's specifically commit time that's at issue, I believe `git
> cherry-pick` preserves the original commit time from the original
> commit, which should make that a non-issue.  Even if you need to fix
> up a commit to get the cherry-pick to apply, you can always `git commit
> -C <ref-of-cherry-pick>` to preserve the authorship/commit time for
> the commit in question.

The problem is that the cherrypicks will often have to modified, and it
can take +20 minutes to resolve some of them.

-- Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +


Re: Multi-branch committing in git, revisited

From
Bruce Momjian
Date:
David E. Wheeler wrote:
> 
> On Sep 21, 2010, at 8:01 PM, Bruce Momjian wrote:
> 
> >> Then they'd all be patched and staged.
> > 
> > If I understand correctly, that 'git reset' will mark all branch changes
> > as staged but not committed, and then you can commit all branches at
> > once and push it.  Is that right?
> 
> Right.

OK, I am scared I actually understood that.  ;-)

Is there a command to commit all stated changes in all branches or do we
have to go around to each branch to do the commit on each one?  I
realize the push works to push all branch commits (or it only do that
from the master branch?).

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +


Re: Multi-branch committing in git, revisited

From
Tom Lane
Date:
"David E. Wheeler" <david@kineticode.com> writes:
> On Sep 21, 2010, at 8:01 PM, Bruce Momjian wrote:
>>> Then they'd all be patched and staged.
>> 
>> If I understand correctly, that 'git reset' will mark all branch changes
>> as staged but not committed, and then you can commit all branches at
>> once and push it.  Is that right?

> Right.

You sure about the "staged" part?  If I'm reading the git-reset man
page correctly, this command will revert your commit position and index,
leaving only the modified work files behind.  So it looks to me like
you need another round of git add, or at least git commit -a.

Offhand I think I like Andrew's recommendation of a shortlived branch
better.  In essence your idea is using the tip of "master" itself as a
shortlived branch, which is maybe a bit too cute.  If you get distracted
and need to do something else for awhile, the tip of "master" is not
where you want your not-yet-pushable work to be.

(For those following along at home, there are some mighty instructive
examples in the git-reset man page.)
        regards, tom lane


Re: Multi-branch committing in git, revisited

From
Bruce Momjian
Date:
Tom Lane wrote:
> "David E. Wheeler" <david@kineticode.com> writes:
> > On Sep 21, 2010, at 8:01 PM, Bruce Momjian wrote:
> >>> Then they'd all be patched and staged.
> >> 
> >> If I understand correctly, that 'git reset' will mark all branch changes
> >> as staged but not committed, and then you can commit all branches at
> >> once and push it.  Is that right?
> 
> > Right.
> 
> You sure about the "staged" part?  If I'm reading the git-reset man
> page correctly, this command will revert your commit position and index,
> leaving only the modified work files behind.  So it looks to me like
> you need another round of git add, or at least git commit -a.

The command was:
git reset --soft HEAD^

The --soft says:
          --soft              Does not touch the index file nor the working tree              at all, but requires them
tobe in a good order.              This leaves all your changed files "Changes to be              committed", as git
statuswould put it.
 

and the HEAD^ is the same as HEAD^1, which is on commit backward from
HEAD.  I assume ""Changes to be committed" means "staged".

> Offhand I think I like Andrew's recommendation of a shortlived branch
> better.  In essence your idea is using the tip of "master" itself as a
> shortlived branch, which is maybe a bit too cute.  If you get distracted

True.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +


Re: Multi-branch committing in git, revisited

From
Bruce Momjian
Date:
Bruce Momjian wrote:
> > Offhand I think I like Andrew's recommendation of a shortlived branch
> > better.  In essence your idea is using the tip of "master" itself as a
> > shortlived branch, which is maybe a bit too cute.  If you get distracted
> 
> True.

However, keep in mind that creating a branch in every existing backpatch
branch is going to create even more backpatching monkey-work.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +


Re: Multi-branch committing in git, revisited

From
Tom Lane
Date:
David Christensen <david@endpoint.com> writes:
> Is the issue here the clock time spent between the commits, i.e., the possibility that someone is going to push to
thespecific branches in between or the date/time that the commit itself displays?  Because if it's specifically commit
timethat's at issue, I believe `git cherry-pick` preserves the original commit time from the original commit, which
shouldmake that a non-issue.  Even if you need to fix up a commit to get the cherry-pick to apply, you can always `git
commit-C <ref-of-cherry-pick>` to preserve the authorship/commit time for the commit in question.
 

Oh, yeah, that's interesting.  So you could force all the commits to
match the timestamp of the first one.  That's sort of the wrong end
of the process though --- I'd rather have a timestamp closer to when
I'm done than when I start.

The other thing that comes to mind on further reflection is that by
the time you get done with the back-patching, the commit log message
might be different from what you thought it would be when you started.
I had an example just today:
http://git.postgresql.org/gitweb?p=postgresql.git;a=commit;h=829f5b3571241cae2cc1a02923439cd0725d683c
Fixing "make distdir" wasn't part of what I was doing when I started.
I suppose I could have done that in a separate series of commits, but
if the idea is to make things more efficient not less so, that's not
the direction I want to go.

So right now I'm thinking that the best approach is to do the work
in temporary topic branches, then make up a commit message and use
it while doing squash merges onto the public branches.  I hadn't thought
when I went into this that a two-line patch would justify a temporary
branch, but if you need to back-patch it, maybe it does.

In principle I guess that we could decide to use -c or -C for the squash
merges and thus make their commit timestamps exactly the same not only
approximately the same.  This seems a bit overly anal retentive to me
at the moment, but maybe sometime in the future it'll be an idea worth
adopting.
        regards, tom lane


Re: Multi-branch committing in git, revisited

From
Tom Lane
Date:
Bruce Momjian <bruce@momjian.us> writes:
> The problem is that the cherrypicks will often have to modified, and it
> can take +20 minutes to resolve some of them.

To say nothing of actually *testing* the patch in each branch, which is
Strongly Recommended if it didn't apply cleanly.  I've not infrequently
spent many hours on a difficult back-patch sequence.
        regards, tom lane


Re: Multi-branch committing in git, revisited

From
Tom Lane
Date:
Bruce Momjian <bruce@momjian.us> writes:
> However, keep in mind that creating a branch in every existing backpatch
> branch is going to create even more backpatching monkey-work.

Monkey-work is scriptable though.  It'll all be worth it if git
cherry-pick is even marginally smarter about back-merging the actual
patches.  In principle it could be less easily confused than plain
old patch, but I was a bit discouraged by the upthread comment that
it's just a shorthand for "git diff | patch" :-(
        regards, tom lane


Re: Multi-branch committing in git, revisited

From
"A.M."
Date:

On Sep 21, 2010, at 11:19 PM, Tom Lane wrote:

Offhand I think I like Andrew's recommendation of a shortlived branch
better.  In essence your idea is using the tip of "master" itself as a
shortlived branch, which is maybe a bit too cute.  If you get distracted
and need to do something else for awhile, the tip of "master" is not
where you want your not-yet-pushable work to be.

For uncommitted work, see also "git stash".

Cheers,
M

Re: Multi-branch committing in git, revisited

From
"David E. Wheeler"
Date:
On Sep 21, 2010, at 8:19 PM, Tom Lane wrote:

> You sure about the "staged" part?

Yes, I do it all the time (I make a lot of mistakes).

> Offhand I think I like Andrew's recommendation of a shortlived branch
> better.  In essence your idea is using the tip of "master" itself as a
> shortlived branch, which is maybe a bit too cute.  If you get distracted
> and need to do something else for awhile, the tip of "master" is not
> where you want your not-yet-pushable work to be.

Yes, I think using branches for everything is generally the way to go. But if you wanted to just use your existing
approach,then reset --soft HEAD^ would work, too. 

Best,

David




Re: Multi-branch committing in git, revisited

From
Heikki Linnakangas
Date:
On 22/09/10 04:20, Tom Lane wrote:
> Okay, so now that I've actually done a couple of multi-branch commits...
>
> I'm using the multiple-work-directory arrangement suggested on our wiki
> page.  The work flow seems to boil down to:
>
> * Prepare patch in master
> * Stage patch with git add
> * git diff --staged>/tmp/patch-head
> * cd into REL9_0_STABLE workdir
> * patch -p0</tmp/patch-head
> * Adjust patch if needed
> * Stage patch with git add
> * git diff --staged>/tmp/patch-90
> * cd into REL8_4_STABLE workdir
> * patch -p0</tmp/patch-90
> * ... lather, rinse, repeat ...
> * cd back to master
> * git commit -F /tmp/commitmsg
> * cd into REL9_0_STABLE workdir
> * git commit -F /tmp/commitmsg
> * cd into REL8_4_STABLE workdir
> * git commit -F /tmp/commitmsg
> * ... lather, rinse, repeat ...
> * git push
>
> While this isn't much worse than what I was used to with CVS, it's
> definitely not better.  I think that I could simplify transferring the
> patch back to older branches if I could use git cherry-pick.  However,
> that only works on already-committed patches.  If I commit in master
> before I start working on 9.0, and so on back, then the commits will be
> separated in time by a significant amount, thus destroying any chance of
> having git_topo_order recognize them as related.

In git, each commit has two timestamps. Author timestamp and committer 
timestamp. They are usually the same, but when you cherry-pick, the 
cherry-picked commit retains the original author timestamp, while commit 
timestamp changes. "git log" shows only the author timestamp, and if I'm 
reading git_topo_order correctly, that's what it cares about too. "git 
log --format=fuller" can be used to show both.

So AFAICS, if you use cherry-pick, you're fine. Even if you don't for 
some reason, you can override the author timestamp with "git commit 
--date=<date>".

--   Heikki Linnakangas  EnterpriseDB   http://www.enterprisedb.com


Re: Multi-branch committing in git, revisited

From
Elvis Pranskevichus
Date:
On September 21, 2010 11:47:30 pm Tom Lane wrote:
> Bruce Momjian <bruce@momjian.us> writes:
> > However, keep in mind that creating a branch in every existing backpatch
> > branch is going to create even more backpatching monkey-work.
> 
> Monkey-work is scriptable though.  It'll all be worth it if git
> cherry-pick is even marginally smarter about back-merging the actual
> patches.  In principle it could be less easily confused than plain
> old patch, but I was a bit discouraged by the upthread comment that
> it's just a shorthand for "git diff | patch" :-(
> 
>             regards, tom lane


cherry-pick is NOT just a shorthand for git diff | patch.  It is a single-
commit merge tool.  man page does not indicate that, but you can supply the 
merge strategy parameter, just like you would do with git merge, but AFAIR 
it's not necessary and cherry-pick will fallback to the default recursive 
merge when needed.
                             Elvis


Re: Multi-branch committing in git, revisited

From
Abhijit Menon-Sen
Date:
At 2010-09-21 21:20:06 -0400, tgl@sss.pgh.pa.us wrote:
>
> So it seems like maybe we still need some more thought about how to
> recognize related commits in different branches.

I'd suggest using "git cherry-pick -x" (or something similar) to mark
backported patches:
   -x  When recording the commit, append to the original commit message       a note that indicates which commit this
changewas cherry-picked       from. Append the note only for cherry picks without conflicts.       Do not use this
optionif you are cherry-picking from your       private branch because the information is useless to the
recipient.If on the other hand you are cherry-picking between       two publicly visible branches (e.g. backporting a
fixto a       maintenance branch for an older release from a development       branch), adding this information can be
useful.

I don't think it makes any sense to contort your workflow to commit to
different branches at the same instant just to be able to group commits
by timestamp. Using the trail left by cherry-pick -x is much better. You
can just commit your changes to master and cherry-pick them wherever you
want to. This is independent of doing the work in a topic branch.

(Of course, with git it's less troublesome to merge forward rather than
pick backwards, but that's a workflow change that's a lot harder to
adjust to.)

-- ams


Re: Multi-branch committing in git, revisited

From
Magnus Hagander
Date:
On Wed, Sep 22, 2010 at 05:47, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Bruce Momjian <bruce@momjian.us> writes:
>> However, keep in mind that creating a branch in every existing backpatch
>> branch is going to create even more backpatching monkey-work.
>
> Monkey-work is scriptable though.  It'll all be worth it if git
> cherry-pick is even marginally smarter about back-merging the actual
> patches.  In principle it could be less easily confused than plain
> old patch, but I was a bit discouraged by the upthread comment that
> it's just a shorthand for "git diff | patch" :-(

FWIW, here's the workflow I just tried for the gitignore patch (blame
me and not the workflow if I broke the patch, btw :P)



* Have a master "committers" repo, with all active branches checked out (and a simple script that updates and can reset
themall automatically) 
* Have a working repo, where I do my changes. Each branch gets a checkout when necessary here, and this is where I
applyit. I've just used 
inline checkouts, but I don't see why it shouldn't work with workdirs etc.
* In the working repo, apply patch to master branch.
* Then use git cherry-pick to get it into the back branches (still in
the working repo) At this point, also do the testing of the backpatch.

At this point we have commits with potentially lots of time in between them.
So now we squash these onto the committers repository, using a small script that
does this:


#!/bin/sh

set -e

CMSG=/tmp/commitmsg.$$

editor $CMSG

if [ ! -f $CMSG ]; then  echo No commit message, aborting.  exit 0
fi

export BRANCHES="master REL9_0_STABLE REL8_4_STABLE REL8_3_STABLE
REL8_2_STABLE REL8_1_STABLE REL8_0_STABLE REL7_4_STABLE"

echo Fetching local changes so they are available to merge
git fetch local

for B in ${BRANCHES} ; do  echo Switching and merging $B...  git checkout $B  git merge --squash local/$B --no-commit
gitcommit -F $CMSG 
done

rm -f $CMSG



BTW, before pushing, I like to do something like this:

git push --dry-run 2>&1 |egrep -v "^To" | awk '{print $1}'|xargs git
log --format=fuller

just to get a list of exactly what I'm about to push :-) That doesn't
mean there won't
be mistake, but maybe fewer of them...

--
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/


Re: Multi-branch committing in git, revisited

From
Andrew Dunstan
Date:

On 09/22/2010 07:07 AM, Magnus Hagander wrote:
> On Wed, Sep 22, 2010 at 05:47, Tom Lane<tgl@sss.pgh.pa.us>  wrote:
>> Bruce Momjian<bruce@momjian.us>  writes:
>>> However, keep in mind that creating a branch in every existing backpatch
>>> branch is going to create even more backpatching monkey-work.
>> Monkey-work is scriptable though.  It'll all be worth it if git
>> cherry-pick is even marginally smarter about back-merging the actual
>> patches.  In principle it could be less easily confused than plain
>> old patch, but I was a bit discouraged by the upthread comment that
>> it's just a shorthand for "git diff | patch" :-(
> FWIW, here's the workflow I just tried for the gitignore patch (blame
> me and not the workflow if I broke the patch, btw :P)
>
>
>
> * Have a master "committers" repo, with all active branches checked out
>    (and a simple script that updates and can reset them all automatically)
> * Have a working repo, where I do my changes. Each branch gets a checkout
>    when necessary here, and this is where I apply it. I've just used
> inline checkouts,
>    but I don't see why it shouldn't work with workdirs etc.
> * In the working repo, apply patch to master branch.
> * Then use git cherry-pick to get it into the back branches (still in
> the working repo)
>    At this point, also do the testing of the backpatch.
>
> At this point we have commits with potentially lots of time in between them.
> So now we squash these onto the committers repository, using a small script that
> does this:
>
>
> #!/bin/sh
>
> set -e
>
> CMSG=/tmp/commitmsg.$$
>
> editor $CMSG
>
> if [ ! -f $CMSG ]; then
>     echo No commit message, aborting.
>     exit 0
> fi
>
> export BRANCHES="master REL9_0_STABLE REL8_4_STABLE REL8_3_STABLE
> REL8_2_STABLE REL8_1_STABLE REL8_0_STABLE REL7_4_STABLE"
>
> echo Fetching local changes so they are available to merge
> git fetch local
>
> for B in ${BRANCHES} ; do
>     echo Switching and merging $B...
>     git checkout $B
>     git merge --squash local/$B --no-commit
>     git commit -F $CMSG
> done
>
> rm -f $CMSG
>
>
>
> BTW, before pushing, I like to do something like this:
>
> git push --dry-run 2>&1 |egrep -v "^To" | awk '{print $1}'|xargs git
> log --format=fuller
>
> just to get a list of exactly what I'm about to push :-) That doesn't
> mean there won't
> be mistake, but maybe fewer of them...


What a rigmarole! This seems to be getting positively gothic.

cheers

andrew


Re: Multi-branch committing in git, revisited

From
Magnus Hagander
Date:
On Wed, Sep 22, 2010 at 13:47, Andrew Dunstan <andrew@dunslane.net> wrote:
>
>
> On 09/22/2010 07:07 AM, Magnus Hagander wrote:
>>
>> On Wed, Sep 22, 2010 at 05:47, Tom Lane<tgl@sss.pgh.pa.us>  wrote:
>>>
>>> Bruce Momjian<bruce@momjian.us>  writes:
>>>>
>>>> However, keep in mind that creating a branch in every existing backpatch
>>>> branch is going to create even more backpatching monkey-work.
>>>
>>> Monkey-work is scriptable though.  It'll all be worth it if git
>>> cherry-pick is even marginally smarter about back-merging the actual
>>> patches.  In principle it could be less easily confused than plain
>>> old patch, but I was a bit discouraged by the upthread comment that
>>> it's just a shorthand for "git diff | patch" :-(
>>
>> FWIW, here's the workflow I just tried for the gitignore patch (blame
>> me and not the workflow if I broke the patch, btw :P)
>>
>>
>>
>> * Have a master "committers" repo, with all active branches checked out
>>   (and a simple script that updates and can reset them all automatically)
>> * Have a working repo, where I do my changes. Each branch gets a checkout
>>   when necessary here, and this is where I apply it. I've just used
>> inline checkouts,
>>   but I don't see why it shouldn't work with workdirs etc.
>> * In the working repo, apply patch to master branch.
>> * Then use git cherry-pick to get it into the back branches (still in
>> the working repo)
>>   At this point, also do the testing of the backpatch.
>>
>> At this point we have commits with potentially lots of time in between
>> them.
>> So now we squash these onto the committers repository, using a small
>> script that
>> does this:
>>
>>
>> #!/bin/sh
>>
>> set -e
>>
>> CMSG=/tmp/commitmsg.$$
>>
>> editor $CMSG
>>
>> if [ ! -f $CMSG ]; then
>>    echo No commit message, aborting.
>>    exit 0
>> fi
>>
>> export BRANCHES="master REL9_0_STABLE REL8_4_STABLE REL8_3_STABLE
>> REL8_2_STABLE REL8_1_STABLE REL8_0_STABLE REL7_4_STABLE"
>>
>> echo Fetching local changes so they are available to merge
>> git fetch local
>>
>> for B in ${BRANCHES} ; do
>>    echo Switching and merging $B...
>>    git checkout $B
>>    git merge --squash local/$B --no-commit
>>    git commit -F $CMSG
>> done
>>
>> rm -f $CMSG
>>
>>
>>
>> BTW, before pushing, I like to do something like this:
>>
>> git push --dry-run 2>&1 |egrep -v "^To" | awk '{print $1}'|xargs git
>> log --format=fuller
>>
>> just to get a list of exactly what I'm about to push :-) That doesn't
>> mean there won't
>> be mistake, but maybe fewer of them...
>
>
> What a rigmarole! This seems to be getting positively gothic.

FWIW, it's shorter and simpler than what I use for cvs ;) But maybe
that's because I'm being overly careful...

--
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/


Re: Multi-branch committing in git, revisited

From
Robert Haas
Date:
On Tue, Sep 21, 2010 at 9:20 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> So it seems like maybe we still need some more thought about how to
> recognize related commits in different branches.  Or at the very least,
> we need a best-practice document explaining how to manage this --- we
> shouldn't expect every committer to reinvent this wheel for himself.
>
> Comments?

I don't think there's one right way to do this.  In fact, there are
probably at least 50 reasonable ways to do it, depending on your own
workflow preferences.  And you needn't do it the same way every time,
either.  I don't.  git is designed to treat commits the way that
databases treat rows.  They are objects.  You can create them, throw
them out, move them around, replace them with updated versions, etc.
And there are multiple ways of doing each of these things (just as
there's no single right way to design a database schema).  Of course,
in the One True Source Tree, we only every create them at the heads of
existing branches.  But in your own workspace, you can do all of those
things - and you should, because they make you able to get the same
things done faster.

What I plan to do, I think, is use one clone nearly all the time.  If
I need to back-patch, I'll switch branches and either apply from the
stash or cherry-pick off the master.  But if I need to to go back more
than one or two branches and there are merge conflicts, I'll create a
bunch of temporary clones off my main clone and push/pull from there.
Then I'll remove them when I'm done.  But from what I gather, there
are probably going to be at least as many workflows as there are
committers, and maybe more, since I just said I'm going to use two
different approaches depending on the situation.

One option is just to update the date stamp on each commit before you
push.  You could check out each branch you've updated and do something
like:

GIT_EDITOR=/usr/bin/true git commit --amend --date=now

Of course that'll only update the top commit, and you want to be sure
not to do it on branches where the top commit is something that's
already been pushed.  But to reiterate my main point, I think we
should only dictate the contents of the commits that must be pushed
(e.g. time stamps close together, so git_topo_order can match them up)
and not the process by which someone creates those commits (because
the chances of getting more than 1 person to agree on the way to
generate such commits seems near zero, and the fact that I plan to do
it different ways depending on the situation means that even getting 1
person to agree with themselves on how to do it may be out of reach).

People have repeatedly suggested that timestamp/author/log message
matching is a lousy way of matching up commits.  I agree, but we have
14.25 years of history for which that's the only practical method.  We
could decide on a different method going forward, such as embedding a
token (the format of which we can argue about until we're blue in the
face - could be whatever git cherry-pick does or could be a reference
to our issue tracking system if we had one, could be something else)
in each commit in a very specific format which a script can then
recognize.  The advantage of that is that it might feel a bit less ad
hoc than what we're doing now; the disadvantage is that then our
scripts would have to know about both methods, unless of course we go
back and annotate all of the old commits (using git-notes) with
reconstructed information on which commits go together, which we
already have from git_topo_order.  No matter what we pick, it's going
to require non-zero effort to not screw it up; and with the exception
of doing forward merges which I think is a terrible idea, none of the
methods so far proposed seem likely to take significantly more time
than any of the others.  So if we're going to change anything at all,
we ought to focus on how it's going to improve the overall way that we
manage the project, not on the exact sequence of commands that will be
required to create it, which I'm fairly confident will settle down to
a quite small number as you and everyone else get used to the new tool
(but it won't be the same sequence for everyone).

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise Postgres Company


Re: Multi-branch committing in git, revisited

From
Bruce Momjian
Date:
Tom Lane wrote:
> Okay, so now that I've actually done a couple of multi-branch commits...
> 
> I'm using the multiple-work-directory arrangement suggested on our wiki
> page.  The work flow seems to boil down to:
> 
> * Prepare patch in master
> * Stage patch with git add
> * git diff --staged >/tmp/patch-head
> * cd into REL9_0_STABLE workdir
> * patch -p0 </tmp/patch-head
> * Adjust patch if needed
> * Stage patch with git add
> * git diff --staged >/tmp/patch-90
> * cd into REL8_4_STABLE workdir
> * patch -p0 </tmp/patch-90
> * ... lather, rinse, repeat ...
> * cd back to master
> * git commit -F /tmp/commitmsg
> * cd into REL9_0_STABLE workdir
> * git commit -F /tmp/commitmsg
> * cd into REL8_4_STABLE workdir
> * git commit -F /tmp/commitmsg
> * ... lather, rinse, repeat ...
> * git push

Uh, just to be clear, the above is more complex than necessary because
git diff will show all uncommitted modifications.  You could just do:
> * Prepare patch in master> * git diff >/tmp/patch-head> * cd into REL9_0_STABLE workdir> * patch -p0
</tmp/patch-head>* Adjust patch if needed...
 

There is no need for 'git add' because once you are done you can use git
commmit -a in each branch to add all modifications and commit them.  I
think this exactly matches how we did thing with CVS.  A final 'git
push' sends them to the remote repository.  This causes commits to all
happen around the same time.

I am not saying that is the way we should to it, but it is clearly
possible.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +


Re: Multi-branch committing in git, revisited

From
Tom Lane
Date:
Bruce Momjian <bruce@momjian.us> writes:
> There is no need for 'git add' because once you are done you can use git
> commmit -a in each branch to add all modifications and commit them.

git commit -a is not a universal solution.  In particular, the patch
I was dealing with yesterday involved additions and removals of files,
neither of which will be implemented by git commit -a.
        regards, tom lane


Re: Multi-branch committing in git, revisited

From
Bruce Momjian
Date:
Tom Lane wrote:
> Bruce Momjian <bruce@momjian.us> writes:
> > There is no need for 'git add' because once you are done you can use git
> > commmit -a in each branch to add all modifications and commit them.
> 
> git commit -a is not a universal solution.  In particular, the patch
> I was dealing with yesterday involved additions and removals of files,
> neither of which will be implemented by git commit -a.

Uh, why is that?  I see -a saying:
      -a, --all          Tell the command to automatically stage files that          have been modified and deleted,
butnew files you have          not told git about are not affected.
 

What is it about add/deletes that it doesn't do?  Is the problem 'git
add' creates a stage already?  How is that a problem?

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +


Re: Multi-branch committing in git, revisited

From
Robert Haas
Date:
On Wed, Sep 22, 2010 at 12:40 PM, Bruce Momjian <bruce@momjian.us> wrote:
> Tom Lane wrote:
>> Bruce Momjian <bruce@momjian.us> writes:
>> > There is no need for 'git add' because once you are done you can use git
>> > commmit -a in each branch to add all modifications and commit them.
>>
>> git commit -a is not a universal solution.  In particular, the patch
>> I was dealing with yesterday involved additions and removals of files,
>> neither of which will be implemented by git commit -a.
>
> Uh, why is that?  I see -a saying:
>
>       -a, --all
>           Tell the command to automatically stage files that
>           have been modified and deleted, but new files you have
>           not told git about are not affected.
>
> What is it about add/deletes that it doesn't do?  Is the problem 'git
> add' creates a stage already?  How is that a problem?

Tom is slightly incorrect.  Deletions work fine with git commit -a.
git already knows about the files, so everything just works.  However,
it won't pick up on added files, because it can't distinguish between
a file that you want added to the repository and a stray file you left
lying around and assumes the latter.  But I don't see that this takes
anything away from your point.  You can certainly just work on the
patch in each repository separately and then commit everything all at
once at the end, if you're so inclined.  Of course, as Tom points out,
it's a lot nicer to apply patches in a way that allows git to try to
auto-merge for you.  Sometimes it works, and when it doesn't work
having the merge conflict stuff in the file is still better than
having a .rej hunk leftover that you have to figure out what to do
with.  So personally I don't intend to do it that way, but as Larry
Wall said about Perl, There's More Than One Way To Do It.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise Postgres Company


Re: Multi-branch committing in git, revisited

From
Bruce Momjian
Date:
Robert Haas wrote:
> > What is it about add/deletes that it doesn't do? ?Is the problem 'git
> > add' creates a stage already? ?How is that a problem?
> 
> Tom is slightly incorrect.  Deletions work fine with git commit -a.
> git already knows about the files, so everything just works.  However,
> it won't pick up on added files, because it can't distinguish between
> a file that you want added to the repository and a stray file you left
> lying around and assumes the latter.  But I don't see that this takes
> anything away from your point.  You can certainly just work on the

OK, so I just somehow made a valid git suggestion.  I think I need to
lay down.  :-O

> patch in each repository separately and then commit everything all at
> once at the end, if you're so inclined.  Of course, as Tom points out,
> it's a lot nicer to apply patches in a way that allows git to try to
> auto-merge for you.  Sometimes it works, and when it doesn't work
> having the merge conflict stuff in the file is still better than
> having a .rej hunk leftover that you have to figure out what to do
> with.  So personally I don't intend to do it that way, but as Larry
> Wall said about Perl, There's More Than One Way To Do It.

My back-patches are usually super-simple (everyone laughs) so my patch
files are trival to apply.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +