Git development
 help / color / mirror / Atom feed
* Re: unmerging feature branches
From: martin f krafft @ 2007-10-23 18:08 UTC (permalink / raw)
  To: Linus Torvalds, git discussion list
In-Reply-To: <alpine.LFD.0.999.0710231026011.30120@woody.linux-foundation.org>

[-- Attachment #1: Type: text/plain, Size: 4097 bytes --]

also sprach Linus Torvalds <torvalds@linux-foundation.org> [2007.10.23.1940 +0200]:
> > > So you can revert the data, but then if you want to get it back, you'll 
> > > need to revert the revert - you cannot just merge the branch again. 
> > 
> > Ouch!
> 
> Well, it's not necessarily "Ouch".

I said "ouch" only because I can foresee the confusion this may
cause in collaborative package maintenance. One party merges the
feature branch, another reverts it, and a third (or the first)
wonders why the feature isn't present despite having merged the
branch and must go through history to find the reverting commit,
which is tied to the commit it reverts through nothing else than
a log message, at best.

> In other words, think of what happens when you merge some
> development branch, and then "git revert" a single commit from
> that branch - the exact same thing will happen - future merges of
> that branch will *not* re-do the commit, because you "already have
> it", and you reverted it after-the-fact.
[...]
> When you revert the data from a merge, the exact same issue
> happens. A revert (whether done by "git revert", or by the
> sequence of events I described) very fundamentally undoes the
> *data* part, but leaves the history intact, and that has
> implications for future events that think about history - which is
> mostly "git merge", but there are other thigns too.

While this makes perfect sense, I am a bit thrown off now wrt two
earlier posts by you (in another thread), where you said:

  In other words, git never looks at individual commits when trying
  to merge. It doesn't try to figure out what the "meaning" of the
  changes are, it purely looks at the content.
    -- http://marc.info/?l=git&m=119198488411957&w=2

  Yes, history is interesting for historical reasons, and to explain
  what the context was, but in many ways, history is exactly the
  *wrong* thing to use when it comes to merging. You should look at
  the end result, since people can - and do - come to the same
  result through different ways.
    -- http://marc.info/?l=git&m=119204501428555&w=2

I master merged branch Foo, then reverted a commit introduced by
Foo, and then Foo would be re-merged, the content *will* differ. So
Git *has to* look at the list of commits in history to properly
handle reverts and *not* redo commits which have since been
reverted.

Is this correct?

> As an example of "other things" that take history into account, think 
> about something like "git rebase". It's not a merge, but it also takes 
> history into account in certain ways: in particular, it may be effectively 
> a "series of cherry-picks", but it actually takes the history of both 
> branches into account, and will not re-apply a patch that already exists 
> in the target history.

In the light of the discussion in
(http://marc.info/?t=119198137100002&r=1&w=2), I am now completely
confused. Or well, not confused, but I simply don't know anymore
what Git does, and I thought I did.

> What does that mean? Let's say that both histories contain a patch X (not 
> the same commit, but the same patch), but one history also contains the 
> revert of X. Again, the revert reverts the data, but it does *not* revert 
> the history, so when you cherry-pick all the stuff from the other branch, 
> X will *not* happen - even if it would apply cleanly, and even if a plain 
> "git cherry-pick" would have redone it!
> 
> Why? History, again. Because "git rebase" sees that the commit already 
> existed, it won't even try to apply it again, never mind that it could 
> have worked. The "revert" didn't undo the history, just the data.

How can rebase know that the commit already existed when you're
saying above that it's about patch X, *not* the same commit?

-- 
martin | http://madduck.net/ | http://two.sentenc.es/
 
"a woman begins by resisting a man's advances and ends by blocking
 his retreat."
                                                        -- oscar wilde
 
spamtraps: madduck.bogus@madduck.net

[-- Attachment #2: Digital signature (see http://martin-krafft.net/gpg/) --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: git-annotate - leaking hundrets of megabytes
From: Linus Torvalds @ 2007-10-23 18:14 UTC (permalink / raw)
  To: Sven Herzberg; +Cc: git
In-Reply-To: <471E28B2.7020508@imendio.com>



On Tue, 23 Oct 2007, Sven Herzberg wrote:
> 
> In my example, it used up to 450MB:
> http://people.imendio.com/~sven/massif.18740.png
> 
> Reproduce:
> 1. git clone git://git.webkit.org/WebKit.git
> 2. cd WebKit/WebCore
> 3. git-annotate --incremental ChangeLog

Hmm. I'm not seeing this at all. I do

	/usr/bin/time git-annotate --incremental ChangeLog > /dev/null

in WebCore, and it returns

	0.16user 0.01system 0:00.18elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
	0inputs+0outputs (0major+8365minor)pagefaults 0swaps

where that minor pagefault count is a good estimate of total memory used. 
8365 minor page faults implies it only ever got 32MB of memory total.

What git version do you have, or did you perhaps mean some other file or 
other config that causes this?

(It does end up using lots more memory if you ask for "-C" to see if there 
are copies from other sources, but even then I'm not seeing anything 
close to 450MB!)

			Linus

^ permalink raw reply

* Re: unmerging feature branches
From: Linus Torvalds @ 2007-10-23 18:24 UTC (permalink / raw)
  To: martin f krafft; +Cc: git discussion list
In-Reply-To: <20071023180825.GA20343@piper.oerlikon.madduck.net>



On Tue, 23 Oct 2007, martin f krafft wrote:
> 
> While this makes perfect sense, I am a bit thrown off now wrt two
> earlier posts by you (in another thread), where you said:
> 
>   In other words, git never looks at individual commits when trying
>   to merge. It doesn't try to figure out what the "meaning" of the
>   changes are, it purely looks at the content.
>     -- http://marc.info/?l=git&m=119198488411957&w=2

This is still true.

Git never looks at individual commits when merging, it looks at the 
*history*.

So it does look at the commits only in the sense that it uses the "shape" 
of the history (which is obviously built up from many individual commits!) 
but it never looks at any individual commit per se.

And the behaviour of "git revert" comes *exactly* from the fact that git 
never even bothers to look at the revert as a "revert" of history! A 
revert is a normal data commit, and has absolutely zero impact on history 
itself. So the reason a merge will never give "back" the data over a 
revert is that the data was already merged, since the history itself 
didn't change!

> I master merged branch Foo, then reverted a commit introduced by
> Foo, and then Foo would be re-merged, the content *will* differ.

No. If you re-merge Foo, nothing at all happens! You're already merged. 
It's a no-op.

If Foo has had *new* commits in the meantime, those new commits will show 
up, of course, but the old commits have absolutely zero effect, because 
they will be part of the common history.

> So Git *has to* look at the list of commits in history to properly 
> handle reverts and *not* redo commits which have since been reverted.
> 
> Is this correct?

No, that's absolutely incorrect. You didn't understand what I meant.

Git merge doesn't look at the revert at all, except (indorectly) when it 
builds up the history and it passes over it in order to find the common 
base for the history.

> > As an example of "other things" that take history into account, think 
> > about something like "git rebase". It's not a merge, but it also takes 
> > history into account in certain ways: in particular, it may be effectively 
> > a "series of cherry-picks", but it actually takes the history of both 
> > branches into account, and will not re-apply a patch that already exists 
> > in the target history.
> 
> In the light of the discussion in
> (http://marc.info/?t=119198137100002&r=1&w=2), I am now completely
> confused. Or well, not confused, but I simply don't know anymore
> what Git does, and I thought I did.

git-rebase is special. It really does look at each commit (obviously), 
since it needs to *move* each commit. 

So git-rebase has nothing at all to do with merges. They have similar 
behaviour (quite often the end result is identical in the *data* - at 
least that's the good case), but at the same time they are very different 
indeed. 

Git-merge *only* cares about the "shape of the history" (to find the 
common commit(s) to use as a merge base) and the actual data, while "git 
rebase" actually goes one commit at a time.

> How can rebase know that the commit already existed when you're
> saying above that it's about patch X, *not* the same commit?

Git-rebase looks at the patch itself, using the "patch fingerprint", and 
when it goes through each commit, it skips commits that have already been 
applied. 

See the man-pages for "git-cherry" and "git-patch-id".

		Linus

^ permalink raw reply

* Re: Howto request: going home in the middle of something?
From: Jan Wielemaker @ 2007-10-23 18:38 UTC (permalink / raw)
  To: Jing Xue; +Cc: Petr Baudis, git
In-Reply-To: <20071023135655.x6g6mln1j4880wog@intranet.digizenstudio.com>

On Tuesday 23 October 2007 19:56:55 Jing Xue wrote:
> Quoting Jan Wielemaker <wielemak@science.uva.nl>:
> > Thanks for the replies.	 I think I can live with something like this
> >
> > 	<work, in the middle of something>
> > 	$ git checkout -b home
> > 	$ git commit
> > 	$ git checkout master
> > 	<arriving at home>
> > 	$ git jan@work:repo fetch home:home	(using ssh)
> > 	$ git checkout home
> > 	<continue editing>
> > 	$ git commit --amend
> > 	$ git checkout master
> > 	$ git merge home
> > 	$ git -d home
> > 	$ git commit
> > 	$ git push
> > 	<arriving at work>
> > 	$ git -d home
> > 	$ git pull
> >
> > Its still a bit many commands and you have to be aware what you are
> > doing for quite a while, but it does provide one single clean commit
> > message, doesn't change the shared repo until all is finished and allows
> > to abandon all work without leaving traces.
>
> What does the extra branch gain for us here? That's not a rhetorical
> question, I'm actually curious to learn, because I always just commit,
> switch to another computer, pull, and reset HEAD^.

I'm just trying to learn. Sofar I like the idea to stash and use
git-fetch to get the stash from the other side. As stash is about
handling current work, it feels as the most appropriate solution
and is a lot shorter.

	Cheers --- Jan

^ permalink raw reply

* Re: git.el fails on non-git managed files
From: Matthieu Lemerre @ 2007-10-23 18:30 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: git
In-Reply-To: <20071023043107.GZ14735@spearce.org>

[-- Attachment #1: Type: text/plain, Size: 720 bytes --]

"Shawn O. Pearce" <spearce@spearce.org> writes:

> racin@free.fr wrote:
>> I found the following on the development version of git.el: saving
>> non-git-managed files in Emacs threw an error.
>> 
>> It is due to a simple error in the call to condition-case in a
>> recently added function, git-update-save-file.
>> 
>> I attached the patch for your convenience.
>
> I'm not sure what happened, but I didn't receive a patch with
> your email.  Would you mind resending it to the list?  You may
> also want to file a bug with your distribution to get the Emacs
> bindings included.

Sure; the SMTP server of my ISP behaved weirdly yesterday and I had to
use one of these webmail applications.  This time it should be OK.


[-- Attachment #2: patch --]
[-- Type: application/octet-stream, Size: 624 bytes --]

diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index 4286d16..ff55607 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1353,7 +1353,7 @@ Commands:
   "Update the corresponding git-status buffer when a file is saved.
 Meant to be used in `after-save-hook'."
   (let* ((file (expand-file-name buffer-file-name))
-         (dir (condition-case nil (git-get-top-dir (file-name-directory file))))
+         (dir (condition-case nil (git-get-top-dir (file-name-directory file)) (error nil)))
          (buffer (and dir (git-find-status-buffer dir))))
     (when buffer
       (with-current-buffer buffer

[-- Attachment #3: Type: text/plain, Size: 71 bytes --]


I'll also file a bug to debian, that's a good idea.

Matthieu Lemerre

^ permalink raw reply related

* Re: What's cooking in git/spearce.git (topics)
From: Junio C Hamano @ 2007-10-23 19:00 UTC (permalink / raw)
  To: Theodore Tso; +Cc: Shawn O. Pearce, Johannes Schindelin, git
In-Reply-To: <20071023120338.GG27132@thunk.org>

Theodore Tso <tytso@mit.edu> writes:

> With git.git, we are essentially throwing away development history
> while it is in 'pu', but once a commit graduates to 'next', we do keep
> the development history forever.  The downside to this is that
> development 'crud' can build up in next; even if all substantive
> commits in 'next' end up graduating to 'master', there will still be
> lots of merge commits that will only be in 'next'.   
>
> I have an emotional bias which tends to treat that excess history as
> toxic waste to be avoided at all costs, but that's probably because
> when you have a git tree as huge as the kernel, life is easier if the
> history is kept as clean as possible.  
>
> Which I suppose is easy enough to do in the git.git model; if you
> throw away the 'next' branch and then rewind it so it is forked off of
> 'master' all of that history essentially gets flushed.

You can view 'next' as if it is sort of -mm.  Following 'master'
is like following Linus tree, whose development is without those
numerous 'merge improvements again' merges into 'next'.

> The downside
> is that people maintaining topics branches which were forked against
> the old 'next' will need to do some grotty work to rebase their
> patches, so any attempt to rewind next would probably require the
> central maintainer to give plenty of notice, and then on the flag day,
> save 'next' as 'old-next' before rewinding to allow the other
> developers to more easily rebase any private branches they might have.

An alternative is to give an easier access to the tips of
individual topic branch head, at least to the ones that have
been merged to 'next' as they will never be rewound once they
are in 'next', and encourage people to fork off of them, instead
of 'next' directly.  Then 'next' will be more like 'pu'.

> Hmm, interesting.  A lot of this is quite subtle, or at least the
> impacts of different choices in the git workflow really didn't become
> obvious to me until I started trying I stepped into the central
> maintainer role for a project using git!

Very true.

^ permalink raw reply

* Re: unmerging feature branches
From: martin f krafft @ 2007-10-23 19:17 UTC (permalink / raw)
  To: Linus Torvalds, git discussion list
In-Reply-To: <alpine.LFD.0.999.0710231115060.30120@woody.linux-foundation.org>

[-- Attachment #1: Type: text/plain, Size: 2016 bytes --]

also sprach Linus Torvalds <torvalds@linux-foundation.org> [2007.10.23.2024 +0200]:
> So it does look at the commits only in the sense that it uses the "shape" 
> of the history (which is obviously built up from many individual commits!) 
> but it never looks at any individual commit per se.

I don't follow what you mean with "shape". The following is
a history:

 o - x - o - o - o - m - o - A* - o - m2 - o - master
      \             /                /
       `o - A - L -' - F - o - o - T' - branch

A is a commit, A* is the commit which reverts (the data change by)
A. L and F are to mark the last and first commits before and after
the first merge m. T is the tip of 'branch'

After merge point m2, the change introduced by A will *not* be in
master. This much makes sense.

What did not make sense is how Git determines to leave it out. But
I think that after drawing the above, it's now clear:

by shape you mean the actual graph, and when 'branch' is merged into
master at m2, Git goes back in time to conclude that master...L must
already be present in master due to the intersection of the two
lines at m, and thus finds commit F as the "oldest direct
descendant" of m2. L is an older descendant of m2, but it's not
direct in the sense that there are multiple paths from m2 to L. Thus
Git will only merge F..T at m2.

Or as you put it:

> If Foo has had *new* commits in the meantime, those new commits
> will show up, of course, but the old commits have absolutely zero
> effect, because they will be part of the common history.

I think I am (moderately) clear again on the inner working of Git.
Sorry for the confusion.

-- 
martin | http://madduck.net/ | http://two.sentenc.es/
 
"the search for the perfect martini is a fraud. the perfect martini
 is a belt of gin from the bottle; anything else is the decadent
 trappings of civilization."
                                                            -- t. k.
 
spamtraps: madduck.bogus@madduck.net

[-- Attachment #2: Digital signature (see http://martin-krafft.net/gpg/) --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: gitk patch collection pull request
From: Linus Torvalds @ 2007-10-23 19:17 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Shawn O. Pearce, git
In-Reply-To: <18205.15967.792413.775786@cargo.ozlabs.ibm.com>



On Tue, 23 Oct 2007, Paul Mackerras wrote:
> 
> OK, done.  The checkbox is in the Edit/Preferences window.  It's
> called "Limit diffs to listed paths" and it's on by default.

Ok, the diff looks fine, but now the "list of files" pane on the right is 
empty. 

Even when you limit the diff output, you often have lots of files. At 
least I do, because I often limit by subdirectory. So I'd still like to 
see the file list on the right, so that I can jump to a particular part of 
the diff.

(It would also be nice if it showed the *size* of the changes a'la 
diffstat or something, but that's another and independent issue).

		Linus

^ permalink raw reply

* Re: unmerging feature branches
From: Junio C Hamano @ 2007-10-23 19:33 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: martin f krafft, git discussion list
In-Reply-To: <alpine.LFD.0.999.0710230922240.30120@woody.linux-foundation.org>

Linus Torvalds <torvalds@linux-foundation.org> writes:

> Now, that said, reverting the data is not that hard. There is not any 
> single-command "revert this arm of a merge", but on the other hand, git 
> can certainly help you.
>
> The way to do it is:
>
> 	# go back to just before the merge, create a "fixup" branch
> 	#
> 	git branch -b fixup M^
>
> 	# merge all of it again, *except* the branch you didn't want to 
> 	# merge (this example assumes that you had a four-way octopus 
> 	# merge, and you now want to turn it into a three-way with the
> 	# next-to-last parent skipped):
> ...

Desire to revert an octopus would, as you demonstrated, often be
to revert only one arm, but I think allowing to revert a twohead
merge should be trivial.  If we define "reverting a merge" to
always revert all arms, then this should suffice.

diff --git a/builtin-revert.c b/builtin-revert.c
index a655c8e..719e293 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -269,8 +269,8 @@ static int revert_or_cherry_pick(int argc, const char **argv)
 
 	if (!commit->parents)
 		die ("Cannot %s a root commit", me);
-	if (commit->parents->next)
-		die ("Cannot %s a multi-parent commit.", me);
+	if (action != REVERT && commit->parents->next)
+		die ("Cannot %s a merge commit.", me);
 	if (!(message = commit->buffer))
 		die ("Cannot get commit message for %s",
 				sha1_to_hex(commit->object.sha1));

Note that allowing cherry-pick by removing the above two lines
allow replaying the data of a merge similar to a squash merge.

^ permalink raw reply related

* Re: unmerging feature branches
From: Linus Torvalds @ 2007-10-23 19:38 UTC (permalink / raw)
  To: martin f krafft; +Cc: git discussion list
In-Reply-To: <20071023191738.GA24575@piper.oerlikon.madduck.net>



On Tue, 23 Oct 2007, martin f krafft wrote:
> 
> I don't follow what you mean with "shape". The following is
> a history:
> 
>  o - x - o - o - o - m - o - A* - o - m2 - o - master
>       \             /                /
>        `o - A - L -' - F - o - o - T' - branch

Right. And you can do two things when merging:

 - the wrong and insane thing: look at the *contents* of each commit, to 
   decide if a commit does a certain thing.

 - the git thing: never look at individual commits at all, except to find 
   the global history, what I called the "shape".

So git obviously very much *does* look at history,  but it does so only to 
find the common point. So in when you create "m2", it looked at the 
history to see that the common point of the two branches was "L". And once 
it has found that, all the other stuff is totally irrelevant. It doesn't 
matter if there are a million commits between 'm' and 'm2', the only thing 
that mattered was the "topology" aka "shape" of the history.

See?

So git never actually cares about the individual commits A*, F, and T (or 
anything else) when it merges those two histories and created "m2".

It did *traverse* those commits, in order to find that "Oh, the last 
common state was 'L'", but it never looked at them in any other sense. 
They were all individually uninteresting, and the only sense in which they 
mattered at all was as the incidental building blocks of the history.

That's what I mean by the "shape" of the history: when merging git does 
walk the commits to see how it all holds together, but git doesn't then 
care in any way what the commits *do* apart from how they connected up 
the history of the two branches.

And once git has found the common commit, it then just merges purely based 
on the contents of the common commit and the two (or more, in the case of 
octopus merges) endpoints. So again, at that point it never looks at any 
of the individual commits, it only looks at what the *state* was.

(This is all a bit more complex when thers is more than one "common 
commit", but that's just a detail, and doesn't change the argument).

And git-rebase is obviously totally different: git-rebase also finds the 
common points, but uses that to just discard all the shared history that 
cannot matter, and then it walks all the *unshared* commits to match them 
up and see which ones already look like they exist (as another commit, but 
one that has the equivalent diff!), and which ones are worthy of trying to 
add.

> A is a commit, A* is the commit which reverts (the data change by)
> A. L and F are to mark the last and first commits before and after
> the first merge m. T is the tip of 'branch'
> 
> After merge point m2, the change introduced by A will *not* be in
> master. This much makes sense.

Yes.

> What did not make sense is how Git determines to leave it out. But
> I think that after drawing the above, it's now clear:
> 
> by shape you mean the actual graph, and when 'branch' is merged into
> master at m2, Git goes back in time to conclude that master...L must
> already be present in master due to the intersection of the two
> lines at m, and thus finds commit F as the "oldest direct
> descendant" of m2. L is an older descendant of m2, but it's not
> direct in the sense that there are multiple paths from m2 to L. Thus
> Git will only merge F..T at m2.

Exactly.

> Or as you put it:
> 
> > If Foo has had *new* commits in the meantime, those new commits
> > will show up, of course, but the old commits have absolutely zero
> > effect, because they will be part of the common history.
> 
> I think I am (moderately) clear again on the inner working of Git.
> Sorry for the confusion.

Hey, I think these things are good to clarify, maybe somebody else didn't 
quite understand it. And the more "graphical" and concrete some problem 
is, the more likely people are to "get it". 

What is interesting is how the actual rules that git follows are *really* 
simple. But they result in all this fairly complex, almost "emergent" 
behaviour. It's like the basic data structures: in many ways, git really 
only has those four basic object types, and you can really descibe 
everything git does in terms of those very simple core data structures: 
but a *repository* is certainly not something simple.

But the final "behaviour" really all comes from the interactions of 
things. The rules are all really really simple, the data structures are 
all totally trivial, but the possibility for interactions causes all the 
excitement.

			Linus

^ permalink raw reply

* Re: unmerging feature branches
From: Linus Torvalds @ 2007-10-23 19:46 UTC (permalink / raw)
  To: martin f krafft; +Cc: git discussion list
In-Reply-To: <alpine.LFD.0.999.0710231221530.30120@woody.linux-foundation.org>



On Tue, 23 Oct 2007, Linus Torvalds wrote:
>
> > by shape you mean the actual graph, and when 'branch' is merged into
> > master at m2, Git goes back in time to conclude that master...L must
> > already be present in master due to the intersection of the two
> > lines at m, and thus finds commit F as the "oldest direct
> > descendant" of m2. L is an older descendant of m2, but it's not
> > direct in the sense that there are multiple paths from m2 to L. Thus
> > Git will only merge F..T at m2.
> 
> Exactly.

Side note: strictly speaking, git will not merge "F..T" in the sense that 
it never actually even _looks_ at any of the commits in that range per se.

So what it really does is to look at state of the common point ('L') and 
then the states of the end-points, and merge things based purely based on 
that state, and then join the histories up.

Yes, that *effectively* means merging all the changes from 'F'..'T', but I 
want again to point out that the actual changes done by any of the 
individual commits in that range are never even looked at. They really are 
totally irrelevant on their own.

So if 'F' did a lot of changes and 'T' undid most of them, the merge 
algorithm will not ever even *see* those changes. They were irrelevant. 
It's not that git sees the changes and then sees that 'T' undid them: git 
will literally never actually even look at them in the first place!

That's what I mean by only taking "state" into account. It didn't matter 
what any individual commit did. Git won't even have looked at the commit, 
other than to find its parent. When git merges, it literally looks at just 
the end results, and the last common state(s).

So history matters a great deal to merging, but it only matters in the 
global "shape" sense, never in the "per-commit" sense.

			Linus

^ permalink raw reply

* Re: unmerging feature branches
From: Linus Torvalds @ 2007-10-23 19:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: martin f krafft, git discussion list
In-Reply-To: <7vir4x7hiu.fsf@gitster.siamese.dyndns.org>



On Tue, 23 Oct 2007, Junio C Hamano wrote:
> 
> Desire to revert an octopus would, as you demonstrated, often be
> to revert only one arm, but I think allowing to revert a twohead
> merge should be trivial.  If we define "reverting a merge" to
> always revert all arms, then this should suffice.

The only reason I don't like this is that it kind of assumes that the 
mainline is the first parent. 

Maybe I'd like to revert a merge, but I want to revert a merge that 
somebody *else* did, and maybe it was the first-hand parent I don't like. 

Those kinds of issues don't exist with non-merge commits: there's never 
any question "which side" to revert.

			Linus

^ permalink raw reply

* Re: How to run git-gui always in English?
From: Steffen Prohaska @ 2007-10-23 20:00 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Git Mailing List, msysGit
In-Reply-To: <CCAD0DE0-65D4-4FEC-B02F-658010FECD04@zib.de>

[-- Attachment #1: Type: text/plain, Size: 752 bytes --]


On Oct 21, 2007, at 8:47 AM, Steffen Prohaska wrote:

> How can I switch msysgit's git-gui to English, independently of
> the language selected for Windows? I recognized that git-gui
> adjusts to the 'language selection' of Windows. How can I
> disable this? I want git-gui to always display English. Nothing
> else, never! I can't help people who use a different language
> in the gui, because I'll not understand what they are talking
> about and they'll not understand me.

And it's even worse. An error in the localization can completely
break git-gui. Apparently the German localization included in
msysgit's Git-1.5.3-preview20071019.exe _is_ broken (see
attached png).

Shouldn't the localization code be a bit more fault tolerant?

	Steffen



[-- Attachment #2: gitGui Fehler.png --]
[-- Type: image/png, Size: 36458 bytes --]

[-- Attachment #3: Type: text/plain, Size: 1 bytes --]



^ permalink raw reply

* Re: git-annotate - leaking hundrets of megabytes
From: Florian Weimer @ 2007-10-23 20:12 UTC (permalink / raw)
  To: git
In-Reply-To: <alpine.LFD.0.999.0710231108150.30120@woody.linux-foundation.org>

* Linus Torvalds:

> What git version do you have, or did you perhaps mean some other file or 
> other config that causes this?

I see it with Debian's 1:1.5.3.4-1 version, but also with dd8175f83c725.
In my case, it's a git-svn mirror of:

  svn://svn.debian.org/secure-testing/data/CVE/list

This is a very difficult file for git-annotate (and "svn blame") because
of its history and size.

^ permalink raw reply

* Re: Howto request: going home in the middle of something?
From: Matthias Kestenholz @ 2007-10-23 20:28 UTC (permalink / raw)
  To: Jing Xue; +Cc: Jan Wielemaker, Petr Baudis, git
In-Reply-To: <20071023135655.x6g6mln1j4880wog@intranet.digizenstudio.com>

Hi,

On 23.10.2007, at 19:56, Jing Xue wrote:
> What does the extra branch gain for us here? That's not a  
> rhetorical question, I'm actually curious to learn, because I  
> always just commit, switch to another computer, pull, and reset HEAD^.

If someone tracks the main branch you are working on and fetches
while you are travelling home, he has the WIP commit as a new tip
in his tree.
If he bases further work upon the WIP commit, he'll need to rebase
or merge his changes onto your new tip once you have amended or
replaced the commit. If you are working on the
master branch, you should really avoid rewinding it. Rewinding topic
branches is ok, but a temporary branch is still better to clearly tell
potential fetch-ers that this is only Work in Progress, and not meant
to be published in the current state.

Matthias

-- 
http://spinlock.ch/blog/

^ permalink raw reply

* [PATCH] revert/cherry-pick: work on merge commits as well
From: Junio C Hamano @ 2007-10-23 20:33 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: martin f krafft, git discussion list
In-Reply-To: <alpine.LFD.0.999.0710231247301.30120@woody.linux-foundation.org>

Usually you cannot revert a merge because you do not know which
side of the merge should be considered the mainline (iow, what
change to reverse).

With this patch, cherry-pick and revert learn -m (--mainline)
option that lets you specify the parent number (starting from 1)
of the mainline, so that you can:

	git revert -m 1 $merge

to reverse the changes introduced by the $merge commit relative
to its first parent, and:

	git cherry-pick -m 2 $merge

to replay the changes introduced by the $merge commit relative
to its second parent.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 Linus Torvalds <torvalds@linux-foundation.org> writes:

 > On Tue, 23 Oct 2007, Junio C Hamano wrote:
 >> 
 >> Desire to revert an octopus would, as you demonstrated, often be
 >> to revert only one arm, but I think allowing to revert a twohead
 >> merge should be trivial.  If we define "reverting a merge" to
 >> always revert all arms, then this should suffice.
 >
 > The only reason I don't like this is that it kind of assumes that the 
 > mainline is the first parent. 
 >
 > Maybe I'd like to revert a merge, but I want to revert a merge that 
 > somebody *else* did, and maybe it was the first-hand parent I don't like. 
 >
 > Those kinds of issues don't exist with non-merge commits: there's never 
 > any question "which side" to revert.

 Fair enough.  How about this?

 Documentation/git-cherry-pick.txt |    9 +++++++-
 Documentation/git-revert.txt      |    9 +++++++-
 builtin-revert.c                  |   42 ++++++++++++++++++++++++++++++------
 git-compat-util.h                 |   13 +++++++++++
 4 files changed, 64 insertions(+), 9 deletions(-)

diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index 76a2edf..937c4a7 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -7,7 +7,7 @@ git-cherry-pick - Apply the change introduced by an existing commit
 
 SYNOPSIS
 --------
-'git-cherry-pick' [--edit] [-n] [-x] <commit>
+'git-cherry-pick' [--edit] [-n] [-m parent-number] [-x] <commit>
 
 DESCRIPTION
 -----------
@@ -44,6 +44,13 @@ OPTIONS
 	described above, and `-r` was to disable it.  Now the
 	default is not to do `-x` so this option is a no-op.
 
+-m parent-number|--mainline parent-number::
+	Usually you cannot revert a merge because you do not know which
+	side of the merge should be considered the mainline.  This
+	option specifies the parent number (starting from 1) of
+	the mainline and allows cherry-pick to replay the change
+	relative to the specified parent.
+
 -n|--no-commit::
 	Usually the command automatically creates a commit with
 	a commit log message stating which commit was
diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt
index 69db498..3457c40 100644
--- a/Documentation/git-revert.txt
+++ b/Documentation/git-revert.txt
@@ -7,7 +7,7 @@ git-revert - Revert an existing commit
 
 SYNOPSIS
 --------
-'git-revert' [--edit | --no-edit] [-n] <commit>
+'git-revert' [--edit | --no-edit] [-n] [-m parent-number] <commit>
 
 DESCRIPTION
 -----------
@@ -27,6 +27,13 @@ OPTIONS
 	message prior committing the revert. This is the default if
 	you run the command from a terminal.
 
+-m parent-number|--mainline parent-number::
+	Usually you cannot revert a merge because you do not know which
+	side of the merge should be considered the mainline.  This
+	option specifies the parent number (starting from 1) of
+	the mainline and allows revert to reverse the change
+	relative to the specified parent.
+
 --no-edit::
 	With this option, `git-revert` will not start the commit
 	message editor.
diff --git a/builtin-revert.c b/builtin-revert.c
index a655c8e..bfed69d 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -19,9 +19,9 @@
  * Copyright (c) 2005 Junio C Hamano
  */
 
-static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] <commit-ish>";
+static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] [-m parent-number] <commit-ish>";
 
-static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-r] [-x] <commit-ish>";
+static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-m parent-number] [-r] [-x] <commit-ish>";
 
 static int edit;
 static int replay;
@@ -29,6 +29,7 @@ static enum { REVERT, CHERRY_PICK } action;
 static int no_commit;
 static struct commit *commit;
 static int needed_deref;
+static int mainline;
 
 static const char *me;
 
@@ -58,6 +59,12 @@ static void parse_options(int argc, const char **argv)
 		else if (!strcmp(arg, "-x") || !strcmp(arg, "--i-really-want-"
 				"to-expose-my-private-commit-object-name"))
 			replay = 0;
+		else if (!strcmp(arg, "-m") || !strcmp(arg, "--mainline")) {
+			if (++i >= argc ||
+			    strtol_i(argv[i], 10, &mainline) ||
+			    mainline <= 0)
+				usage(usage_str);
+		}
 		else if (strcmp(arg, "-r"))
 			usage(usage_str);
 	}
@@ -234,7 +241,7 @@ static int merge_recursive(const char *base_sha1,
 static int revert_or_cherry_pick(int argc, const char **argv)
 {
 	unsigned char head[20];
-	struct commit *base, *next;
+	struct commit *base, *next, *parent;
 	int i;
 	char *oneline, *reencoded_message = NULL;
 	const char *message, *encoding;
@@ -269,8 +276,29 @@ static int revert_or_cherry_pick(int argc, const char **argv)
 
 	if (!commit->parents)
 		die ("Cannot %s a root commit", me);
-	if (commit->parents->next)
-		die ("Cannot %s a multi-parent commit.", me);
+	if (commit->parents->next) {
+		/* Reverting or cherry-picking a merge commit */
+		int cnt;
+		struct commit_list *p;
+
+		if (!mainline)
+			die("Commit %s is a merge but no -m option was given.",
+			    sha1_to_hex(commit->object.sha1));
+
+		for (cnt = 1, p = commit->parents;
+		     cnt != mainline && p;
+		     cnt++)
+			p = p->next;
+		if (cnt != mainline || !p)
+			die("Commit %s does not have parent %d",
+			    sha1_to_hex(commit->object.sha1), mainline);
+		parent = p->item;
+	} else if (0 < mainline)
+		die("Mainline was specified but commit %s is not a merge.",
+		    sha1_to_hex(commit->object.sha1));
+	else
+		parent = commit->parents->item;
+
 	if (!(message = commit->buffer))
 		die ("Cannot get commit message for %s",
 				sha1_to_hex(commit->object.sha1));
@@ -299,14 +327,14 @@ static int revert_or_cherry_pick(int argc, const char **argv)
 		char *oneline_body = strchr(oneline, ' ');
 
 		base = commit;
-		next = commit->parents->item;
+		next = parent;
 		add_to_msg("Revert \"");
 		add_to_msg(oneline_body + 1);
 		add_to_msg("\"\n\nThis reverts commit ");
 		add_to_msg(sha1_to_hex(commit->object.sha1));
 		add_to_msg(".\n");
 	} else {
-		base = commit->parents->item;
+		base = parent;
 		next = commit;
 		set_author_ident_env(message);
 		add_message_to_msg(message);
diff --git a/git-compat-util.h b/git-compat-util.h
index f23d934..a12c36b 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -376,4 +376,17 @@ static inline int strtoul_ui(char const *s, int base, unsigned int *result)
 	return 0;
 }
 
+static inline int strtol_i(char const *s, int base, int *result)
+{
+	long ul;
+	char *p;
+
+	errno = 0;
+	ul = strtol(s, &p, base);
+	if (errno || *p || p == s || (int) ul != ul)
+		return -1;
+	*result = ul;
+	return 0;
+}
+
 #endif
-- 
1.5.3.4.1324.ga7925

^ permalink raw reply related

* Re: [PATCH trailing ws fixed] use only the PATH for exec'ing git commands
From: Alex Riesen @ 2007-10-23 21:12 UTC (permalink / raw)
  To: Scott Parish; +Cc: git
In-Reply-To: <20071023040844.GQ16291@srparish.net>

Scott Parish, Tue, Oct 23, 2007 06:08:45 +0200:
> We need to correctly set up PATH for non-c based git commands. Since we
> already do this, we can just use that PATH and execvp, instead of looping
> over the paths with execve.
> 
> This patch adds a setup_path() function to exec_cmd.c, which sets
> the PATH order correctly for our search order. execv_git_cmd() is
> stripped down to setting up argv and calling execvp(). git.c's main()
> only only needs to call setup_path().
> 
> Signed-off-by: Scott R Parish <srp@srparish.net>

Acked-by: Alex Riesen <raa.lkml@gmail.com>

Don't forget to mention it needs the patch from Johannes re "deducing
exec_path from calls to git with a relative path" and your
"current_exec_path"-patch. Took me a while to figure these out...

^ permalink raw reply

* Re: [PATCH trailing ws fixed] use only the PATH for exec'ing  gitcommands
From: Scott R Parish @ 2007-10-23 21:27 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git
In-Reply-To: <20071023211202.GA729@steel.home>

> Acked-by: Alex Riesen <raa.lkml@gmail.com>
>
> Don't forget to mention it needs the patch from Johannes re "deducing
> exec_path from calls to git with a relative path" and your
> "current_exec_path"-patch. Took me a while to figure these out...

Sorry about that! I was basing my patches off the head of spearce, as it
sounded like Junio was going to pick that stuff up.

sRp

^ permalink raw reply

* Re: [PATCH 1/2] rev-list: implement --bisect-all
From: Junio C Hamano @ 2007-10-23 21:33 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Christian Couder, git
In-Reply-To: <Pine.LNX.4.64.0710080607180.4174@racer.site>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> On Mon, 8 Oct 2007, Christian Couder wrote:
>
>> but I am not sure that the "dunno" logic should be the first part of it 
>> to be done in C.
>
> The thing is, git-bisect is porcelain-ish.  And by having a lot of the 
> functionality there, which is not really porcelain, but plumbing, you 
> prevent other porcelains, such as git-gui or qgit, from using that 
> function.
>
> Which is bad.

Still, it is good to prototype in the script while figuring out
what the desired behaviour is, I would say.

What I was hoping to see when I posted --bisect-all suggestion
was a bit different from what Christian did, by the way.

In addition to the bisect/skip-* that are filtered at the shell
level, if you feed the list of commits that cannot be tested to
the bisection plumbing, you can affect the way the resulting
list from the --bisect-all is sorted.

Suppose you have this (B is bad, G is good):

           o---.........---o---Y---o---o---B
          /                       /
     G---o---.........---o---Z---X

and one round of bisection picked X.  You find it untestable,
and Y and Z both bisects the remaining set equally well.  In
such a case, the current code sorts the resulting set, with Y
and Z next to each other (because they are both closest to the
midway), and the Porcelain filters out X which is better than Y
or Z.  You may end up picking Z.

Often, when X is not testable, neither is Z.  We would be better
off to avoid checking a commit close to what are known to be
untestable while there are other commits that are equally close
to the midway.

So instead of sorting the list solely based on the mid-ness like
the current code does (i.e. compare_commit_dist()), we can tweak
commits' mid-ness value (i.e. best_bisection_sorted() computes
it in distance variable) by penalizing it with the closeness of
the commit to known untestable commits.

Naively, "closeness" of commit Z to commit X can be defined as
something simple as "rev-list Z...X | wc -l".  The smaller the
number, the closer the commits.

^ permalink raw reply

* UI and git-completion.sh
From: Paolo Ciarrocchi @ 2007-10-23 21:46 UTC (permalink / raw)
  To: git

Hi all,
I just asked for help on the #git irc channel in order to install
the .git-completion.sh script (thanks nessundorma) and after using it 
for a while I started wondering why I cannot find any reference to it the 
official documentation.
The only important think that git grep found is:
	paolo@paolo-desktop:~/git$ git grep completion *
	Documentation/RelNotes-1.5.0.txt: - Bash completion scripts have been updated heavily.
Shouldn't it be mentioned somewhere? 

I know that newbies are somehow scared by the following:
	paolo@paolo-desktop:~/git$ git-
	Display all 151 possibilities? (y or n)
What? Do I have to learn 151 commands?
No way!

Using the git-completation script it all boils down to 48 commands.

paolo@paolo-desktop:~/git$ git 
add                   fetch                 rebase 
am                    filter-branch         rebase--interactive 
annotate              format-patch          relink 
apply                 fsck                  remote 
archive               gc                    repack 
bisect                get-tar-commit-id     request-pull 
blame                 grep                  reset 
branch                gui                   resolve 
bundle                imap-send             revert 
checkout              init                  rm 
checkout-index        instaweb              send-email 
cherry                log                   shortlog 
cherry-pick           lost-found            show 
citool                ls-files              show-branch 
clean                 ls-remote             show-ref 
clone                 ls-tree               stash 
commit                merge                 status 
config                mergetool             submodule 
convert-objects       mv                    tag 
count-objects         name-rev              var 
describe              pickaxe               verify-pack 
diff                  pull                  whatchanged 
diff-stages           push

And I think I can remove some commands from the list.

What people think about starting suggesting the usage of the script in the documentation?
I just want to know the opinion of the list before trying to write a documentation patch.
Next step would be to reduce the number of the items listed by git <tab> but I know there is 
already a discussion about it on the list.

Regards,
		Paolo

^ permalink raw reply

* Re: UI and git-completion.sh
From: Steven Grimm @ 2007-10-23 22:00 UTC (permalink / raw)
  To: Paolo Ciarrocchi; +Cc: git
In-Reply-To: <20071023234617.45a4fc64@paolo-desktop>

Paolo Ciarrocchi wrote:
> What people think about starting suggesting the usage of the script in the documentation?
>   
Also might be worth mentioning the zsh completion support. (I know it's 
there, but haven't used it -- maybe its author would care to describe it 
a bit?)

-Steve

^ permalink raw reply

* Re: [PATCH 4/7] Bisect: factorise "bisect_write_*" functions.
From: Junio C Hamano @ 2007-10-23 22:13 UTC (permalink / raw)
  To: Christian Couder; +Cc: Johannes Schindelin, git
In-Reply-To: <20071014142938.d722299c.chriscool@tuxfamily.org>

Sort of offtopic, but is "factorise" a correct verb here?  I
thought "factorise" is to express a non prime number as the
product of prime numbers.

"refactor" is the act of splitting and merging pieces of
functions for better reuse, isn't it?

^ permalink raw reply

* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Alex Riesen @ 2007-10-23 22:13 UTC (permalink / raw)
  To: Wincent Colaiuta
  Cc: Johannes Schindelin, Andreas Ericsson, Jakub Narebski,
	Steffen Prohaska, Federico Mena Quintero, git
In-Reply-To: <ED965042-27DE-450B-96CB-00D27000FAF6@wincent.com>

Wincent Colaiuta, Mon, Oct 22, 2007 15:17:19 +0200:
>
>> So once again, what operations involving git do people use regularly?
>
> Here are my top ten commands, sorted by the number of times they appear in 
> my ~/.bash_history:

from my (short, 500) .bash_history:

     26 am
     22 gitk
     21 fetch
     15 reset
     10 log
      9 merge
      8 cherry-pick
      7 status
      5 commit
      4 svn
      4 push
      4 gc
      4 diff
      3 gui
      3 format-patch
      2 pull
      2 clone
      1 show
      1 rebase
      1 grep
      1 cat-file
      1 branch
      1 apply

branch, cat-file and show are actually fairly common, the history just
shorted and I lost them.

^ permalink raw reply

* Re: [PATCH 4/7] Bisect: factorise "bisect_write_*" functions.
From: J. Bruce Fields @ 2007-10-23 22:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Christian Couder, Johannes Schindelin, git
In-Reply-To: <7v640x7a4n.fsf@gitster.siamese.dyndns.org>

On Tue, Oct 23, 2007 at 03:13:12PM -0700, Junio C Hamano wrote:
> Sort of offtopic, but is "factorise" a correct verb here?  I
> thought "factorise" is to express a non prime number as the
> product of prime numbers.

"Factor" is a perfectly good verb on its own, no need for the "ise"
normally.

--b.

^ permalink raw reply

* Re: [PATCH 4/7] Bisect: factorise "bisect_write_*" functions.
From: Andreas Ericsson @ 2007-10-23 22:36 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Christian Couder, Johannes Schindelin, git
In-Reply-To: <7v640x7a4n.fsf@gitster.siamese.dyndns.org>

Junio C Hamano wrote:
> Sort of offtopic, but is "factorise" a correct verb here?  I
> thought "factorise" is to express a non prime number as the
> product of prime numbers.
> 

It's the reverse of expanding brackets, like so:
2x² + x - 3 = (2x + 3)(x - 1)

> "refactor" is the act of splitting and merging pieces of
> functions for better reuse, isn't it?
> 

Yes.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox