git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Files different for me
@ 2009-02-25 16:11 John Dlugosz
       [not found] ` <16946e800902250840o677f8708x7c0bf8980e004b91@mail.gmail.com>
                   ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: John Dlugosz @ 2009-02-25 16:11 UTC (permalink / raw)
  To: git

I'm working with a group, and using git for source code.  I need to change a couple files temporarily and just for me.  I thought, "that's easy", just don't stage them when I check in changes.  But, what do I do when I pull changes from others?  I think it will complain that I have unsaved changes.
What's the best way to do this?

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

* Re: Files different for me
       [not found] ` <16946e800902250840o677f8708x7c0bf8980e004b91@mail.gmail.com>
@ 2009-02-25 16:42   ` Feanil Patel
  0 siblings, 0 replies; 17+ messages in thread
From: Feanil Patel @ 2009-02-25 16:42 UTC (permalink / raw)
  To: git

You could use 'git stash' to stash the changes away for later use.
Then when you want them you can 'git stash apply' them later.

-Feanil

On Wed, Feb 25, 2009 at 10:11 AM, John Dlugosz
<JDlugosz@tradestation.com> wrote:
>
> I'm working with a group, and using git for source code.  I need to change a couple files temporarily and just for me.  I thought, "that's easy", just don't stage them when I check in changes.  But, what do I do when I pull changes from others?  I think it will complain that I have unsaved changes.
> What's the best way to do this?
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: Files different for me
  2009-02-25 16:11 Files different for me John Dlugosz
       [not found] ` <16946e800902250840o677f8708x7c0bf8980e004b91@mail.gmail.com>
@ 2009-02-25 17:05 ` Brian Gernhardt
  2009-02-25 18:02   ` John Dlugosz
  2009-02-25 17:55 ` Junio C Hamano
  2009-02-25 18:04 ` Linus Torvalds
  3 siblings, 1 reply; 17+ messages in thread
From: Brian Gernhardt @ 2009-02-25 17:05 UTC (permalink / raw)
  To: John Dlugosz; +Cc: git


On Feb 25, 2009, at 11:11 AM, John Dlugosz wrote:

> I'm working with a group, and using git for source code.  I need to  
> change a couple files temporarily and just for me.  I thought,  
> "that's easy", just don't stage them when I check in changes.  But,  
> what do I do when I pull changes from others?  I think it will  
> complain that I have unsaved changes.
> What's the best way to do this?

Generally when I keep changes like this, I make a commit called "Local  
Changes" or similar and have branch.master.rebase set to true so that  
my changes get rebased on top of origin when I pull.

~~ Brian

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

* Re: Files different for me
  2009-02-25 16:11 Files different for me John Dlugosz
       [not found] ` <16946e800902250840o677f8708x7c0bf8980e004b91@mail.gmail.com>
  2009-02-25 17:05 ` Brian Gernhardt
@ 2009-02-25 17:55 ` Junio C Hamano
  2009-02-25 18:04 ` Linus Torvalds
  3 siblings, 0 replies; 17+ messages in thread
From: Junio C Hamano @ 2009-02-25 17:55 UTC (permalink / raw)
  To: John Dlugosz; +Cc: git

"John Dlugosz" <JDlugosz@TradeStation.com> writes:

> I'm working with a group, and using git for source code.  I need to
> change a couple files temporarily and just for me.  I thought, "that's
> easy", just don't stage them when I check in changes.  But, what do I do
> when I pull changes from others?  I think it will complain that I have
> unsaved changes.  What's the best way to do this?

[jc: Overlong lines wrapped]

This typically happens when a configuration file of some sort that *must*
be different in each work tree is tracked.

"git pull" and "git merge" do not care when you have local changes to
paths *and* the merge does not involve them, and errors out without
touching any files in your tree when the merge needs to touch them.  You
can safely deal with your local changes after seeing such an error.  This,
and because such a file tend to be modified much less often than the real
contents, means that:

 (1) you do not usually have to worry about this issue, and can keep your
     small local changes you do not mind losing around, and

 (2) when you have to recover, you can easily stash your changes away,
     redo the pull and unstash them.

