Re: git 1.4.0 usability problem

3 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: git 1.4.0 usability problem

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:30

Jeff Garzik [off-list ref] writes:
But if what Ryan says is true, about simply needing to ditch
the "-f" argument I habitually pass to 'git checkout', would that
alleviate the need for a patch?
To a certain degree, yes.

But I suspect (I am not a kernel person so I can only speculate)
in the kernel workflow you would often pick up a patch from the
list, apply it to your working tree (without applying it to your
index, IOW with "patch -p1" or "git apply", not with "git apply
--index"), and then decide to pull from somewhere else while
your working tree is dirty (but index is not).  The patch might
have created a new file or two, and the pull may also contain a
commit that applied the same patch in question.  The no-clobber
check would trigger in such a case preventing you from pulling,
and neither "checkout" nor "checkout -f" would clean these new
files that you have not told git about.
FWIW, my workflow is

	cd /repos
	cd linux-2.6
	git pull
	cd ../libata-dev
	git checkout -f master	# guarantee any WIP goes away
We kept saying "with checkout -f any dirty state goes away from
your working tree".  It is true only with respect to the files
git knows about.  The trouble you experienced was about
untracked files -- files git does not know about, and they will
be left behind.

So if path F is in test branch head and linus branch head, but
not in your master branch head, and you have checked out test in
your working tree, even if path F in the working tree is clean:

	git checkout -f master

will leave F behind.  If you pull from linus at this point, the
check would trigger.  Running "git checkout master" without -f
would however remove it and you would not have the problem.
That is what Ryan's suggestion is about.

However, if you have a patch you got from somebody on the net
that creates F (maybe it is the same patch linus accepted
recently) while on your master branch, and you tried to examine
it by applying it to your working tree with "patch -p1" or "git
apply", your working tree will have F that is not in index (and
in your branch head).  In that state if you pull from linus, the
no-clobber check triggers.  In this case, neither "git checkout
master", "git checkout -f master", nor "git reset --hard master"
would remove F, because git does not even know about it, so
pulling from linus would fail.  "git clean" would removes F, so
it may not be a big deal, but it is rather a heavy-handed
operation that removes all crufts, so you may find it a
not-so-useful workaround (I certainly would, and that is the
primary reason I rarely use "git clean" myself).

It's a bit sad situation.  One of the useful feature of git is
that you can continue working in a dirty working tree as long as
your index is clean and your local changes do not interfere with
a merge, patch application, or branch switching.  Strictly
speaking, this no-clobber check _is_ about a local change that
does interfere with the operation, so from theoretical point of
view it is a good safety measure, but at the same time we did
not consider untracked files as precious until recently, and I
suspect that "the same patch applied elsewhere to create the
same file" pattern is reasonably common that this safety valve
may interfere the work more often than it may help avoiding
mistakes.

Re: git 1.4.0 usability problem

From: Jeff Garzik <hidden>
Date: 2016-06-15 22:42:30

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
Generating pack...
Done counting 3427 objects.
Result has 2510 objects.
Deltifying 2510 objects.
  100% (2510/2510) done
Unpacking 2510 objects
Total 2510, written 2510 (delta 2024), reused 0 (delta 0)
  100% (2510/2510) done
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.

Re: git 1.4.0 usability problem

From: Ryan Anderson <hidden>
Date: 2016-06-15 22:42:30

On Tue, Jun 20, 2006 at 04:36:46AM -0400, Jeff Garzik wrote:
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
Generating pack...
Done counting 3427 objects.
Result has 2510 objects.
Deltifying 2510 objects.
 100% (2510/2510) done
Unpacking 2510 objects
Total 2510, written 2510 (delta 2024), reused 0 (delta 0)
 100% (2510/2510) done
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.
If that is the case, how did it get into the directory, then?

I suspect the history we're missing is this:

git checkout upstream
...
git checkout -f master

If you have a clean tree, there's not really a reason to use -f.  It
actively hurts you by confusing git as to what state your directory is
in. (If you don't have a clean tree, well, using -f will orphan new
files that Git knows about, and overwrite the changes on ones it does,
so it's still rather inconsistent, and probably not at all what you
intend.)

Instead of using "git checkout -f" to abandon any WIP, try something
like this:

	git branch throw-away HEAD
	git checkout throw-away
	git commit -a -m "throw away"
	git checkout $1
	git branch -D throw-away


i.e:
$ sed -i -e 's/PHONY/YNOHP/g' Makefile
$ git branch throw-away HEAD
$ git checkout throw-away
$ git diff |diffstat
 Makefile |   60 ++++++++++++++++++++++++++++++------------------------------
$ git commit -a -m "throw-away"
$ git checkout master
$ git branch -d throw-away
The branch 'throw-away' is not a strict subset of your current HEAD.
If you are sure you want to delete it, run 'git branch -D throw-away'.
$ git branch -D throw-away
Deleted branch throw-away.
$ git diff | diffstat
0 files changed
$ git branch throw-away HEAD
$ cp Makefile Makefile-ryan
$ git add Makefile-ryan 
$ git checkout throw-away
$ git diff | diffstat
 0 files changed
$ git status
# On branch refs/heads/throw-away
#
# Updated but not checked in:
#   (will commit)
#
#	new file: Makefile-ryan
#
$ git commit -a -m "throw-away"
$ git checkout master
$ git status
nothing to commit

Note that using plain "checkout" should be noticeably faster, too.





-- 

Ryan Anderson
  sometimes Pug Majere
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help