Thread (1 message) 1 message, 1 author, 2016-06-15

Re: git 1.4.0 usability problem

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:30
Subsystem: the rest · Maintainer: Linus Torvalds

Possibly related (same subject, not in this thread)

Jeff Garzik [off-list ref] writes:
Here's a real world example of the 1.4.0 change breaking a merge:

("netdev-2.6" == local clone of kernel.org/...jgarzik/netdev-2.6.git)
[jgarzik@pretzel netdev-2.6]$ git branch
  ALL
  e100-sbit
* master
  upstream
  upstream-linus

[jgarzik@pretzel netdev-2.6]$ git pull /spare/repo/linux-2.6
...
Updating from 427abfa28afedffadfca9dd8b067eb6d36bac53f to
25f42b6af09e34c3f92107b36b5aa6edc2fdba2f
fatal: Untracked working tree file 'drivers/net/myri10ge/Makefile'
would be overwritten by merge.

EXPLANATION:

* drivers/net/myri10ge/Makefile exists in latest Linus kernel tree,
stored locally in /spare/repo/linux-2.6.
* drivers/net/myri10ge/Makefile exists in netdev-2.6#upstream and
netdev-2.6#upstream-linus branches.
* drivers/net/myri10ge/Makefile does not exist in current branch,
netdev-2.6#master.
Requesting one more bit of explanation.

When you did this pull, you were on your "master" branch.  Whose
HEAD does not have the myri10ge/Makefile in its tree.  And you
did not have that path in the index either (otherwise it would
not have said "untracked working tree file").  Did you have that
file in your working tree?  And if so how/why?

If you did something like this before ending up in your "master"
branch, I think you would have such a file:

	$ git branch ;# you were in upstream-linus branch
          ALL
          e100-sbit
          master
          upstream
        * upstream-linus
        $ git diff      ;# and were up-to-date -- no output nor
        $ git diff HEAD ;# local changes
        $ git checkout -f master ;# but you switched to master with -f

With "checkout -f", your local changes to files that appear in
the "master" branch will be overwritten, but the files that are
supposed to disappear because you are switching out of the
current branch (e.g. myri10ge/Makefile) are left behind.

It probably would make sense to change "checkout -f" so that it
removes such files from your working tree to support this
particular usage.  We kept saying "with -f local dirty state
will be gone", but "checkout -f" does not do as thorough job as
"reset --hard".  Changing "checkout -f next-branch" to do the
moral equivalent of "reset --hard HEAD && checkout next-branch"
would solve this problem, and I do not think changing it that
way would not have any negative impact.

I suspect this patch would do exactly that...
diff --git a/git-checkout.sh b/git-checkout.sh
index 564117f..193f6c5 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -137,7 +137,7 @@ # what we already had
 
 if [ "$force" ]
 then
-    git-read-tree --reset $new &&
+    git-read-tree --reset -u $new &&
 	git-checkout-index -q -f -u -a
 else
     git-update-index --refresh >/dev/null
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help