If you want an "I do not have to think" solution, an easiest recipe to
follow would be:

    $ git stash
    $ git pull
    ... potentially resolve conflicts and make a merge commit ...
    $ git stash pop

But as described above, stash/stash pop are superfluous for most of the
time.

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

* RE: Files different for me
  2009-02-25 17:05 ` Brian Gernhardt
@ 2009-02-25 18:02   ` John Dlugosz
  2009-02-25 18:38     ` Brian Gernhardt
  2009-02-25 18:44     ` Matthieu Moy
  0 siblings, 2 replies; 17+ messages in thread
From: John Dlugosz @ 2009-02-25 18:02 UTC (permalink / raw)
  To: Brian Gernhardt; +Cc: git

> Generally when I keep changes like this, I make a commit called "Local

> Changes" or similar and have branch.master.rebase set to true so that

> my changes get rebased on top of origin when I pull.

That sounds ideal.  However, I don't understand the specific steps you
mention.  Looking in the help for git-config,

	branch.<name>.rebase

		When true, rebase the branch <name> on top of the
fetched branch, 
		instead of merging the default branch from the default
remote when 
		"git pull" is run. NOTE: this is a possibly dangerous
operation; 
		do not use it unless you understand the implications 
		(see git-rebase(1) for details).

So, assuming you are working on the "master" branch, this will rebase
the pulled content on top of the existing "master" rather than merging.
If my local changes are committed to "master" first, then this will take
all the commits from other developers that I don't already have in my
local copy and apply them on top of my existing (including Local
Changes).  But since those will now be different commits, what happens
next time?  Ah, "...which introduce the same textual changes..." so
that's covered in how rebase works.

But this will have Local Changes present, and different commits (with
the same textual changes) in my branch.  So what happens when I "push"?

	Oldstuff--A--B--C  remote
	       \
	        LC--X--Y  mine

LC is "Local Changes", X and Y are changes I made, and A, B, C are
changes from other developers.

After a fetch, I have:

	Oldstuff--LC--X--Y--A'--B'--C'  mine

So what happens when I "push"?

In any case, the whole point is that I don't want to publish LC.

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

* Re: Files different for me
  2009-02-25 16:11 Files different for me John Dlugosz
                   ` (2 preceding siblings ...)
  2009-02-25 17:55 ` Junio C Hamano
@ 2009-02-25 18:04 ` Linus Torvalds
  2009-02-25 18:51   ` Junio C Hamano
  3 siblings, 1 reply; 17+ messages in thread
From: Linus Torvalds @ 2009-02-25 18:04 UTC (permalink / raw)
  To: John Dlugosz; +Cc: git



On Wed, 25 Feb 2009, John Dlugosz wrote:
>
> I'm working with a group, and using git for source code.  I need to 
> change a couple files temporarily and just for me.  I thought, "that's 
> easy", just don't stage them when I check in changes.  But, what do I do 
> when I pull changes from others?  I think it will complain that I have 
> unsaved changes.

If your changes do not touch any of the files that the "git pull" updates, 
then everything is fine. The pull will just work, and your changes will 
still exists in your tree. This is not an accident - git was very much 
designed to work that way, because it's a common usage case for me.

I often have some trivial small changes in my tree (like a pending change 
to the top-level Makefile for the next version number that I just haven't 
committed yet - just a reminder to myself that I'm soon about to release 
another -rc). And I still want to continue to do "git pull" to fetch 
stuff, or even "git am -s" to apply patches.

HOWEVER. If the pull actually wants to modify a file that you have changed 
(ie that same file was changed in the remote), then "git pull" will fail 
gracefully after having done the fetch, saying something like

	Entry 'file-name' not uptodate. Cannot merge.

