git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* Re: Please undo "Use git-merge instead of git-resolve in
@ 2005-09-22 14:55 Jon Loeliger
  2005-09-22 16:01 ` Petr Baudis
  2005-09-22 16:06 ` Linus Torvalds
  0 siblings, 2 replies; 22+ messages in thread
From: Jon Loeliger @ 2005-09-22 14:55 UTC (permalink / raw
  To: git

Dave Wrote:
> From: Linus Torvalds <torvalds@osdl.org>
> 
> > I often have local changes in my tree that I don't want to commit but that 
> > I'm testing out. Havign them interfere with merging other peoples work 
> > would mean that I'd have to have a totally separate tree for that, which I 
> > could do, but I'm much much happier not having to.
> 
> You know, I personally was unaware that this was supported until now.
> I have been always reverting local debugging changes in order to merge
> other people's work in, then reapply the debugging changes afterwards.

So, interesting that this comes up now, as I recently had a
discussion on this topic with a few coworkers.  We concluded
that we were clueless and what would help us out a whole bunch
would be a few more Use Cases down this line added to the Tutorial.

I'll include my original (internal) question as an example
use case.  Perhaps it will illustrate two things:

    - How clueless I am about Git still
    - Where some of the Git Frustration still lies

I'd offer to write it, but I'm just flat in the dark here and
need to _read_ it first. :-)  I'll offer this instead:  If you
(someone) tells me the commands that illustrate how to do what
I'm after here, I'll make a stab at writing up the tutorial
Use Case for it.

