From: Junio C Hamano <hidden> Date: 2016-06-15 22:46:17
Linus Torvalds [off-list ref] 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.
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
From: Jay Soffian <hidden> Date: 2016-06-15 22:46:17
On Wed, Feb 25, 2009 at 1:51 PM, Junio C Hamano [off-list ref] 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.
From: John Dlugosz <hidden> Date: 2016-06-15 22:46:17
=== 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
From: John Dlugosz <hidden> Date: 2016-06-15 22:46:17
=== 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