and at that point you have to decide whethe you want to commit the change, 
"stash" it, or just undo it. Or whether you don't want to do the merge 
yet because you're still working on your own changes, and don't want the 
distraction.

		Linus

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

* Re: Files different for me
  2009-02-25 18:02   ` John Dlugosz
@ 2009-02-25 18:38     ` Brian Gernhardt
  2009-02-25 19:01       ` John Dlugosz
  2009-02-25 18:44     ` Matthieu Moy
  1 sibling, 1 reply; 17+ messages in thread
From: Brian Gernhardt @ 2009-02-25 18:38 UTC (permalink / raw)
  To: John Dlugosz; +Cc: git


On Feb 25, 2009, at 1:02 PM, John Dlugosz wrote:

>> Generally when I keep changes like this, I make a commit called  
>> "Local
>> Changes" or similar and have branch.master.rebase set to true so that
>> my changes get rebased on top of origin when I pull.
>
> That sounds ideal.  However, I don't understand the specific steps you
> mention.  Looking in the help for git-config,

As Junio and Linus have pointed out, most pulls will ignore local  
changes,
so this is likely overkill unless your changes are in commonly changed  
files.

> So, assuming you are working on the "master" branch, this will rebase
> the pulled content on top of the existing "master" rather than  
> merging.
> If my local changes are committed to "master" first, then this will  
> take
> all the commits from other developers that I don't already have in my
> local copy and apply them on top of my existing (including Local
> Changes).  But since those will now be different commits, what happens
> next time?  Ah, "...which introduce the same textual changes..." so
> that's covered in how rebase works.

You can set branch.master.rebase with

   git config branch.master.rebase true

It actually works the other way.  Your changes will be rebased on top of
the work from other developers.

A--B--E--F  origin/master
     \
      C--D master

will become

A--B--E--F  origin/master
           \
            C'--D' master

I share most of my changes using format-patch and e-mail instead of
pushes, so I just don't generate patches for my unimportant changes.
For pushing, I'd suggest either working on new features in a different
branch ("topic" and "local" for example), or using "rebase -i" to move
your local changes to the top and using "push HEAD^".

~~ Brian

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

* Re: Files different for me
  2009-02-25 18:02   ` John Dlugosz
  2009-02-25 18:38     ` Brian Gernhardt
@ 2009-02-25 18:44     ` Matthieu Moy
  1 sibling, 0 replies; 17+ messages in thread
From: Matthieu Moy @ 2009-02-25 18:44 UTC (permalink / raw)
  To: John Dlugosz; +Cc: Brian Gernhardt, git

"John Dlugosz" <JDlugosz@TradeStation.com> writes:

> 	Oldstuff--A--B--C  remote
> 	       \
> 	        LC--X--Y  mine
>
> LC is "Local Changes", X and Y are changes I made, and A, B, C are
> changes from other developers.
>
> After a fetch, I have:
>
> 	Oldstuff--LC--X--Y--A'--B'--C'  mine

No, your changes get rebased:

 	Oldstuff--A--B--C--LC'--X'--Y'   mine

You should just be carrefull not to push in this state, since you'd
push LC too. But you can throw away LC later with "git rebase -i".

-- 
Matthieu

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

* Re: Files different for me
  2009-02-25 18:04 ` Linus Torvalds
@ 2009-02-25 18:51   ` Junio C Hamano
  2009-02-25 19:12     ` Linus Torvalds
                       ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Junio C Hamano @ 2009-02-25 18:51 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: John Dlugosz, git

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