(Yes, I know there is a Use Case very similar to this in
the Tutorial, but it is not quite the same.  And I can't
see how to intuit a step towards what I'm wanting here.)

Thanks,
jdl



    OK, so I have a git tree that looks like this:

    241 % git show-branch --more=5
    * [jdl] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
     ! [master] Merge branch 'master' of /home/src/linux-2.6/
      ! [origin] Merge branch 'master' of /home/src/linux-2.6/
       ! [paul] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
    ----
    +  + [jdl] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
    ++++ [master] Merge branch 'master' of /home/src/linux-2.6/
    ++++ [master~1] NTFS: Fix ntfs_{read,write}page() to cope with concurrent truncates better.
    ++++ [master~2] NTFS: Fix handling of compressed directories that I broke in earlier changeset.
    ++++ [master~3] NTFS: Fix various bugs in the runlist merging code.  (Based on libntfs
    ++++ [master~4] vc: Use correct size on buffer copy in vc_resize
    +  + [jdl~1] Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge
    +  + [jdl^2] ppc32: Allow user to individual select CHRP/PMAC/PREP config
    +  + [jdl^2~1] powerpc: Merge simplified sections.h into asm-powerpc
    +  + [jdl^2~2] powerpc: Remove section free() and linker script bits
    +  + [jdl^2~3] powerpc: Remove sections use from ppc64 and drivers
    +  + [jdl^2~4] powerpc: Remove sections use from ppc
    +  + [jdl^2~5] ppc32: Removed non-inlined versions of local_irq* functions
    ++++ [jdl~2] Merge master.kernel.org:/home/rmk/linux-2.6-arm

    I have current, modified, non-committed files in my working tree
    in the "jdl" branch.  I don't want to commit them now (yet).

    I now know that Linus has updated his tree with new -rc2 parts.
    I want it.  In fact, I want it on the "origin" or "master" branch.
    (Or both.  And I don't know which.)

    How do I get Linus' updates and merge them into the "origin" branch
    without changing to that branch first?

    How do I get Paul's updates and merge them into the "paul" branch
    without changing to that branch first?

    I think I can fetch the Linus updates by doing something like this:

	git fetch origin
    or
	git fetch rsync://....path/to/linus-2.6-git

    That will just grab the Objects and throw them into my .git/objects.

    But how to do the merge?  I think that the merges all require
    the "target branch" to be the "active"/checkedout branch, right?
    I don't know how to now say "Merge-up those new Objects on the
    origin branch".

    I think what's confusing me still is that the previous
    World View According to CVS was essentially that you have
    this import branch into which you dragged all the external
    updates.  Then you merged that over to your working branch.
    And, you could easily have views of _both_ of those
    branches simultaneously.

    With Git, you can't really do that in quite the same way.
    Sure, you can treat a branch as an "import branch".  But
    if you have uncommitted files over in a different branch,
    you can't change your cehckout-view to do so.

    However, I _could_ just stick in my "jdl" working branch and
    directly pull-in and merge the linus changes.  I mean, my next
    step after pulling those changes into the so-called import
    branch was going to be to merge them to my branch anyway.

    OK, so let's say I did pull linus' update into the jdl branch.
    And they merge up nicely.  How do I now propogate _just_ the
    linus changes to the origin branch?  Again, I don't think I
    can without first checking out the "origin" branch.

    Am I missing something here?  Fighting against the tool?


A coworker replied:

    > I read your message, and I read the git documentation, and I
    > scratched my head a bit, and the end result is that I still don't
    > know.  The docs really suck.  Everything you say seems to make
    > sense, but I just can't confirm that it's actually how things
    > work.  And I don't know how to do a merge like you propose.

I responded:

    So, you will all be pleased to know that I tried
    some stuff and was not successful.  In the "jdl"
    branch, I did a "git pull linus".  It happily went
    out and grabbed all the new objects from his tree.
    Spiffy.  It then announced that my branch of the
    working tree was "dirty" and quit.

    At this point, I _think_ this is where a "cg-pull"
    instead of a "git pull" would have gone on, done
    some figuring, and decided that it needed to
    rebase my current changes after merging in the
    fetched objects.

    Not sure.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-22 14:55 Jon Loeliger
@ 2005-09-22 16:01 ` Petr Baudis
  2005-09-22 16:06 ` Linus Torvalds
  1 sibling, 0 replies; 22+ messages in thread
From: Petr Baudis @ 2005-09-22 16:01 UTC (permalink / raw
  To: Jon Loeliger; +Cc: git

Dear diary, on Thu, Sep 22, 2005 at 04:55:26PM CEST, I got a letter
where Jon Loeliger <jdl@freescale.com> told me that...
>     I now know that Linus has updated his tree with new -rc2 parts.
>     I want it.  In fact, I want it on the "origin" or "master" branch.
>     (Or both.  And I don't know which.)
> 
>     How do I get Linus' updates and merge them into the "origin" branch
>     without changing to that branch first?
> 
>     I think I can fetch the Linus updates by doing something like this:
> 
> 	git fetch origin
>     or
> 	git fetch rsync://....path/to/linus-2.6-git
> 
>     That will just grab the Objects and throw them into my .git/objects.
> 
>     But how to do the merge?  I think that the merges all require
>     the "target branch" to be the "active"/checkedout branch, right?
>     I don't know how to now say "Merge-up those new Objects on the
>     origin branch".

[I say 'master', but I mean the whatever branch you are currently
working on.]

Your origin branch just represents what Linus has in his master branch.
You don't ever merge anything to it - if you fetch new stuff from Linus,
it simply gets updated to point at the newest Linus' stuff. You can then
merge your 'origin' branch to your 'master' branch, therefore getting
the newest Linus' stuff there.

About two nights ago I tried to describe all this branching stuff in
Cogito's README. It is aimed at Cogito, but generally appliable to GIT
as well. s/cg-/git-/, cg-update is git-pull, and instead of using
cg-branch-* you edit stuff in .git/remotes. It'd be interesting to know
how much more light it manages to shed on the issue, and generally what
do people think about it:


Understanding GIT branching and merging
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Cogito's (inherited from GIT) concept of branching and merging may be a little
confusing at first, since it can be different from what you knew so far. First,
"branch" is too abstract word for us, so we will abandon it for now. We will
present two other key concepts instead:

	- Repository - when you did `cg-clone` or `cg-init`, you created
	  a repository. That is a kind of container holding (usually) all your
	  history and data.

	- Head - each repository has some heads available. Those are kind of
	  handles for various sequences of commit. A head contains simply a
	  pointer to the last commit in the sequence, and if you commit 'onto'
	  a head, the pointer will be advanced to the new commit. Your
	  "current" head is the one you are currently working on. It is
	  normally called 'master'.

Now let's take an hypothetical repository:

	repository
	+--------+
	|  master<  heads
	|   unoji<
	+--------+

Let's suppose that we want to fork off master's development. We have two
possibilities, either make new repository for it, or a new head.

Let's say that we want to fork it off for our work offline on a notebook,
so we will make it through cloning the repository to our notebook. What
will `cg-clone` do?

	+--------+
	+--------+
First it creates an empty repository

	+--------+
	$  origin<
	+--------+
Then it creates an 'origin' head, and will copy all the history from the
remote repository's 'master' head there. So this head exists to reflect
the state of the remote repository. The important point is that it is
called 'origin' in our new repository, even through it corresponds to
a 'master' head in the old repository. This is normal - you can name your
local heads whatever you want.

The dollar sign denotes that this head is associated with a "remote branch"
- a source location of the head is saved somewhere and you can fetch the
head and possibly push to it.

	+--------+
	|  master<
	$  origin<
	+--------+
Finally it copied over the 'origin' head to the 'master' head, which will
from now as your current head represent your local development in the
repository.

So you do some local development, do few commits on the 'master' head and
want to catch up with the upstream repository. You use 'cg-update', but what
will it do?

	+--------+
	|  master<
	$  origin< < < < <
	+--------+
First, it will populate your 'origin' head with the new commits from the
remote's 'master' head.

	+--------+
	|  master<-M-.
	$  origin>---'
	+--------+
Then, it will merge those new commits to your 'master' head.

Now let's imagine that there is also another head 'unoji' on the other side
besides 'master', containing some cool commits not in 'master' (it has such an
exotic name, after all...). You want to merge its commits to your head too?

	$ cg-branch-add r-unoji 'http://remote/repository#unoji'
	$ cg-fetch r-unoji

will make your repository look like

	+--------+
	|  master<
	$  origin<
	$ r-unoji<
	+--------+

with 'r-unoji' containing stuff from the remote's 'unoji' branch.

Ok, you did some development, but you decided not to merge it into upstream's
'master' yet since it is not yet stable enough. However, you want to upload it
into the upstream repository since it is public and you want people to be able
to try out your stuff. Easy, let's push it to a new head on the server.

	$ cg-branch-add upmirror 'git+ssh://remote/repository#nislu'

will make your repository look like:

	+--------+
	|  master<
	$  origin<
	$ r-unoji<
	$upmirror|
	+--------+

Note that 'upmirror' has no head associated, it has just the "remote branch"
info. That is because it needs no head since it's solely for pushing. It is
however normal to have a head (frequently it's the 'origin') both for pulling
and pushing.

	$ cg-push upmirror

will then make the remote repository look like:

	+--------+
	|  master<
	|   unoji<
	|   nislu<
	+--------+

with 'nislu' on the remote side corresponding to the 'master' in your local
repository.

Ok, so this is how it goes for multiple repositories, where the cloned
repositories are essentially single branches. Note that if you clone the
repository locally, it can be actually very cheap, basically for free with
`cg-clone -l` (but please read its documentation).

But what if you still do not want multiple repositories? The key here is to
change your "current head" from 'master' to some new head, and then to be
able to switch back and forth. This is unfortunately something Cogito does
not let you do directly right now, but you can use core GIT commands

	$ git-checkout -b aspyk

to create a new 'aspyk' head and switch to it, and

	$ git-checkout master

to switch back to 'master' later, etc. Note that between the switching,
Cogito will work just fine even if your current head is not 'master'.

You can get the list of available heads by

	$ cg-status -g

where the current head is marked by '>' and remote heads are marked by 'R'.
You can also get the list of source locations for remote heads by

	$ cg-branch-ls


-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
VI has two modes: the one in which it beeps and the one in which
it doesn't.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-22 14:55 Jon Loeliger
  2005-09-22 16:01 ` Petr Baudis
@ 2005-09-22 16:06 ` Linus Torvalds
  1 sibling, 0 replies; 22+ messages in thread
From: Linus Torvalds @ 2005-09-22 16:06 UTC (permalink / raw
  To: Jon Loeliger; +Cc: git



On Thu, 22 Sep 2005, Jon Loeliger wrote:
> 
>     - Where some of the Git Frustration still lies

Btw, I'd love to have more "this frustrates me" stories. I used to ask for 
them from the (few) people that used git early on, just to see what the 
problems were.

I can't really help you with documentation, and would just hope that 
people who figure out a problem they had would actually document it so 
that others don't have to figure it out the hard way.

But if there is some usage pattern that doesn't make sense, post about it,
and I can try to at least say why it happens that way (and then it's back
to the "please send a patch to the documentation" case above ;). 

Alternatively, maybe it is something that doesn't need to happen at all, 
and it's just git being stupid, and we can just fix it.

So to look at your care.

>     OK, so I have a git tree that looks like this:
> 
>     241 % git show-branch --more=5
>     * [jdl] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
>      ! [master] Merge branch 'master' of /home/src/linux-2.6/
>       ! [origin] Merge branch 'master' of /home/src/linux-2.6/
>        ! [paul] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
>     ----
>     +  + [jdl] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
>     ++++ [master] Merge branch 'master' of /home/src/linux-2.6/
>     ++++ [master~1] NTFS: Fix ntfs_{read,write}page() to cope with concurrent truncates better.
>     ++++ [master~2] NTFS: Fix handling of compressed directories that I broke in earlier changeset.
>     ++++ [master~3] NTFS: Fix various bugs in the runlist merging code.  (Based on libntfs
>     ++++ [master~4] vc: Use correct size on buffer copy in vc_resize
>     +  + [jdl~1] Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge
>     +  + [jdl^2] ppc32: Allow user to individual select CHRP/PMAC/PREP config
>     +  + [jdl^2~1] powerpc: Merge simplified sections.h into asm-powerpc
>     +  + [jdl^2~2] powerpc: Remove section free() and linker script bits
>     +  + [jdl^2~3] powerpc: Remove sections use from ppc64 and drivers
>     +  + [jdl^2~4] powerpc: Remove sections use from ppc
>     +  + [jdl^2~5] ppc32: Removed non-inlined versions of local_irq* functions
>     ++++ [jdl~2] Merge master.kernel.org:/home/rmk/linux-2.6-arm
> 
>     I have current, modified, non-committed files in my working tree
>     in the "jdl" branch.  I don't want to commit them now (yet).
> 
>     I now know that Linus has updated his tree with new -rc2 parts.
>     I want it.  In fact, I want it on the "origin" or "master" branch.
>     (Or both.  And I don't know which.)
> 
>     How do I get Linus' updates and merge them into the "origin" branch
>     without changing to that branch first?
> 
>     How do I get Paul's updates and merge them into the "paul" branch
>     without changing to that branch first?
> 
>     I think I can fetch the Linus updates by doing something like this:
> 
> 	git fetch origin

Yes, this works. This will fetch the new objects, and automatically update
the right branch (ie it will also update the "origin" branch).

> 	git fetch rsync://....path/to/linus-2.6-git

This will _not_ work. Or rather, it will "work" in the sense that it 
fetches the objects, but without a place to put them into, it won't update 
any of the branches, so it's kind of pointless.

>     That will just grab the Objects and throw them into my .git/objects.
> 
>     But how to do the merge?  I think that the merges all require
>     the "target branch" to be the "active"/checkedout branch, right?
>     I don't know how to now say "Merge-up those new Objects on the
>     origin branch".

The first one should have done that already.

You can also specify _precisely_ what branches you want to use as a source 
and as a destination.

Ie

	git fetch rsync:..../linus-2.6-git <src>:<dst>

will fetch the <src> branch (ie you'd usually use "master") from my tree 
and write it to the <dst> branch on your tree.

And it's not a "merge" - it's just an update. A merge implies that you 
take two trees that have had development on them and try to join them 
together. A "git fetch" does _not_ merge anything: it just _fetches_ the 
other side, and writes the objects (and top branch).

>     I think what's confusing me still is that the previous
>     World View According to CVS was essentially that you have
>     this import branch into which you dragged all the external
>     updates.  Then you merged that over to your working branch.
>     And, you could easily have views of _both_ of those
>     branches simultaneously.

Hmm.. I'm not sure exactly what you want, but

	git fetch origin

will fetch my stuff without touching your changes AT ALL, and then you can 
do things like

	gitk --all

to see both your development series _and_ my stuff at the same time. And 
yes, it works fine even if you have "dirty state" in your tree.

>     However, I _could_ just stick in my "jdl" working branch and
>     directly pull-in and merge the linus changes.  I mean, my next
>     step after pulling those changes into the so-called import
>     branch was going to be to merge them to my branch anyway.

And indeed, if you just did

	git pull origin

then now you're doing a _pull_ instead of a fetch, which means that you do 
both the fetch _and_ the merge.

In fact, if you use the shorthand with a named branch, the above really 
_will_ do a "git fetch origin" first, ie it will actually _update_ the 
"origin" branch before merging it into your current branch. So you'll have 
_both_.

You can see that (again) with

	gitk --all

where you can actually see that "origin" got updated, and also merged into 
whatever branch you were working on.

>     OK, so let's say I did pull linus' update into the jdl branch.
>     And they merge up nicely.  How do I now propogate _just_ the
>     linus changes to the origin branch?  Again, I don't think I
>     can without first checking out the "origin" branch.

The "origin" branch was already updated automatically if you used

	git pull origin

However, if you used

	git pull rsync:..../linus-2.6.git

then git would only have fetched the objects, and _not_ updated the 
"origin" branch (because you didn't tell it about the "origin" branch). 

But you can trivially fix that by doing

	git fetch origin

at this point, which will end up doing the equivalent of

	git fetch rsync:..../linus-2.6.git master:origin

(depending on what the contents of your .git/remotes/origin are, of 
course, the above is just an example).

>     Am I missing something here?  Fighting against the tool?

No, you just didn't realize how "git pull" and "git fetch" worked. Git
should actually do what you want to do very naturally. Its' really how 
it's designed to work, you just didn't realize ;)

>     So, you will all be pleased to know that I tried
>     some stuff and was not successful.  In the "jdl"
>     branch, I did a "git pull linus".  It happily went
>     out and grabbed all the new objects from his tree.
>     Spiffy.  It then announced that my branch of the
>     working tree was "dirty" and quit.

Ok, it really depends on what your ".git/remotes/linus" looks like.

For example, it _may_ just contain something like

	URL: rsync:..../linus2.6.git

in which case there is no explicit heads specified. In that case, you 
really should specify _which_ of the heads you want to pull, and what the 
target should be. For example, you can do that with

	git fetch linus master:linus

which says: "fetch the branch 'master' from the repository described by 
'linus' (.git/remotes/linus) into _my_ branch 'linus'".

NOTE! This really is a _fetch_. It will fetch the objects, and _overwrite_ 
the old value of the branch "linus".

Now, you can specify that this is what you _always_ want to do, and 
actually set the branches in the ".git/remotes/linus" file explicitly. You 
can make your .git/remotes/linus file look like this instead:

	URL: rsync:..../linus2.6.git
	Pull: master:linus

and now you've told it that whenever you fetch (or pull) from "linus", you
want to fetch the "master" branch from the remote end, and you always want
to store it in the "linus" branch in the local repository.

NOTE NOTE NOTE! Your branch-name does _not_ have to match the shorthand 
name. So you can make the "Pull:" line say "master:linus-branch", and that 
will mean that when you do "git fetch linus", it will update the 
"linus-branch" instead.

Still with me?

Finally (or _instead_ of the "fetch"), we can do

	git pull linus

now. It will do the fetch, and since you now specify a destination in your 
"remotes/linus" file, it will always update the "linus" part (it a "git 
pull" is a _superset_ of what "git fetch" does). But in _addition_ to 
fetching the "linus" branch, it will then try to merge it.

Now, this is where "dirty" comes in. The merge will fail if you have 
changed any files that the merge wants to modify. So do a

	git diff --name-only HEAD

to see if there are any changes, and commit them - or undo them - if so.  
Then try to pull again.
	
		Linus

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
@ 2005-09-22 18:32 Jon Loeliger
  2005-09-22 19:10 ` Petr Baudis
  2005-09-22 21:12 ` Linus Torvalds
  0 siblings, 2 replies; 22+ messages in thread
From: Jon Loeliger @ 2005-09-22 18:32 UTC (permalink / raw
  To: git

Linus schreib:
>
>	git fetch rsync:..../linus-2.6-git <src>:<dst>
>
> will fetch the <src> branch (ie you'd usually use "master") from my tree 
> and write it to the <dst> branch on your tree.

... "origin".  OK.

Und, Petr schreib auch:
> Then it creates an 'origin' head, and will copy all the history from
> the remote repository's 'master' head there. So this head exists to
> reflect the state of the remote repository. The important point is
> that it is called 'origin' in our new repository, even through it
> corresponds to a 'master' head in the old repository. This is normal -
> you can name your local heads whatever you want.

Wait.

For me, this paragraph suddenly turned on one missing light:
The default construction of repository branches/heads _mismatches_
names on local and remote ends: "origin" local came from "master"
remote.  Did I miss reading that somewhere else? (Likely.)

And I sat through the Great Remote Name Discussion of '05
("How is working on arbitrary remote heads supposed to work in Cogito")
but I just didn't get it back then.

(This is an intentional asymmetry, right?  Distributed systems, right?)

In any case, I just tried this:

    git fetch rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.gi\t master:origin

And got this mess:

    sent 18136 bytes  received 2731519 bytes  60431.98 bytes/sec
    total size is 97584183  speedup is 35.49
    rsync: link_stat "/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/info/alt\ernates" (in pub) failed: No such file or directory (2)
    rsync error: some files could not be transferred (code 23) at main.c(1173)
    * non-commit: 3fd07d3bf0077dcc0f5a33d2eb1938ea050da8da
      branch 'master' of rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/l\inux-2.6
    * refs/heads/origin: does not fast forward to branch 'master' of rsync://www.ke\rnel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6;
      leaving it in 'refs/heads/origin.remote'

And this is due to kernel.org being Not Quite Right, right?

Which points out one of the other points of frustration
that I feel should be addressed eventually:  A whole section
about "What To Do When It Goes Wonky" needs to be written.

OK, so it didn't merge?  Now what?  What got left where?
How do I recover?  What bits are in my tree, and what bits
are in the Index, and what bits are in the Object store now?

OK, so it didn't download it left you "refs/heads/rigin.remote".
What should I do with it now?  And later, should I re-execute
the same "git fetch" command and hope it recovers and patches
the pieces together?  Should I do a round of house cleaning
before attempting to re-run some (the same?) command?

Things of that nature.

And more as I get further too. :-)

Thanks!
jdl

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-22 18:32 Jon Loeliger
@ 2005-09-22 19:10 ` Petr Baudis
       [not found]   ` <34462.10.10.10.28.1127417134.squirrel@linux1>
  2005-09-22 21:12 ` Linus Torvalds
  1 sibling, 1 reply; 22+ messages in thread
From: Petr Baudis @ 2005-09-22 19:10 UTC (permalink / raw
  To: Jon Loeliger; +Cc: git

Dear diary, on Thu, Sep 22, 2005 at 08:32:45PM CEST, I got a letter
where Jon Loeliger <jdl@freescale.com> told me that...
> Which points out one of the other points of frustration
> that I feel should be addressed eventually:  A whole section
> about "What To Do When It Goes Wonky" needs to be written.
> 
> OK, so it didn't merge?  Now what?  What got left where?
> How do I recover?  What bits are in my tree, and what bits
> are in the Index, and what bits are in the Object store now?
> 
> OK, so it didn't download it left you "refs/heads/rigin.remote".
> What should I do with it now?  And later, should I re-execute
> the same "git fetch" command and hope it recovers and patches
> the pieces together?  Should I do a round of house cleaning
> before attempting to re-run some (the same?) command?

FWIW, with Cogito, interrupted or failed fetch can be safely rerun, no
extra recovery procedure is required. It *seems* that this holds for
git-fetch as well.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
VI has two modes: the one in which it beeps and the one in which
it doesn't.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
@ 2005-09-22 19:12 Jon Loeliger
  2005-09-22 21:22 ` Linus Torvalds
  0 siblings, 1 reply; 22+ messages in thread
From: Jon Loeliger @ 2005-09-22 19:12 UTC (permalink / raw
  To: git


Linus calmly explained again:
>
> The "origin" branch was already updated automatically if you used
> 
> 	git pull origin
> 
> However, if you used
> 
> 	git pull rsync:..../linus-2.6.git
> 
> then git would only have fetched the objects, and _not_ updated the 
> "origin" branch (because you didn't tell it about the "origin" branch). 
> 
> But you can trivially fix that by doing
> 
> 	git fetch origin
> 
> at this point, which will end up doing the equivalent of
> 
> 	git fetch rsync:..../linus-2.6.git master:origin
> 
> (depending on what the contents of your .git/remotes/origin are, of 
> course, the above is just an example).

This was a very helpful section for me.

> For example, it _may_ just contain something like
> 
>	URL: rsync:..../linus2.6.git
> 
> in which case there is no explicit heads specified. In that case, you 
> really should specify _which_ of the heads you want to pull, and what the 
> target should be. 

In fact it contained just the "rsync:...." bits.


> For example, you can do that with
>
>	git fetch linus master:linus
>
> which says: "fetch the branch 'master' from the repository described by 
> 'linus' (.git/remotes/linus) into _my_ branch 'linus'".

Just to be clear on the overloaded use of "linus" here,
let me rewrite that:

	git fetch foo master:bar

    which says: "fetch the branch 'master' from the repository described
    by 'foo' (.git/remotes/foo) into _my_ branch 'bar'".

Right?

> Now, you can specify that this is what you _always_ want to do, and
> actually set the branches in the ".git/remotes/linus" file explicitly.
> You can make your .git/remotes/linus file look like this instead:
>
>	URL: rsync:..../linus2.6.git
>	Pull: master:linus

OK.  I think I get it.  The concept you are trying to beat into
my head is essentially the difference between a "complete" and
an "incomplete" specifier.  If there is enough specification to
fetch and merge into a branch, you can.  And there are a few
different ways to do so:

    A) git fetch rsync:..../linus-2.6.git master:origin
or 
    B) git fetch linus master:linus
       with just the URL bits in the .git/remotes
or
    C)	git fetch linus
        with both URL and "Pull:" clauses in .git remotes
            URL: rsync:..../linus2.6.git
	    Pull: master:linus

If it is an incomplete specification (without branch names),
you just can't do the whole sheebang.  You have to stop after
fetching the objects.

And add "merging" in the "git pull" cases.

> Now, this is where "dirty" comes in. The merge will fail if you have 
> changed any files that the merge wants to modify. So do a

D'oh.  This is what bites me.  Some of those diffs that
come back to me in the linus tree are one that I originated
and sent up stream in the first place.  To get those to
wash-out with the merge, I will have had to have had those
committed in my branch, right?  Otherwise they just look
like dirty files -- never mind that they are (should be)
the exact same bits coming back at me.

> So do a
>
>	git diff --name-only HEAD
>
> to see if there are any changes, and commit them - or undo them - if so.
> Then try to pull again.

Ah hah.  OK.


I want to return to this for one last comment:

    > You can make your .git/remotes/linus file look like this instead:
    >
    >	URL: rsync:..../linus2.6.git
    >	Pull: master:linus

So, philosophically perhaps, there are several different
reasons for having branches within a repository.  One of
them is to track external repositories as indicated above.
But no-one (ie, no tool) currently constructs the .git/remotes
files to have that layout, right?  I mean, The One True editor
can, but there is no git or Cogito command that says to
construct the URL: and Pull: bits like that for the purposes
of establishing a "track branch", right?  Would it make sense
to have a "--tracking" flag added to branch creation that
trumped these bits up and promotes a simpler, or specific
purpose branch?

jdl

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
       [not found]   ` <34462.10.10.10.28.1127417134.squirrel@linux1>
@ 2005-09-22 19:25     ` Sean
  2005-09-22 22:22       ` Junio C Hamano
  2005-09-23  9:10     ` Petr Baudis
  1 sibling, 1 reply; 22+ messages in thread
From: Sean @ 2005-09-22 19:25 UTC (permalink / raw
  To: Petr Baudis; +Cc: Jon Loeliger, git

On Thu, September 22, 2005 3:10 pm, Petr Baudis said:

> FWIW, with Cogito, interrupted or failed fetch can be safely rerun, no
> extra recovery procedure is required. It *seems* that this holds for
> git-fetch as well.

Petr,

Why doesn't cogito just use the git fetch/pull commands?   Why does it
need anything special?   It seems like cogito is doing more than just
being an ease-of-use layer above git.

Sean

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-22 18:32 Jon Loeliger
  2005-09-22 19:10 ` Petr Baudis
@ 2005-09-22 21:12 ` Linus Torvalds
  1 sibling, 0 replies; 22+ messages in thread
From: Linus Torvalds @ 2005-09-22 21:12 UTC (permalink / raw
  To: Jon Loeliger; +Cc: git



On Thu, 22 Sep 2005, Jon Loeliger wrote:
> 
> For me, this paragraph suddenly turned on one missing light:
> The default construction of repository branches/heads _mismatches_
> names on local and remote ends: "origin" local came from "master"
> remote.  Did I miss reading that somewhere else? (Likely.)
> 
> And I sat through the Great Remote Name Discussion of '05
> ("How is working on arbitrary remote heads supposed to work in Cogito")
> but I just didn't get it back then.
> 
> (This is an intentional asymmetry, right?  Distributed systems, right?)

Right. It's intentional. The "master" branch tends to be the main one for
everybody, but _my_ "master" branch is clearly _your_ "linus" branch, and
_your_ "master" branch would be the "jon" branch for me.

So it's not "asymmetric". It _is_ symmetric, but it's symmetric the same
way "left" and "right" are symmetric when facing each other - my left is
your right, your left is my right. It's a symmetry, but it's not an 
_identity_.

And obviously, nobody is going to have every possible branch anyway. You
just name the ones you care about (and that, in turn, _will_ break the
symmetry ;)

> In any case, I just tried this:
> 
>     git fetch rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git master:origin
> 
> And got this mess:
> 
>     sent 18136 bytes  received 2731519 bytes  60431.98 bytes/sec
>     total size is 97584183  speedup is 35.49
>     rsync: link_stat "/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/info/alternates" (in pub) failed: No such file or directory (2)
>     rsync error: some files could not be transferred (code 23) at main.c(1173)

Ok, ignore that error.

>     * non-commit: 3fd07d3bf0077dcc0f5a33d2eb1938ea050da8da
>       branch 'master' of rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6

Ok, 3fd07d3bf0077dcc0f5a33d2eb1938ea050da8da is my current head, so that 
part looks good. However, the "non-commit" part doesn't look good. It 
_should_ say "committish".

What does

	git-cat-file -t 3fd07d3bf0077dcc0f5a33d2eb1938ea050da8da

say in your tree? I suspect you don't have that object at all, and that
the mirrors are still not in sync (ie I suspect you get a "error: unable
to find 3fd..")

This, btw, is why I hate the rsync protocol. Quite frankly, it sucks. It
was wonderful for bootstrapping git when we didn't have anything else, but
dammit, it's horrid. It has no git knowledge at all, does _zero_ sanity
checking, and leaves the user going "huh" when it fails.

>     * refs/heads/origin: does not fast forward to branch 'master' of rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6;
>       leaving it in 'refs/heads/origin.remote'
> 
> And this is due to kernel.org being Not Quite Right, right?

Yes. It tries to verify that the new commit it stuffs into "origin" is a 
proper superset of the old one (so that you're not losing any data), and 
it fails, since the new commit doesn't even exist in your object list yet.

> Which points out one of the other points of frustration
> that I feel should be addressed eventually:  A whole section
> about "What To Do When It Goes Wonky" needs to be written.

Hey, you seem to have a good example of Wonky, maybe you want to write it?

> OK, so it didn't merge?  Now what?  What got left where?
> How do I recover?  What bits are in my tree, and what bits
> are in the Index, and what bits are in the Object store now?

The good news is, I don't think there's anything to recover. It refused to 
write the new head, because it wasn't valid yet.

Actually, the fact that it even left it as a head might cause problems 
(because now you have a reference to something that doesn't exist), so you 
are probably best off just removing the .git/refs/heads/origin.remote file 
entirely. 

You just need to try again when the mirroring is doing better.

Oh. And I think you might want to change that "rsync:" to "http:" instead. 
It's going to be slower, but at least git-http-fetch should be more 
careful, since it's fetching one object at a time, and validating what it 
fetches that way. The rsync: protocol just does everything totally blidly 
(which makes it fairly efficient, but also means that when things go 
wrong, they are _really_ confusing).

		Linus

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-22 19:12 Please undo "Use git-merge instead of git-resolve in Jon Loeliger
@ 2005-09-22 21:22 ` Linus Torvalds
  2005-09-22 21:37   ` Linus Torvalds
  0 siblings, 1 reply; 22+ messages in thread
From: Linus Torvalds @ 2005-09-22 21:22 UTC (permalink / raw
  To: Jon Loeliger; +Cc: git



On Thu, 22 Sep 2005, Jon Loeliger wrote:
>
> > For example, you can do that with
> >
> >	git fetch linus master:linus
> >
> > which says: "fetch the branch 'master' from the repository described by 
> > 'linus' (.git/remotes/linus) into _my_ branch 'linus'".
> 
> Just to be clear on the overloaded use of "linus" here,
> let me rewrite that:
> 
> 	git fetch foo master:bar
> 
>     which says: "fetch the branch 'master' from the repository described
>     by 'foo' (.git/remotes/foo) into _my_ branch 'bar'".
> 
> Right?

Right.

> OK.  I think I get it.  The concept you are trying to beat into
> my head is essentially the difference between a "complete" and
> an "incomplete" specifier.  If there is enough specification to
> fetch and merge into a branch, you can.  And there are a few
> different ways to do so:
> 
>     A) git fetch rsync:..../linus-2.6.git master:origin
> or 
>     B) git fetch linus master:linus
>        with just the URL bits in the .git/remotes
> or
>     C)	git fetch linus
>         with both URL and "Pull:" clauses in .git remotes
>             URL: rsync:..../linus2.6.git
> 	    Pull: master:linus

Absolutely.

Note that you can also override, so let's say that you have _both_ the
"URL:" and the "Pull:" line in your "remotes" file, the "pull" line is 
still just a default, so you could do

	git fetch linus other:myother

and it would now use the URL line, but since you specified the branch by
hand, it would ignore the default branch information, and instead fetch
the "other" branch from the remote site into the "myother" local branch.

> > Now, this is where "dirty" comes in. The merge will fail if you have 
> > changed any files that the merge wants to modify. So do a
> 
> D'oh.  This is what bites me.  Some of those diffs that
> come back to me in the linus tree are one that I originated
> and sent up stream in the first place.  To get those to
> wash-out with the merge, I will have had to have had those
> committed in my branch, right?

Yes. Then git will merge them for you automatically (if they are 
identical), or may ask you to fix up any merge rejects (if there are 
clashes). 

Now, the fixing up any merges is pretty much exactly the same as under 
CVS - you'll get the same "<<<<" "====" ">>>>" markers.

>			  Otherwise they just look
> like dirty files -- never mind that they are (should be)
> the exact same bits coming back at me.

Right, but git doesn't know, and is too lazy to check. 

I _considered_ allowing a dirty file that happened to match the end 
result, but I never felt it was worth the complexity. It's nasty. And if 
it doesn't match, you really can't merge, because it's too dangerous to 
overwrite the users changes (even if you use some three-way merge and 
leave the rejects there).

> I want to return to this for one last comment:
> 
>     > You can make your .git/remotes/linus file look like this instead:
>     >
>     >	URL: rsync:..../linus2.6.git
>     >	Pull: master:linus
> 
> So, philosophically perhaps, there are several different
> reasons for having branches within a repository.  One of
> them is to track external repositories as indicated above.

Yes.

> But no-one (ie, no tool) currently constructs the .git/remotes
> files to have that layout, right?

The "git clone" thing will construct the original "origin" file to that 
layout. That's fairly recent, though.

And I think "cg-branch" will do it these days - and that's very much the
intent.  Havign porcelain on top of git that hides this thing so that you
don't have to edit configuration files by hand.

(Don't get me wrong: I think it's wonderful to have ASCII configuration 
files that you _can_ edit by hand, and it's the UNIX way of doing things, 
but I also think it's great to have front-end tools that allow doing these 
things without even having to understand the config file syntax etc).

		Linus

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-22 21:22 ` Linus Torvalds
@ 2005-09-22 21:37   ` Linus Torvalds
  2005-09-22 21:57     ` Daniel Barkalow
  0 siblings, 1 reply; 22+ messages in thread
From: Linus Torvalds @ 2005-09-22 21:37 UTC (permalink / raw
  To: Jon Loeliger; +Cc: git



On Thu, 22 Sep 2005, Linus Torvalds wrote:
> 
> Now, the fixing up any merges is pretty much exactly the same as under 
> CVS - you'll get the same "<<<<" "====" ">>>>" markers.

I should have continued this. 

What you do is you just edit the end result to be what it should be 
(exactly as under CVS), and then you do "git commit --all" to commit the 
manual merge.

NOTE NOTE NOTE! This is one case where if you had dirty state in your tree
before the merge, that you need to be careful. In that case you obviously
must NOT use "--all", since that will commit all the dirty state - both
your old dirty state _and_ your manual merge resolve. So if you had other 
changes in your tree that you don't want to commit, you need to do

	git commit <list manually merged files individually here>

so that it doesn't commit anything else. 

Oh. And while preparing the merge, you can use

	git diff

to see what the manual part was: the automated part of the merge will have
updated index for the automatic side, so this will _not_ show the part 
of the merge that was done automatically for you.

Or, of you want to see _everything_ the merge has done, just do

	git diff HEAD

to see what the _total_ diff from your pre-merge head was to what is now
in your tree. But that will be the diff for what you're merging - so it
can be _huge_ if you're pulling my tree and merging everything I've
accepted over the last week or two.

And if the merge ends up being too complex, and you decide that you need 
help and want to undo the partial merge entirely and not even try to fix 
it up, do

	git reset --hard

which will roll back the index and the working tree to your old HEAD (BUT 
LOOK OUT! IT WILL ALSO DESTROY ANY DIRTY STATE YOU HAD BEFORE THE MERGE!).

Basically: having dirty state in your tree and then ending up having to do 
a manual merge is a big pain. Not worth it. I just keep really small dirty 
stuff so that I don't mind blowing it away if I need to.

		Linus

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-22 21:37   ` Linus Torvalds
@ 2005-09-22 21:57     ` Daniel Barkalow
  2005-09-22 22:05       ` Linus Torvalds
  0 siblings, 1 reply; 22+ messages in thread
From: Daniel Barkalow @ 2005-09-22 21:57 UTC (permalink / raw
  To: Linus Torvalds; +Cc: Jon Loeliger, git

On Thu, 22 Sep 2005, Linus Torvalds wrote:

> Basically: having dirty state in your tree and then ending up having to do 
> a manual merge is a big pain. Not worth it. I just keep really small dirty 
> stuff so that I don't mind blowing it away if I need to.

Would it be worthwhile to have a flag to make git-read-tree abort rather 
than making a mess if you have any dirty state and the merge isn't 
completely automatic? It's certainly easy enough to write.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-22 21:57     ` Daniel Barkalow
@ 2005-09-22 22:05       ` Linus Torvalds
  2005-09-23  8:33         ` [PATCH] Fix overzealous cleanliness check in git-merge Junio C Hamano
  2005-09-23  9:01         ` [PATCH] Use git-merge in git-pull (second try) Junio C Hamano
  0 siblings, 2 replies; 22+ messages in thread
From: Linus Torvalds @ 2005-09-22 22:05 UTC (permalink / raw
  To: Daniel Barkalow; +Cc: Jon Loeliger, git



On Thu, 22 Sep 2005, Daniel Barkalow wrote:
> 
> Would it be worthwhile to have a flag to make git-read-tree abort rather 
> than making a mess if you have any dirty state and the merge isn't 
> completely automatic? It's certainly easy enough to write.

I don't think it would be wrong, necessarily.

On the other hand, it might be easier to just instead do a 

	git diff HEAD > .git/pre-merge-diff

and let it go at that. If the merge ends up being nasty, you can then just 
do

	git reset --hard
	git-apply .git/pre-merge-diff

or something.

I dunno. This is not something that has caused me a lot of headache. I 
certainly _hope_ that people generally don't keep a lot of dirty state 
around: I do it for truly small stuff that I don't care about.

Let's face it - if I cared about it, I'd have committed it (possibly to
another branch). It's not like that's hard. So the dirty stuff really does 
tend to be only trivial things.

		Linus

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-22 19:25     ` Sean
@ 2005-09-22 22:22       ` Junio C Hamano
       [not found]         ` <55917.10.10.10.28.1127429674.squirrel@linux1>
  0 siblings, 1 reply; 22+ messages in thread
From: Junio C Hamano @ 2005-09-22 22:22 UTC (permalink / raw
  To: Sean; +Cc: git

"Sean" <seanlkml@sympatico.ca> writes:

> Why doesn't cogito just use the git fetch/pull commands?   Why does it
> need anything special?   It seems like cogito is doing more than just
> being an ease-of-use layer above git.

The way this question is posed is quite unfair to Pasky -- it
makes him look needlessly bad.

The simple reason is because Cogito had its own richer
fetch/pull first.  The development of git aware pack transfer
protocols by Linus and the list discussion for multi-head pushes
and pulls came much later, which resulted in the current 'git
fetch/pull' interface.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
       [not found]         ` <55917.10.10.10.28.1127429674.squirrel@linux1>
@ 2005-09-22 22:54           ` Sean
  0 siblings, 0 replies; 22+ messages in thread
From: Sean @ 2005-09-22 22:54 UTC (permalink / raw
  To: Junio C Hamano; +Cc: git

On Thu, September 22, 2005 6:22 pm, Junio C Hamano said:
> "Sean" <seanlkml@sympatico.ca> writes:
>
>> Why doesn't cogito just use the git fetch/pull commands?   Why does it
>> need anything special?   It seems like cogito is doing more than just
>> being an ease-of-use layer above git.
>
> The way this question is posed is quite unfair to Pasky -- it
> makes him look needlessly bad.

Will try to pose it differently then, because it was not meant to make him
"look bad".  In a different email Pasky seemed to be musing that cogito
might do away with fast forward merges.  This too seemed like a decision
best left to the plumbing, so i have been wondering how Pasky views
cogito's relationship to git.

But the immediate question really was, wouldn't it be better if cogito
used the same code paths that git uses for push/pull/fetch?  Is there a
reason that this isn't possible?

> The simple reason is because Cogito had its own richer
> fetch/pull first.  The development of git aware pack transfer
> protocols by Linus and the list discussion for multi-head pushes
> and pulls came much later, which resulted in the current 'git
> fetch/pull' interface.

Yes, cogito had it first but once this functionality gets pushed down into
git (where it's been for a while now) it makes a lot of sense for the
procelain layers to use it.   That way the functionality only has to be
maintained in one place and nobody has to guess what transports work with
cogito or git etc.  But perhaps there are reasons that this just isn't
possible with the cogito code, i dunno.

Sean

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH] Fix overzealous cleanliness check in git-merge
  2005-09-22 22:05       ` Linus Torvalds
@ 2005-09-23  8:33         ` Junio C Hamano
  2005-09-23  9:01         ` [PATCH] Use git-merge in git-pull (second try) Junio C Hamano
  1 sibling, 0 replies; 22+ messages in thread
From: Junio C Hamano @ 2005-09-23  8:33 UTC (permalink / raw
  To: Linus Torvalds; +Cc: git

Being able to try multiple strategies and automatically picking one
that seems to give less conflicting result may or may not much sense
in practice.  At least that should not force normal use case to
additionally require the working tree to be fully clean.  As Linus
shouted, local changes do not matter unless they interfere with the
merge.

This commit changes git-merge not to require a clean working tree.
Only when we will iterate through more than one merge strategies,
local changes are stashed away before trying the first merge, and
restored before second and later merges are attempted.

The index file must be in sync with HEAD in any case -- otherwise the
merge result would contain changes since HEAD that was done locally
and registered in the index.  This check is already enforced by
three-way read-tree existing merge strategies use, but is done here as
a safeguard as well.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

 Taking hint from your message, here is an attempt to fix the
 'incredibly broken' git-merge.  This does not make git-pull
 use it yet.

 git-merge.sh |   65 ++++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 49 insertions(+), 16 deletions(-)

abfefa19cf56a312d571ea36a491152ac7aef657
diff --git a/git-merge.sh b/git-merge.sh
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -18,8 +18,19 @@ all_strategies='recursive octopus resolv
 default_strategies='resolve octopus'
 use_strategies=
 
-dropheads() {
-	rm -f -- "$GIT_DIR/MERGE_HEAD" || exit 1
+dropsave() {
+	rm -f -- "$GIT_DIR/MERGE_HEAD" \
+		 "$GIT_DIR/MERGE_SAVE" || exit 1
+}
+
+savestate() {
+	git diff -r -z --name-only $head | cpio -0 -o >"$GIR_DIR/MERGE_SAVE"
+}
+
+restorestate() {
+	git reset --hard $head
+	cpio -iuv <"$GIT_DIR/MERGE_SAVE"
+	git-update-index --refresh >/dev/null
 }
 
 summary() {
@@ -92,7 +103,7 @@ case "$#,$common" in
 	# If head can reach all the merge then we are up to date.
 	# but first the most common case of merging one remote
 	echo "Already up-to-date. Yeeah!"
-	dropheads
+	dropsave
 	exit 0
 	;;
 1,"$head")
@@ -102,7 +113,7 @@ case "$#,$common" in
 	git-read-tree -u -m $head "$1" || exit 1
 	git-rev-parse --verify "$1^0" > "$GIT_DIR/HEAD"
 	summary "$1"
-	dropheads
+	dropsave
 	exit 0
 	;;
 1,*)
@@ -124,29 +135,51 @@ case "$#,$common" in
 	if test "$up_to_date" = t
 	then
 		echo "Already up-to-date. Yeeah!"
-		dropheads
+		dropsave
 		exit 0
 	fi
 	;;
 esac
 
-# At this point we need a real merge.  Require that the tree matches
-# exactly our head.
 
-git-update-index --refresh &&
-test '' = "`git-diff-index --cached --name-only $head`" || {
-	die "Need real merge but the working tree has local changes."
-}
+# At this point, we need a real merge.  No matter what strategy
+# we use, it would operate on the index, possibly affecting the
+# working tree, and when resolved cleanly, have the desired tree
+# in the index -- this means that the index must be in sync with
+# the $head commit.
+files=$(git-diff-index --cached --name-only $head) || exit
+if [ "$files" ]; then
+   echo >&2 "Dirty index: cannot merge (dirty: $files)"
+   exit 1
+fi
+
+case "$use_strategies" in
+?*' '?*)
+    # Stash away the local changes so that we can try more than one.
+    savestate
+    single_strategy=no
+    ;;
+*)
+    single_strategy=yes
+    ;;
+esac
 
 result_tree= best_cnt=-1 best_strategy= wt_strategy=
 for strategy in $use_strategies
 do
     test "$wt_strategy" = '' || {
 	echo "Rewinding the tree to pristine..."
-	git reset --hard $head
+	restorestate
     }
-    echo "Trying merge strategy $strategy..."
+    case "$single_strategy" in
+    no)
+	echo "Trying merge strategy $strategy..."
+	;;
+    esac
+
+    # Remember which strategy left the state in the working tree
     wt_strategy=$strategy
+
     git-merge-$strategy $common -- $head "$@" || {
 
 	# The backend exits with 1 when conflicts are left to be resolved,
@@ -185,14 +218,14 @@ then
     echo "Committed merge $result_commit, made by $wt_strategy."
     echo $result_commit >"$GIT_DIR/HEAD"
     summary $result_commit
-    dropheads
+    dropsave
     exit 0
 fi
 
 # Pick the result from the best strategy and have the user fix it up.
 case "$best_strategy" in
 '')
-	git reset --hard $head
+	restorestate
 	die "No merge strategy handled the merge."
 	;;
 "$wt_strategy")
@@ -200,7 +233,7 @@ case "$best_strategy" in
 	;;
 *)
 	echo "Rewinding the tree to pristine..."
-	git reset --hard $head
+	restorestate
 	echo "Using the $best_strategy to prepare resolving by hand."
 	git-merge-$best_strategy $common -- $head "$@"
 	;;

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH] Use git-merge in git-pull (second try).
  2005-09-22 22:05       ` Linus Torvalds
  2005-09-23  8:33         ` [PATCH] Fix overzealous cleanliness check in git-merge Junio C Hamano
@ 2005-09-23  9:01         ` Junio C Hamano
  1 sibling, 0 replies; 22+ messages in thread
From: Junio C Hamano @ 2005-09-23  9:01 UTC (permalink / raw
  To: Linus Torvalds; +Cc: git

This again makes git-pull to use git-merge, so that different merge
strategy can be specified from the command line.  Without explicit
strategy parameter, it defaults to git-merge-resolve if only one
remote is pulled, and git-merge-octopus otherwise, to keep the
default behaviour of the command the same as the original.

Also this brings another usability measure: -n flag from the command
line, if given, is passed to git-merge to prevent it from running the
diffstat at the end of the merge.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

 I tested this at least once with a dirty working tree ;-).  The
 main difference from the one that was backed out is that only
 one strategy is used by default -- this is to avoid any
 'stashing away old states' done on the git-merge side.

 git-pull.sh |   48 ++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 44 insertions(+), 4 deletions(-)

9c078a16523a2aae224a99e70f41eeb3d05a470c
diff --git a/git-pull.sh b/git-pull.sh
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -6,6 +6,38 @@
 
 . git-sh-setup || die "Not a git archive"
 
+usage () {
+    die "git pull [-n] [-s strategy]... <repo> <head>..."
+}
+
+strategy_args= no_summary=
+while case "$#,$1" in 0) break ;; *,-*) ;; *) break ;; esac
+do
+	case "$1" in
+	-n|--n|--no|--no-|--no-s|--no-su|--no-sum|--no-summ|\
+		--no-summa|--no-summar|--no-summary)
+		no_summary=-n ;;
+	-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
+		--strateg=*|--strategy=*|\
+	-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
+		case "$#,$1" in
+		*,*=*)
+			strategy=`expr "$1" : '-[^=]*=\(.*\)'` ;;
+		1,*)
+			usage ;;
+		*)
+			strategy="$2"
+			shift ;;
+		esac
+		strategy_args="${strategy_args}-s $strategy "
+		;;
+	-*)
+		usage
+		;;
+	esac
+	shift
+done
+
 orig_head=$(cat "$GIT_DIR/HEAD") || die "Pulling into a black hole?"
 git-fetch --update-head-ok "$@" || exit 1
 
@@ -31,11 +63,19 @@ case "$merge_head" in
 	echo >&2 "No changes."
 	exit 0
 	;;
-*' '?*)
-	echo >&2 "Pulling more than one heads; making an Octopus."
-	exec git-octopus
+?*' '?*)
+	strategy_default_args='-s octopus'
+	;;
+*)
+	strategy_default_args='-s resolve'
+	;;
+esac
+
+case "$strategy_args" in
+'')
+	strategy_args=$strategy_default_args
 	;;
 esac
 
 merge_name=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD")
-git-resolve "$(cat "$GIT_DIR"/HEAD)" $merge_head "$merge_name"
+git-merge $no_summary $strategy_args "$merge_name" HEAD $merge_head

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
       [not found]   ` <34462.10.10.10.28.1127417134.squirrel@linux1>
  2005-09-22 19:25     ` Sean
@ 2005-09-23  9:10     ` Petr Baudis
  2005-09-23  9:34       ` Junio C Hamano
  1 sibling, 1 reply; 22+ messages in thread
From: Petr Baudis @ 2005-09-23  9:10 UTC (permalink / raw
  To: Sean; +Cc: Jon Loeliger, git

Dear diary, on Thu, Sep 22, 2005 at 09:25:34PM CEST, I got a letter
where Sean <seanlkml@sympatico.ca> told me that...
> On Thu, September 22, 2005 3:10 pm, Petr Baudis said:
> 
> > FWIW, with Cogito, interrupted or failed fetch can be safely rerun, no
> > extra recovery procedure is required. It *seems* that this holds for
> > git-fetch as well.
> 
> Petr,
> 
> Why doesn't cogito just use the git fetch/pull commands?   Why does it
> need anything special?   It seems like cogito is doing more than just
> being an ease-of-use layer above git.

As Junio already explained, Cogito had those commands earlier - so the
main reason was simply that I didn't manage to do it yet. It is not so
easy to keep up with the latest GIT stuff _and_ enhance Cogito at the
same time, so I simply didn't get to really consider that yet. :-)

That said, this is a non-comprehensive list of the factors in my
consideration:

Pros (not so much of them, but they are big):
	* Already supports alternates and remotes
	* Do it once, stop caring :-) - only single instance of the code
	  does the stuff (this is obviously the motivation)

Cons:
	* cg-fetch can do with symlinked object database
	* cg-fetch will hardlink if possible when fetching locally
	* cg-fetch will fetch the tags if possible
		(this is actually a bit controversial - we should have
		the private/public tags distinction, that's another
		thing I simply didn't get to yet)
	* cg-fetch has cute progress info
		(perhaps git-fetch output could be just fed to that)
	* cg-fetch won't do useless fetches when we are already
	  up-to-date
	* I'm not sure if I could call git-fetch to do the initial
	  fetch during clone
	* The amount of work to initially convert it might be comparable
	  with implementing the current new stuff
	* I really dislike the git-fetch coding style
		This is not that I'd like to force my coding style
		customs on anyone and Junio might well feel the same
		about Cogito's code, but I would have to support and
		fix bugs in git-fetch if I used it.
	* I'm obviously not too happy to throw away the rather big
	  amount of code I spent a lot of time on and which is already
	  pretty well debugged and tuned, I think (that's not to say
	  that git-fetch is buggy... ;-)

The cons may seem mostly minor stuff which is quite fixable, and that's
right, it's just show that there is plenty of stuff to do before
git-fetch will be superset of cg-fetch. Now because of the coding style,
I might as well just implement the alternates and remotes stuff to
cg-fetch, which would be less work and less painful for me in the short
term.

I'll convert cg-object-id to use git-rev-parse after the release so that
you can't say I'm an old-fashioned freak refusing to use any of the new
GIT stuff. :^)

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
VI has two modes: the one in which it beeps and the one in which
it doesn't.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-23  9:10     ` Petr Baudis
@ 2005-09-23  9:34       ` Junio C Hamano
  2005-09-23  9:57         ` Petr Baudis
  0 siblings, 1 reply; 22+ messages in thread
From: Junio C Hamano @ 2005-09-23  9:34 UTC (permalink / raw
  To: Petr Baudis; +Cc: git

Petr Baudis <pasky@suse.cz> writes:

> 	* cg-fetch can do with symlinked object database

Do you mean ".git/object" in the repository you are fetching
into is a symlink to somewhere, or something else?

> 	* cg-fetch will hardlink if possible when fetching locally

True, git-fetch and git-clone try to use pack protocols by
default, which is debatable.  Adding -l (similar to what
git-clone does) would not be too hard, if enough people want
it.

> 	* cg-fetch won't do useless fetches when we are already
> 	  up-to-date

Care to explain?  Perhaps you are talking about rsync transport
(in which case I would not be surprised)?

> 	* I'm not sure if I could call git-fetch to do the initial
> 	  fetch during clone

    $ git-init-db && git fetch http://kernel.org/pub/scm/git/git.git

should work.

There is another minor "con", if you include git-clone in the
discussion.  Over http transport, it refuses to run against a
remote repository that does not have info/refs and info/packs,
even if it is not packed.  I think cg-clone uses recursive wget
for directory traversal and does not have to use them.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-23  9:34       ` Junio C Hamano
@ 2005-09-23  9:57         ` Petr Baudis
  2005-09-23 21:07           ` Daniel Barkalow
  2005-09-24  6:19           ` Junio C Hamano
  0 siblings, 2 replies; 22+ messages in thread
From: Petr Baudis @ 2005-09-23  9:57 UTC (permalink / raw
  To: Junio C Hamano; +Cc: git

Dear diary, on Fri, Sep 23, 2005 at 11:34:16AM CEST, I got a letter
where Junio C Hamano <junkio@cox.net> told me that...
> Petr Baudis <pasky@suse.cz> writes:
> 
> > 	* cg-fetch can do with symlinked object database
> 
> Do you mean ".git/object" in the repository you are fetching
> into is a symlink to somewhere, or something else?

Yes, exactly that. You get it by doing cg-clone -l /local/path.  O(1)
cloning, but it has its downsides and dangers which I tried to describe
in the cg-clone documentation.

> > 	* cg-fetch won't do useless fetches when we are already
> > 	  up-to-date
> 
> Care to explain?  Perhaps you are talking about rsync transport
> (in which case I would not be surprised)?

Just that if the reference pointer did not change, you don't try to pull
any objects. Speeds things up somewhat, and now it should always work
(well, cg-fetch has -f which makes it always try objects as well, in
case something went wrong anyway).

> > 	* I'm not sure if I could call git-fetch to do the initial
> > 	  fetch during clone
> 
>     $ git-init-db && git fetch http://kernel.org/pub/scm/git/git.git
> 
> should work.

Good.

> There is another minor "con", if you include git-clone in the
> discussion.  Over http transport, it refuses to run against a
> remote repository that does not have info/refs and info/packs,
> even if it is not packed.  I think cg-clone uses recursive wget
> for directory traversal and does not have to use them.

cg-clone just basically does cg-init && cg-fetch, and I'd really want to
keep it on that. So effectively, cg-clone over http just runs
git-http-fetch and trusts it to do the right thing (reasonably fast).

Recursive wget is used only for fetching tags (and it actually seems to
work nicely, when directory listing is enabled, obviously). Yes, I
should teach cg-fetch about info/refs too.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
VI has two modes: the one in which it beeps and the one in which
it doesn't.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
@ 2005-09-23 13:51 Jon Loeliger
  0 siblings, 0 replies; 22+ messages in thread
From: Jon Loeliger @ 2005-09-23 13:51 UTC (permalink / raw
  To: git



>> (This is an intentional asymmetry, right?  Distributed systems, right?)
>
>Right. It's intentional. The "master" branch tends to be the main one for
>everybody, but _my_ "master" branch is clearly _your_ "linus" branch, and
>_your_ "master" branch would be the "jon" branch for me.

OK, I'm being clued slowly... :-)

>So it's not "asymmetric". It _is_ symmetric, but it's symmetric the same
>way "left" and "right" are symmetric when facing each other - my left is
>your right, your left is my right. It's a symmetry, but it's not an 
>_identity_.

Ah, right.  I mis-spoke myself, I see. :-)

> What does
>
>	git-cat-file -t 3fd07d3bf0077dcc0f5a33d2eb1938ea050da8da

It used to be nothing at all.  It is now (after another fetch)
a commit.  And, it did leave this:

    jdl.com 231 % cat .git/refs/heads/origin.remote
    3fd07d3bf0077dcc0f5a33d2eb1938ea050da8da


> Actually, the fact that it even left it as a head might
> cause problems (because now you have a reference to something
> that doesn't exist), so you are probably best off just removing
> the .git/refs/heads/origin.remote file entirely.

Excellent.

<aside stage=left>
IMO, one of the things that distinguishes those "who get git"
and those who don't yet git it, are the ones who can casually
toss out phrases like, "Oh, you don't need that, just rm it."
The rest of us sit around and ponder "Do I need _that_ data?
How do I know I can toss it?  If I toss it, what will be lost
with it?  But if I revert the index, I lose... _it_, right?"

There is a certain amount of opacity to Git and its Object
store that makes it a bit scary.  And, at least for me, as
a result I am a bit reluctant to go wildly experimenting.
With more certainty as to "recovering from badness", I'll
be more familiar and more willing to experiment, I'm sure.
</aside>

Things are better, I've now been able to:

    * committish: e484585ec3ee66cd07a627d3a9e2364640a3807f
      branch 'master' of rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
    * refs/heads/origin: fast forward to branch 'master' of rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6


Thanks for your help!

jdl

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-23  9:57         ` Petr Baudis
@ 2005-09-23 21:07           ` Daniel Barkalow
  2005-09-24  6:19           ` Junio C Hamano
  1 sibling, 0 replies; 22+ messages in thread
From: Daniel Barkalow @ 2005-09-23 21:07 UTC (permalink / raw
  To: Petr Baudis; +Cc: Junio C Hamano, git

On Fri, 23 Sep 2005, Petr Baudis wrote:

> Dear diary, on Fri, Sep 23, 2005 at 11:34:16AM CEST, I got a letter
> where Junio C Hamano <junkio@cox.net> told me that...
> > Petr Baudis <pasky@suse.cz> writes:
> > 
> > > 	* cg-fetch can do with symlinked object database
> > 
> > Do you mean ".git/object" in the repository you are fetching
> > into is a symlink to somewhere, or something else?
> 
> Yes, exactly that. You get it by doing cg-clone -l /local/path.  O(1)
> cloning, but it has its downsides and dangers which I tried to describe
> in the cg-clone documentation.

That's actually how I use git, and it works for me. (To be precise, I 
have:

 ~/git/project.git/{objects,refs,info}

and I have

 ~/working/git/current-work/, with .git/{objects,refs,info} symlinks to 
                              the above.

git fetch works fine, with the exception that remotes aren't shared 
between working trees.

> > > 	* cg-fetch won't do useless fetches when we are already
> > > 	  up-to-date
> > 
> > Care to explain?  Perhaps you are talking about rsync transport
> > (in which case I would not be surprised)?
> 
> Just that if the reference pointer did not change, you don't try to pull
> any objects. Speeds things up somewhat, and now it should always work
> (well, cg-fetch has -f which makes it always try objects as well, in
> case something went wrong anyway).

I assume you mean with rsync? The current git-http-fetch won't try any 
objects if the ref didn't change (or, for that matter, if we have a 
different ref that's the same), and the old one would make a local check 
for the objects before trying to downlaod anything.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Please undo "Use git-merge instead of git-resolve in
  2005-09-23  9:57         ` Petr Baudis
  2005-09-23 21:07           ` Daniel Barkalow
@ 2005-09-24  6:19           ` Junio C Hamano
  1 sibling, 0 replies; 22+ messages in thread
From: Junio C Hamano @ 2005-09-24  6:19 UTC (permalink / raw
  To: Petr Baudis; +Cc: git

Petr Baudis <pasky@suse.cz> writes:

> Dear diary, on Fri, Sep 23, 2005 at 11:34:16AM CEST, I got a letter
> where Junio C Hamano <junkio@cox.net> told me that...
>> Petr Baudis <pasky@suse.cz> writes:
>> 
>> > 	* cg-fetch can do with symlinked object database
>> 
>> Do you mean ".git/object" in the repository you are fetching
>> into is a symlink to somewhere, or something else?
>
> Yes, exactly that. You get it by doing cg-clone -l
> /local/path.

git-clone -l -s does optimization similar to that in spirit, but
it does not create a repository with symlinked .git/object
pointing at /some/where/original/repo/.git/object.  Instead it
uses alternates to borrow from the other; newly created objects
are always stored locally.

But I thought you were talking about fetch.  git-fetch should be
able to pull into a repository whose .git/object happens to be a
symlink pointing at somewhere else just fine.

> Just that if the reference pointer did not change, you don't try to pull
> any objects.

Both git-aware protocol and commit walker peek at the remote ref
and stop without downloading objects if it is known to us, so I
think we are OK.

>>     $ git-init-db && git fetch http://kernel.org/pub/scm/git/git.git
>> 
>> should work.
>
> Good.

Of course, the above 'git fetch' only fetches remote HEAD and
stores it in .git/FETCH_HEAD; if you truly want to 'clone', you
could first run git-ls-remote to peek the remote refs and then
give them as storing refspecs to git fetch, doing something like
this (modulo renaming 'master' over there to 'origin' here):

	mkdir foo && cd foo && git-init-db
	refspec=$(git-ls-remote $repo | \
	        sed -n -e 's/^[0-9a-f]*	//' -e 's|refs/.*|&:&|p')
	git fetch $repo $refspec

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2005-09-24  6:19 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-22 19:12 Please undo "Use git-merge instead of git-resolve in Jon Loeliger
2005-09-22 21:22 ` Linus Torvalds
2005-09-22 21:37   ` Linus Torvalds
2005-09-22 21:57     ` Daniel Barkalow
2005-09-22 22:05       ` Linus Torvalds
2005-09-23  8:33         ` [PATCH] Fix overzealous cleanliness check in git-merge Junio C Hamano
2005-09-23  9:01         ` [PATCH] Use git-merge in git-pull (second try) Junio C Hamano
  -- strict thread matches above, loose matches on Subject: below --
2005-09-23 13:51 Please undo "Use git-merge instead of git-resolve in Jon Loeliger
2005-09-22 18:32 Jon Loeliger
2005-09-22 19:10 ` Petr Baudis
     [not found]   ` <34462.10.10.10.28.1127417134.squirrel@linux1>
2005-09-22 19:25     ` Sean
2005-09-22 22:22       ` Junio C Hamano
     [not found]         ` <55917.10.10.10.28.1127429674.squirrel@linux1>
2005-09-22 22:54           ` Sean
2005-09-23  9:10     ` Petr Baudis
2005-09-23  9:34       ` Junio C Hamano
2005-09-23  9:57         ` Petr Baudis
2005-09-23 21:07           ` Daniel Barkalow
2005-09-24  6:19           ` Junio C Hamano
2005-09-22 21:12 ` Linus Torvalds
2005-09-22 14:55 Jon Loeliger
2005-09-22 16:01 ` Petr Baudis
2005-09-22 16:06 ` Linus Torvalds

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).