# Re: Please undo "Use git-merge instead of git-resolve in

3 messages from 2005-09-22 to 2005-09-22. Participants: Jon Loeliger, Petr Baudis, Linus Torvalds.
Thread: https://gitlist.dev/t/1913

## Jon Loeliger, 2005-09-22 14:55

Subject: Re: Please undo "Use git-merge instead of git-resolve in
Message-ID: <E1EISTu-0000MI-Gz@jdl.com>
URL: https://gitlist.dev/e/E1EISTu-0000MI-Gz%40jdl.com

```
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.

```

## Petr Baudis, 2005-09-22 16:01

Subject: Re: Please undo "Use git-merge instead of git-resolve in
Message-ID: <20050922160113.GL21019@pasky.or.cz>
URL: https://gitlist.dev/e/20050922160113.GL21019%40pasky.or.cz
In-Reply-To: <E1EISTu-0000MI-Gz@jdl.com>

```
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.

```

## Linus Torvalds, 2005-09-22 16:06

Subject: Re: Please undo "Use git-merge instead of git-resolve in
Message-ID: <Pine.LNX.4.58.0509220826460.2553@g5.osdl.org>
URL: https://gitlist.dev/e/Pine.LNX.4.58.0509220826460.2553%40g5.osdl.org
In-Reply-To: <E1EISTu-0000MI-Gz@jdl.com>

```


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

```