> If your changes do not touch any of the files that the "git pull" updates, 
> then everything is fine. The pull will just work, and your changes will 
> still exists in your tree. This is not an accident - git was very much 
> designed to work that way, because it's a common usage case for me.
>
> I often have some trivial small changes in my tree (like a pending change 
> to the top-level Makefile for the next version number that I just haven't 
> committed yet - just a reminder to myself that I'm soon about to release 
> another -rc). And I still want to continue to do "git pull" to fetch 
> stuff, or even "git am -s" to apply patches.
>
> HOWEVER. If the pull actually wants to modify a file that you have changed 
> (ie that same file was changed in the remote), then "git pull" will fail 
> gracefully after having done the fetch, saying something like
>
> 	Entry 'file-name' not uptodate. Cannot merge.
>
> and at that point you have to decide whethe you want to commit the change, 
> "stash" it, or just undo it. Or whether you don't want to do the merge 
> yet because you're still working on your own changes, and don't want the 
> distraction.

I've been repeating the above to new people to save you time, but recently
I noticed one thing.

The handling of a case where a pull decides to go ahead (because it does
not have to touch the Makefile you have your codename updates in) but does
not complete with real conflicts, is not as graceful as the other two
cases (merge refusing to run at all without touching anything, or merge
completes cleanly and makes a commit).

You will be left with:

 - Paths that have local changes (index matches HEAD but work tree does
   not match the index --- like your Makefile);

 - Paths cleanly merged (index and HEAD are different but work tree
   already matches the index);

 - Unmerged paths (index has higher stage entries with <<</===/>>> files
   in the work tree);

You, I and experienced users know what to do.  Deal *only* with the last
kind, mark them with "git add" after you are done with each of them, and
make sure you do not say "-a" when committing the result, to exclude the
first kind from the merge result.

I've been wondering if we can make this safer for others.

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

* RE: Files different for me
  2009-02-25 18:38     ` Brian Gernhardt
@ 2009-02-25 19:01       ` John Dlugosz
  0 siblings, 0 replies; 17+ messages in thread
From: John Dlugosz @ 2009-02-25 19:01 UTC (permalink / raw)
  To: Brian Gernhardt; +Cc: git

Thanks for the clarification, and thanks all on the thread for
explaining things to me.
It appears that fetching with my local changes is not a problem.  For
going the other way, you suggest:

	For pushing, I'd suggest either working on new features in a
different
	branch ("topic" and "local" for example), or using "rebase -i"
to move
	your local changes to the top and using "push HEAD^".

I get the idea of floating "that" change to the top and using "push
HEAD^", though I've never tried --interactive so I'll have to play
around with that on a backup first.

I think if those changes are not committed, it won't be an issue.  

So, my plan at this point is to "stash" my Local Change, and then apply
it.  Then just keep it out of the index.  If I do get a conflict, I can
re-apply my change from the stashed copy.  


Ordinarily, I'll all about working on a feature on a branch, exposing a
"task based" system to other developers.  But, this particular change is
not isolated, and I'm adding parameter to functions and such (I'm
changing the way configuration works and making more things
configurable) all over the place.  I want to push stable work frequently
so other changes don't get too far away making a merge nightmare.

<rant>
Last time, I was careful to publish stable code frequently to the
official "dev" branch, but when another major feature was finished, they
just declared that branch to be the new main-line official branch.
</rant>


-----Original Message-----
From: Brian Gernhardt [mailto:benji@silverinsanity.com] 

You can set branch.master.rebase with

   git config branch.master.rebase true

It actually works the other way.  Your changes will be rebased on top of
the work from other developers.

A--B--E--F  origin/master
     \
      C--D master

will become

A--B--E--F  origin/master
           \
            C'--D' master

I share most of my changes using format-patch and e-mail instead of
pushes, so I just don't generate patches for my unimportant changes.
For pushing, I'd suggest either working on new features in a different
branch ("topic" and "local" for example), or using "rebase -i" to move
your local changes to the top and using "push HEAD^".

~~ Brian

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

