RE: git pull on Linux/ACPI release tree

5 messages, 4 authors, 2006-01-09 · open the first message on its own page

RE: git pull on Linux/ACPI release tree

From: Brown, Len <hidden>
Date: 2006-01-08 07:47:42

Hi Linus,

adding git-u79uwXL29TaiAVqoAR/hOK1cXZ9k6wlg@public.gmane.org
quoted
please pull this batch of trivial patches from: 
git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git release

Len,

I _really_ wish you wouldn't have those automatic merges.

Why do you do them? They add nothing but ugly and unnecessary 
history, and in this pull, I think almost exactly half of the
commits were just these empty merges.
Is it possible for it git, like bk, to simply ignore merge commits in its summary output?

Note that "Auto-update from upstream" is just the place-holder comment
embedded in the wrapper script in git/Documentation/howto/using-topic-branches.txt
All instances of it here are from me manually updating --
the only "auto" happening here is the automatic insertion of that comment:-)

I think that Tony's howto above captures two key requirements
from all kernel maintainers -- which the exception of you --
who hang out  in the middle of the process rather than
at the top of the tree.

1. It is important that we be able (and encouraged, not discouraged)
to track the top of tree as closely as we have time to handle.
Divergence and conflicts are best handled as soon as they are noticed
and can be a huge pain if left to fester and discovered
only when it is time to push patches upstream.
Plus, tracking the top of tree means we force more folks to
track the top of tree, and so it gets more testing.  This is goodness.

Earlier in your release cycle when changes are appearing faster,
my need/desire to sync is greater than later in the cycle when changes
are smaller and infrequent.  On average, I think that one sync/day
from upstream is an entirely reasonable frequency.

2. It is also important that we be able to cherry pick individual patches
in our trees so that they don't block each other from going upstream.
Tony's using-topic-branches.txt above is the best way I know of doing that.
I think it is a big improvement over the bk model since I can have a simple
branch for each patch or group of patches rather than an entire repository
dedicatd to each.  But for this to work, I need to be able to update
any and all of the topic branches from upstream, and to merge them with
each other -- just like I could with BK.  Otherwise they become "dated"
in the time they were first integrated, and it is not convenient to do
simple apples/apples comparisons that are needed to debug and test.

I'm probably a naïve git user -- but I expect I have a lot of company.
If there is a better way of using the tool to get the job done,
I'm certainly a willing customer with open ears.

thanks,
-Len
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Re: git pull on Linux/ACPI release tree

From: "David S. Miller" <davem@davemloft.net>
Date: 2006-01-08 08:17:00

From: "Brown, Len" <redacted>
Date: Sun, 8 Jan 2006 02:47:30 -0500
I'm probably a naïve git user -- but I expect I have a lot of company.
If there is a better way of using the tool to get the job done,
I'm certainly a willing customer with open ears.
What I do is simply build a new fresh tree if I feel the urge
to sync with the top of Linus's tree.  I use the script below
which I call "git suck".  It just sucks the patches out of
one tree and sticks them into another tree.  You go:

bash$ cd new-2.6
bash$ git suck ../foo-2.6

It preserves everything except the dates, and it's so incredibly
cheap and fast with GIT.

I know a lot of people react to this kind of usage with "what's the
point of the source control system if you're just messing with patches
in and out of the tree all the time" But as a subsystem maintainer,
you deal with a lot of changes and it's important to get a pristine
clean history when you push things to Linus.

In fact, I do this so much that Linus's tree HEAD often equals my
origin when he pulls.

Merges really suck and I also hate it when the tree gets cluttered
up with them, and Linus is right, ACPI is the worst offender here.

Yes, we can grep the merges out of the shortlog or whatever, but that
merging crap is still physically in the tree.

Just don't do it.  Merge into a private branch for testing if you
don't want to rebuild trees like I do, but push the clean tree to
Linus.