* Re: Files different for me
  2009-02-25 18:51   ` Junio C Hamano
@ 2009-02-25 19:12     ` Linus Torvalds
  2009-02-25 20:06       ` Junio C Hamano
  2009-02-25 19:16     ` Jay Soffian
  2009-02-25 19:23     ` John Dlugosz
  2 siblings, 1 reply; 17+ messages in thread
From: Linus Torvalds @ 2009-02-25 19:12 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: John Dlugosz, git



On Wed, 25 Feb 2009, Junio C Hamano wrote:
>
> I've been repeating the above to new people to save you time, but recently
> I noticed one thing.
> 
> The handling of a case where a pull decides to go ahead (because it does
> not have to touch the Makefile you have your codename updates in) but does
> not complete with real conflicts, is not as graceful as the other two
> cases (merge refusing to run at all without touching anything, or merge
> completes cleanly and makes a commit).

I agree (although your phrasing was confusing - by "does not complete with 
real conflicts" you made it sound like there were no real conflicts, but 
you must have meant "does not actually finish the merge commit _due_ to 
real conflicts").

That case is one large part of why I wanted to have that "git reset 
--merge" behavior - because it's a good way to get back to the "pre-merge 
with dirty state" situation. Although I have to admit that I don't think 
I've had that happen since the feature got merged ;)

> You will be left with:
> 
>  - Paths that have local changes (index matches HEAD but work tree does
>    not match the index --- like your Makefile);
> 
>  - Paths cleanly merged (index and HEAD are different but work tree
>    already matches the index);
> 
>  - Unmerged paths (index has higher stage entries with <<</===/>>> files
>    in the work tree);

Yes. The good news is that for people who know what they are doing, this 
is all unambiguous. Clean merges will be up-to-date in the index, unmgered 
paths will be marked as such in the index, and your own _real_ dirty state 
will be unambioguously dirty in the working tree.

But I do agree that if you don't know what's up, you now are an in a 
really good position for screwing up, and (for example) resolving the 
merge conflict and then incorrectly committing your own unrelated changes 
with the merge.

> You, I and experienced users know what to do.  Deal *only* with the last
> kind, mark them with "git add" after you are done with each of them, and
> make sure you do not say "-a" when committing the result, to exclude the
> first kind from the merge result.
> 
> I've been wondering if we can make this safer for others.

You're right. We could decide to have a mode (maybe default to it, so that 
people like me can just use a config option to enable "expert" mode) that
simply refuses to do the merge if it doesn't succeed cleanly if there were 
dirty files in the tree.

			Linus

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

* Re: Files different for me
  2009-02-25 18:51   ` Junio C Hamano
  2009-02-25 19:12     ` Linus Torvalds
@ 2009-02-25 19:16     ` Jay Soffian
  2009-02-25 19:38       ` John Dlugosz
  2009-02-25 19:23     ` John Dlugosz
  2 siblings, 1 reply; 17+ messages in thread
From: Jay Soffian @ 2009-02-25 19:16 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Linus Torvalds, John Dlugosz, git

On Wed, Feb 25, 2009 at 1:51 PM, Junio C Hamano <gitster@pobox.com> wrote:
> The handling of a case where a pull decides to go ahead (because it does
> not have to touch the Makefile you have your codename updates in) but does
> not complete with real conflicts, is not as graceful as the other two
> cases (merge refusing to run at all without touching anything, or merge
> completes cleanly and makes a commit).
>
> You will be left with:
>
>  - Paths that have local changes (index matches HEAD but work tree does
>   not match the index --- like your Makefile);
>
>  - Paths cleanly merged (index and HEAD are different but work tree
>   already matches the index);
>
>  - Unmerged paths (index has higher stage entries with <<</===/>>> files
>   in the work tree);
>
> You, I and experienced users know what to do.  Deal *only* with the last
> kind, mark them with "git add" after you are done with each of them, and
> make sure you do not say "-a" when committing the result, to exclude the
> first kind from the merge result.
>
> I've been wondering if we can make this safer for others.

Have pull detect this case and stash if so, with a message to the user
to pop the stash after they have committed the merge results? Or would
it make more sense to do it in merge? Maybe a pre-merge hook?

j.

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

* RE: Files different for me
  2009-02-25 18:51   ` Junio C Hamano
  2009-02-25 19:12     ` Linus Torvalds
  2009-02-25 19:16     ` Jay Soffian
@ 2009-02-25 19:23     ` John Dlugosz
  2009-02-25 20:04       ` Junio C Hamano
  2 siblings, 1 reply; 17+ messages in thread
From: John Dlugosz @ 2009-02-25 19:23 UTC (permalink / raw)
  To: Junio C Hamano, Linus Torvalds; +Cc: git


=== re: ===

The handling of a case where a pull decides to go ahead (because it does
not have to touch the Makefile you have your codename updates in) but
does
not complete with real conflicts, is not as graceful as the other two
cases (merge refusing to run at all without touching anything, or merge
completes cleanly and makes a commit).

You will be left with:

 - Paths that have local changes (index matches HEAD but work tree does
   not match the index --- like your Makefile);

 - Paths cleanly merged (index and HEAD are different but work tree
   already matches the index);

 - Unmerged paths (index has higher stage entries with <<</===/>>> files
   in the work tree);

You, I and experienced users know what to do.  Deal *only* with the last
kind, mark them with "git add" after you are done with each of them, and
make sure you do not say "-a" when committing the result, to exclude the
first kind from the merge result.

I've been wondering if we can make this safer for others.

===end===

I've gone over that carefully and I understand (I think) what you are
saying.  The first two are things that were not committed, and should
stay that way (added or not) if they did not conflict.  But they can get
in the way if a merge (on other files) is needed.

In an effort to "wonder" out loud, can you explain how to handle that
with "mergetool"?  For a dumb user like me, it just fixes some files
itself (I guess kdiff is smarter than the normal merge logic) and
presents me with a GUI for things I need to specify.  This should
naturally only go through files with conflicts because of those
"<<</===/>>>" files present.

So, what should I know/do?  "Don't use -a"?  If the idea is to commit
the merged stuff but preserve the status of what I've added but don't
want to commit yet, I'm at a loss.  Using git GUI, it will be backwards:
my additions show, but the freshly merged files are noticed as changes
that could be staged.  I want to un-stage the original, stage the merged
files, commit, then re-stage the original stuff?!

Looking again and what you wrote, I think you are not doing that at all.
You would add the merged files to the index, carefully preserving the
first kind.  Is it possible/easy to do what I thought you meant at
first:  commit just the merged files, and leave the "unaffected" files
still in the index and not committed?

--John

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

* RE: Files different for me
  2009-02-25 19:16     ` Jay Soffian
@ 2009-02-25 19:38       ` John Dlugosz
  0 siblings, 0 replies; 17+ messages in thread
From: John Dlugosz @ 2009-02-25 19:38 UTC (permalink / raw)
  To: Jay Soffian, Junio C Hamano; +Cc: Linus Torvalds, git

=== re: ===
Have pull detect this case and stash if so, with a message to the user
to pop the stash after they have committed the merge results? Or would
it make more sense to do it in merge? Maybe a pre-merge hook?
===end===

I've wondered a couple times how to abort a merge.  I ended up just deleting all the funny files.  Did I understand correctly that "git reset --merge" is a new feature?

Perhaps best practice, if I have stuff I've added but don't want to commit yet (why? add the files as you touch them so you don't forget?  keep them from getting confused with the ones you intend to not add at all?), or changes I've not added yet,
would be to "stash" first, do the pull, then "stash apply".

With the existence of a clean way to abort the merge, I could just pull with the assumption that there will be no conflicts, then abort, stash, pull again if needed.  Without the ability to abort the merge, the stakes are high to risk the assumption that all will go well.  So, always stash first.  

Assuming that is correct, it inspires this behavior:
Automatically stash and apply first, then merge.
If merge is clean, delete the stash.
If intervention is needed, I have the stash state to reset to if necessary, and to show me what was already changed if I need to know that.

But I'm still mixed up.  What is the requirement here?  I can understand the need to pull to keep current but not publish my own changes yet.  But why is it necessary to preserve the fact that _some_ (not all) of the changes are in the index?

--John


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

* Re: Files different for me
  2009-02-25 19:23     ` John Dlugosz