#!/bin/sh
#
# Usage: git suck path-to-tree
#
# Pull all patches relative to 'origin' from the tree specified
# and apply them to the current directory tree, keeping all changelog
# and authorship information identical.  It will update the dates
# of the changes of course.
(cd $1; git format-patch --mbox origin) || exit 1
for i in $1/*.txt
do
   sed 's/\[PATCH\] //' <$i >tmp.patch
   git-applymbox -k tmp.patch || exit 1
done

RE: git pull on Linux/ACPI release tree

From: Linus Torvalds <torvalds@osdl.org>
Date: 2006-01-08 19:10:25


On Sun, 8 Jan 2006, Brown, Len wrote:
Is it possible for it git, like bk, to simply ignore merge commits in its summary output?
That's not the point. It does: "git log --no-merges" does exactly that.

But fire up "gitk" to watch the history, and see the difference.
Note that "Auto-update from upstream" is just the place-holder comment
embedded in the wrapper script in git/Documentation/howto/using-topic-branches.txt
That has absolutely nothing to do with anything. It's not the comment 
(which admittedly gives absolutely no information - but why should it, 
since the _commit_ itself has no information in it?)

It's like you have empty commits that don't do anything at all, except 
that they are worse, because they have two parents.
I think that Tony's howto above captures two key requirements
from all kernel maintainers -- which the exception of you --
No. Your commits make it harder for _everybody_ to track the history. 

A merge by definition "couples" the history of two branches. That's what a 
merge very fundamentally is. It ties two things together. But two things 
that don't have any connection to each other _shouldn't_ be tied together.

Just as an example: because of the extra merges, you've made all your 
commits dependent on what happened in my tree, with no real reason. So 
let's say that somebody reports that something broke in ACPI. Now you 
can't just go to the top of the ACPI history and work backwards - you'll 
have tied up the two histories so that they are intertwined.

And yes, you can always work around it, but there's just no point. And 
none of the other developers seem to need to do it. They do their 
development, and then they say "please pull". At that point the two 
histories are tied together, but now they are tied together for a 
_reason_. It was an intentional synchronization point.

An "automated pull" by definition has no reason. If it works automated, 
then the merge has zero semantic meaning. 

			Linus
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Re: git pull on Linux/ACPI release tree

From: Al Viro <hidden>
Date: 2006-01-09 00:49:12

On Sun, Jan 08, 2006 at 11:10:20AM -0800, Linus Torvalds wrote:
That has absolutely nothing to do with anything. It's not the comment 
(which admittedly gives absolutely no information - but why should it, 
since the _commit_ itself has no information in it?)
How do you deal with conflict resolution?  That's a genuine question -
I'm not talking about deliberate misuse to hide an attack, just a normal
situation when you have to resolve something like

A:
	if (foo)
		bar

B:
	if (foo & baz)
		bar

A':
#ifdef X
	if (foo)
		bar
	...
#endif

merge of A' and B: trivial conflict

and have git pull fail.  The obvious way (edit file in question, update-index,
commit) will not only leave zero information about said conflict and actions
needed to deal with it, but will lead to situation when git whatchanged will
not show anything useful.   I.e. if conflict turns out to be non-trivial and
ends up being resolved wrong, everyone will have very nasty time trying to
figure out where the breakage had come from when looking at history 6 months
down the road.

Is there any SOP I'm missing here?

Worse (for my use), format-patch on such tree will not give a useful patchset.
You get a series of patches that won't apply to _any_ tree.  Even if all
conflicts had been resolved correctly, they still remain there for everyone
trying to apply the patch series, unless you manually rebase it before
format-patch.

And that's a fundamental problem behind all that rebase activity, AFAICS.
It definitely is in my case, and yes, it's fscking inconvenient in a lot
of respects.  E.g. I'm using git for resync between build trees on several
boxen.  There's a repository holding patchset, plus one clone per build
box.  Fixes for build breakage, etc., get done in those clones; after they
are committed there, I pull into master and then pull from other clones
to spread them to other build trees.  Works fine, but...  Any rebase in
master => instant hell for all clones.  I've ended up with the following
layout that kinda-sorta avoids mess:
master:origin: matches upstream
master:topic branch: _not_ rebased until there is a conflict, never get
	a pull from anywhere
master:master: gets pulls from topic branches and origin _and_ _nothing_ _else_
master:work: where interaction with build boxen and any edits done in master
	repository go.  Edits, commits, pulls from master:master, pulls from
	build boxen.
buildN:origin == master:work
buildN:work: where work on buildN goes.
When I want to get new stuff (== difference between master:master and
master:work) into the patchset, I cherry-pick from work to topic branches
and re-pull them into master:master until it matches master:work.  Then
I pull master:master into master:work to create a point in work history
that marks beginning of new portion of pending stuff.  New stuff upstream
is pulled to master:origin -> master:master -> master:work -> build trees.

That works, and gives me merge-free topic branches I can safely format-patch
while keeping master in sync with mainline _and_ also safe for format-patch.
The price is in rather convoluted SOP.  And the following piece of fun:
when cherry-pick work->topic, pull topic->master or pull origin->master
gives a conflict, it's time to rebase.  Which I do by renaming topic branches
(direct mv in .git/refs/heads), then starting new ones at current origin
and applying old ones to them (cherry + cherry-pick if possible, format-patch
+ applymbox if things get hairy).  Then master is recreated as branch from
origin that gets pulls from topic branches, work is branched from it and
build trees get killed and cloned from scratch.  It's tolerable since I'm
using ccache on build boxen, so it's _not_ that much of rebuild.

However, that clearly is a killer if any poor sucker (me included) ever
clones from master for any other purpose.  And that, BTW, is the main
reason that stops me from moving master to kernel.org right now.
And yes, you can always work around it, but there's just no point. And 
none of the other developers seem to need to do it. They do their 
development, and then they say "please pull". At that point the two 
histories are tied together, but now they are tied together for a 
_reason_. It was an intentional synchronization point.

An "automated pull" by definition has no reason. If it works automated, 
then the merge has zero semantic meaning. 
I'm afraid you are missing a part of picture.  There is a bunch of git
uses that handle a heap of foam rather than a long-term branching.  I.e.
the tree is tied to mainline closely and most of the stuff in it is
supposed to get flushed into mainline soon after it appears.  I.e. the
situation when we have a mergepoint for fixes that _has_ to follow
mainline closely.

I wonder what life would be without merge nodes and with equality nodes
instead.  I.e. to merge
O -> A1 -> ..... -> An (=A)
  -> B1 -> ..... -> Bm (=B)
would be to create a new branch (C) at Bm, have entire A1...An replayed there,
have B1...Bm replayed in A and then create a node certifying that new head
of A and head of C refer to the same tree.  Plus have a way to see which
commits are claimed to be replays of each other.  At least that way rebase
would be simply saying that old history is superceded by new one, with
equality node proving that it's OK to do.  We would have
O -> M1 -> ....  ->Mn for mainline
O -> B1 -> ....  -> B for branch post-pull
Mn -> P1 -> ... -> P for merge branch
and B == P as equality node.   Old branch would have a bunch of changesets
of its own plus ones from mainline that got there by pulls (including the
last one).  And new branch would contain the ports of not-yet-merged ones
to new mainline head, with the same tree as the result and all further
development going on there rather than in the old branch.  Oh, well...

Re: git pull on Linux/ACPI release tree

From: Linus Torvalds <torvalds@osdl.org>
Date: 2006-01-09 03:52:45


On Mon, 9 Jan 2006, Al Viro wrote:
How do you deal with conflict resolution?  That's a genuine question -
I'm not talking about deliberate misuse to hide an attack, just a normal
situation when you have to resolve something like

A:
	if (foo)
		bar

B:
	if (foo & baz)
		bar

A':
#ifdef X
	if (foo)
		bar
	...
#endif

merge of A' and B: trivial conflict
Actually, these days git is pretty good at it. Much better than CVS, 
certainly. You can see the "conflict against my old tree", or "conflict 
against the remote tree" by using the "--ours" or "--theirs" flag to "git 
diff" respectively.

(Or "diff conflict against common base": "git diff --base").

So for your particular example with a trivial base file:

	line    1
	        2
	        3
	        if (foo)
	                bar
	        6
	        7
	        8

and then the changes you had as an example in the A' and B branches, if I 
from A' do a "git pull . B", I get:

	Trying really trivial in-index merge...
	fatal: Merge requires file-level merging
	Nope.
	Merging HEAD with ad56343c578785b8d932224a8676615e7a3e191f
	Merging: 
	9d619225e3adecee6432a36d67d140e29b0acf62 A' case 
	ad56343c578785b8d932224a8676615e7a3e191f B: case 
	found 1 common ancestor(s): 
	93765ba3f64e9c73438e52683fffa68e5a493df7 Base commit 
	Auto-merging A 
	CONFLICT (content): Merge conflict in A 

	Automatic merge failed; fix up by hand

and then the file contains the contents

	line    1
	        2
	        3
	<<<<<<< HEAD/A
	#ifdef X
	        if (foo)
	=======
	        if (foo && baz)
	>>>>>>> ad56343c578785b8d932224a8676615e7a3e191f/A
	                bar
	        6
	#endif
	        7
	        8

ie it will have does a CVS-like merge for me, and I need to fix this up. 
However, to _help_ me fix it up, I can now see what the diff is aganst my 
original version (A'), with "git diff --ours" (the "--ours" is default, so 
it's unnecessary, but just to make it explicit):

	* Unmerged path A
	diff --git a/A b/A
	index 06dd3bc..7334364 100644
	--- a/A
	+++ b/A
	@@ -1,8 +1,12 @@
	 line   1
	        2
	        3
	+<<<<<<< HEAD/A
	 #ifdef X
	        if (foo)
	+=======
	+       if (foo && baz)
	+>>>>>>> ad56343c578785b8d932224a8676615e7a3e191f/A
	                bar
	        6
	 #endif

which is very helpful especially once I have resolved it. IOW, I just edit 
the file and do the trivial resolve, and now I can do a "git diff" again 
to make sure that it looks ok:

	* Unmerged path A
	diff --git a/A b/A
	index 06dd3bc..924fc97 100644
	--- a/A
	+++ b/A
	@@ -2,7 +2,7 @@ line    1
	        2
	        3
	 #ifdef X
	-       if (foo)
	+       if (foo && baz)
	                bar
	        6
	 #endif

ahh, looks good, so I just do "git commit A" and that creates the 
resolved merge.
 The obvious way (edit file in question, update-index, commit) will not 
only leave zero information about said conflict and actions needed to 
deal with it, but will lead to situation when git whatchanged will not 
show anything useful.
Now, this is a real issue. 

The resolve part is pretty easy, but the fact that it's hard to see in 
"git-whatchanged" is a limitation of git-whatchanged. 

You need to use "gitk", which _does_ know how to show merges as a diff 
(and yes, I just checked).
Is there any SOP I'm missing here?
You're just missing the fact that git-whatchanged (or rather, 
"git-diff-tree") isn't smart enough to show merges nicely. It really 
_should_. It doesn't. You can choose to show merges with the "-m" flag, 
but that will show diffs against each parent, which really isn't what you 
want. 

I should do the same thing gitk does in git-diff-tree.
Worse (for my use), format-patch on such tree will not give a useful patchset.
You get a series of patches that won't apply to _any_ tree. 
Now, git-diff-tree _does_ do that. Use the "-m" flag, and choose the tree 
you want.

And btw, that works with "git-whatchanged" too. You _can_ pass the "-m" 
flag to git-whatchanged, and it will show you each side of the merge 
correctly. So it _works_. It's just such a horrible format that by default 
it prefers to shut up about merges entirely. 

(I don't know of a good three-way diff format. "gitk" can do it, because 
gitk can show colors. That's a big deal when you do three-way - or 
more-way - diffs).
And that's a fundamental problem behind all that rebase activity, AFAICS.
You do _not_ want to rebase a merge. It not only won't work, it's against 
the whole point of rebasing.

Rebasing is really only a valid operation when you have a few patches OF 
YOUR OWN that you want to move up to a new version of somebody elses tree 
that you are tracking. You fundamentally _cannot_ rebase if you've done 
anything but a linear set of patches. And that has nothing to do with the 
patch difficulty - it simply isn't an operation that makes sense.

(Btw, not making sense doesn't mean it might not work. It sometimes might 
actually work and do what you _hoped_ it would do, but it's basically by 
pure luck, and not because it is a sensible operation. Even stupid 
people hit on the right solution every once in a while - not because 
they thought about things right, but just because they happened to try 
something that worked. The same is true of "git rebase" with merges ;^).

The fundamental reason a rebase doesn't make sense is that if you've done 
a merge, it obviously means that some other branch has done development, 
and already has the commits that you're trying to rebase. And you CANNOT 
rebase for them.

So instead of rebasing across a merge, what you can do is to not do the 
merge at all, but instead rebase one of the two branches against the 
other. Then you can rebase the result against the thing that you wanted to 
rebase them both against. Now you've never rebased a merge - you've just
linearised branches that were linear in themselves against each other.

Basically, a merge ties two branches together. Once you've merged, you 
can't make a linear history any more. The merge fundamentally is not 
linear.

		Linus
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help