@ 2009-02-25 20:04       ` Junio C Hamano
  0 siblings, 0 replies; 17+ messages in thread
From: Junio C Hamano @ 2009-02-25 20:04 UTC (permalink / raw)
  To: John Dlugosz; +Cc: Linus Torvalds, git

"John Dlugosz" <JDlugosz@TradeStation.com> writes:

> You will be left with:
>
>  - Paths that have local changes (index matches HEAD but work tree does
>    not match the index --- like your Makefile);
>
>  - Paths cleanly merged (index and HEAD are different but work tree
>    already matches the index);
>
>  - Unmerged paths (index has higher stage entries with <<</===/>>> files
>    in the work tree);
>
> You, I and experienced users know what to do.  Deal *only* with the last
> kind, mark them with "git add" after you are done with each of them, and
> make sure you do not say "-a" when committing the result, to exclude the
> first kind from the merge result.
>
> I've been wondering if we can make this safer for others.
>
> ===end===
>
> I've gone over that carefully and I understand (I think) what you are
> saying.  The first two are things that were not committed, and should
> stay that way (added or not) if they did not conflict.  But they can get
> in the way if a merge (on other files) is needed.

No, the latter two *should* be committed.  The first one *must* be
excluded.

"merge" (and "git am" with or without "-3" for patch application) are
carefully written in such a way that:

 (1) They do not tolerate a dirty index.  They stop without touching
     anything if you have *any* staged changes.

 (2) As long as your index is clean, i.e. matches HEAD, there are two
     cases.

     (2-a) They add cleanly merged paths to the index and write the result
           out in the work tree.

     (2-b) They leave unclean merges as unmerged entries in the index and
           write the conflicted merge result in the work tree.

     (2-c) If all paths cleanly merge, then the index is written out as a
           tree and a merge commit is created.

     However, neither of the above happens when you have local changes to
     the paths they need to do so.

     Your local changes to the paths that "merge" (and "git am") does not
     have to touch are tolerated.

Unlike CVS/SVN, you do not merge when you are in the middle of doing
something, potentially risking a huge merge conflict that you are unable
to resolve and redo, and (1) and "However" in (2) are both safety against
such "Merge conflicts between my HEAD and the other branch are intermixed
with my still uncommitted changes, and I am lost" disaster.  You get a
chance to finish what you started working with your index first before
continuing with the merge.

We were discussing something very different.

In the case (2) where your local changes do not interact with the merge,
the merge as the whole can fail due to conflicts in some paths.  If you
ran "git add" before starting this merge, you wouldn't have come this far
but would have been dealt with by the safety of (1).

Now, in such a case, you have:

 - Files you had modifications before starting this merge.  Because we are
   talking about case (2), by definition, you haven't done "git add" to
   them.  The index entries are at stage 0 and match HEAD for these paths.

 - Files cleanly merged.  In the index, they are at stage 0 and may be
   different from HEAD.  The difference from HEAD comes from the changes
   in the branch being merged (or in the case of "am -3", the change the
   patch introduces).  It can never come from your local changes, because
   we are talking about case (2), and you couldn't have done "git add"
   them before you started this merge.

 - Files with conflicts.  These conflict come from changes committed to
   your HEAD and the branch being merged (or in the case of "am -3", the
   change the patch introduces).  You can never have had local changes to
   these paths (see "However" in (2) above).

That means:

 - The paths at stage 0 in the index can and should be committed without
   any further "git add" when recording this merge.  Doing "git add" for
   paths in the first category among the three will include your unrelated
   local changes in the result which is not what you want.  And doing "git
   add" for the paths in the second category is unnecessary; "merge" (and
   "git am") have already updated the index with the merge result.

 - The paths at higher stages (i.e. unmerged) come from the merge, and you
   must resolve them (either in vi or mergetool) and "git add" them.

So the short rule is "resolve and 'git add' to mark the resolution only
for paths with conflicts.  Never 'git add' anything else before making
your commit.  And do not say 'git commit -a' because that is part of the
previous rule."

> In an effort to "wonder" out loud, can you explain how to handle that
> with "mergetool"?  For a dumb user like me, it just fixes some files
> itself (I guess kdiff is smarter than the normal merge logic) and
> presents me with a GUI for things I need to specify.  This should
> naturally only go through files with conflicts because of those
> "<<</===/>>>" files present.
>
> So, what should I know/do?  "Don't use -a"?  If the idea is to commit
> the merged stuff but preserve the status of what I've added but don't
> want to commit yet,

You do not have to worry about that, because you don't "merge" (or "am")
when you already have changes that are "git add"ed to the index.  These
tools correctly detect this case that you are in the middle of something
and refuse to touch neither your index nor your work tree(see (1) above).

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

* Re: Files different for me
  2009-02-25 19:12     ` Linus Torvalds
@ 2009-02-25 20:06       ` Junio C Hamano
  2009-02-25 20:14         ` Linus Torvalds
  0 siblings, 1 reply; 17+ messages in thread
From: Junio C Hamano @ 2009-02-25 20:06 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: John Dlugosz, git

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

>> You, I and experienced users know what to do.  Deal *only* with the last
>> kind, mark them with "git add" after you are done with each of them, and
>> make sure you do not say "-a" when committing the result, to exclude the
>> first kind from the merge result.
>> 
>> I've been wondering if we can make this safer for others.
>
> You're right. We could decide to have a mode (maybe default to it, so that 
> people like me can just use a config option to enable "expert" mode) that
> simply refuses to do the merge if it doesn't succeed cleanly if there were 
> dirty files in the tree.

"git merge" has always had this "stash away local changes before starting,
and unstash once done" safety when we try to run multiple strategies.
A patch to trigger it even for a single strategy case may be trivial.

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

* Re: Files different for me
  2009-02-25 20:06       ` Junio C Hamano
@ 2009-02-25 20:14         ` Linus Torvalds
  0 siblings, 0 replies; 17+ messages in thread
From: Linus Torvalds @ 2009-02-25 20:14 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: John Dlugosz, git



On Wed, 25 Feb 2009, Junio C Hamano wrote:
> 
> "git merge" has always had this "stash away local changes before starting,
> and unstash once done" safety when we try to run multiple strategies.
> A patch to trigger it even for a single strategy case may be trivial.

Well, I'd feel better if it was actually in the low-level merge code, the 
way the current "I refuse to merge if the file is dirty" logic is.

			Linus

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

end of thread, other threads:[~2009-02-25 20:17 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-25 16:11 Files different for me John Dlugosz
     [not found] ` <16946e800902250840o677f8708x7c0bf8980e004b91@mail.gmail.com>
2009-02-25 16:42   ` Feanil Patel
2009-02-25 17:05 ` Brian Gernhardt
2009-02-25 18:02   ` John Dlugosz
2009-02-25 18:38     ` Brian Gernhardt
2009-02-25 19:01       ` John Dlugosz
2009-02-25 18:44     ` Matthieu Moy
2009-02-25 17:55 ` Junio C Hamano
2009-02-25 18:04 ` Linus Torvalds
2009-02-25 18:51   ` Junio C Hamano
2009-02-25 19:12     ` Linus Torvalds
2009-02-25 20:06       ` Junio C Hamano
2009-02-25 20:14         ` Linus Torvalds
2009-02-25 19:16     ` Jay Soffian
2009-02-25 19:38       ` John Dlugosz
2009-02-25 19:23     ` John Dlugosz
2009-02-25 20:04       ` Junio C Hamano

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 NNTP newsgroup(s).