git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: git-name-rev off-by-one bug

From
Junio C Hamano <junkio@cox.net>
Date
Nov 29, 2005, 09:29 UTC
Message-ID
<7voe43iyyu.fsf@assigned-by-dhcp.cox.net>
In-Reply-To
<20051129080529.20705.qmail@science.horizon.com>
linux@horizon.com writes:
> (In particular, and unlike other SCMs, "push" and "pull" are
> based on merging!  So I can't even understand what pulling from
> Linus's tree does until I understand merging.)

If you do "git pull git://.../linux-2.6/", it fetches the objects and stores Linus "master" into .git/FETCH_HEAD, and then merges that into whatever branch you happen to be on (but you already know that).

> BUT... what's the second argument to git-read-tree for, if it
> always has to be HEAD?

git-read-tree is purely "a building block to be scripted" in your second mail (private?). In my message you are replying to, I outlined what the end-user level tool, git-pull (and git-merge it uses) does, which is built using git-read-tree, and we happen to always pass HEAD as its second argument. But it does not have to be that way. One thing planned in the future is to do a merge in a temporary working directory, not in your primary working tree, and when we implement that, the second argument will be whatever branch head you are pulling into, not necessarily your current HEAD.

> BTW, I'd change the description of git-read-tree from

Thanks. I am a bit too tired tonight so I may send you a correction later if what I am going to comment here turns out to be incorrect, but a quick glance tells me this is a good clarification.

> ...  I was wondering why the
> hell a 2-way merge looked more complex than a 3-way.

2-way is called merge but it is not about the merge at all (git-merge is mostly about 3-way merge). It is more about checkout. Suppose you have checked out branch A, and have local modificiations (both in index and in working tree). You would want to switch to branch B by "git checkout B" (without -f). 2-way "read-tree -m -u" is used to ensure that you take your local modifications with you while checking out branch B into your working tree, meaning:

 (1) local changes already registered in the index stays in the
     index file; obviously this can be done only if A and B are
     the same at such paths.
 (2) local changes not registered in the index stays in the
     working tree; similar restriction applies but the rules are
     more involved.

Similar to 3-way case, 2-way will refuse to lose your local modifications, and that is the 2-way case table in Documentation/git-read-tree.txt is about.

> This is git-merge, as opposed to the more primitive git-read-tree -m
> plus git-merge-index, right?

Everything I wrote in the previous message was about the end-user tools git-pull/git-merge.

> - Doesn't any non-trivial merge or invocation of git-update-index
>   produce blob objects in the database that become garbage if you
>   do this?

We produce garbage blobs all the time, and we do not care. Even the following sequence that does not involve any merge produces a garbage blob for the first version of A that was faulty:

        $ git checkout
        $ edit A
        $ git update-index A
        $ make ;# oops, there is a mistake.
        $ edit A
        $ make ;# this time it is good.
        $ git commit -a -m 'Finally compiles.'
Occasional fsck-objects, prune and repack are your friends.
> - Is there any difference between "git-reset --hard" and "git-checkout -f"?

"reset --hard" does more thorough job removing unwanted files from your working tree. It looks at your current HEAD, the commit you are resetting to (when you say "reset --hard <commit>"), and your index file, and paths mentioned by any of these three that should not remain (that is, not in the commit you are resetting to) are removed from your working tree. In addition, "reset --hard <commit>" updates the branch head and can be used to rewind it. On the other hand, "checkout -f" tells git to *ignore* what is in the index, so any file in the working tree that used to be in the index (or old branch you were working on) that does not exist in the branch you are checking out is not removed.

On a related topic of removing unwanted paths, earlier I said 2-way is used to make sure "git checkout" takes your changes with you when you switch branches. As a natural consequence of this, if you do not have any local changes, "git checkout" without "-f" does the right thing -- it removes unwanted paths that existed in the original branch but not in the branch you are switching to.

> Okay, so git-update-index will overwrite a staged file with a
> fresh stage-0 copy.  And git-commit will refuse to commit
> (to be precise, it'll stop at the git-write-tree stage) if there
> are unresolved conflicts.

Sorry, I was unclear that I was talking about end-user level tool. The update-index here is not about the conflict resolution in the index file read-tree documentation talks about. That has already been done when "merge" ran in the conflicting case. In the conflicting case, the working tree holds 3-way merge conflicting result, and the index holds HEAD version at stage0 for such a path. Hand resolving after update-index is to record what you eventually want to commit (i.e. you are not replacing higher stage entry in the index with stage0 entry -- you are replacing stage0 entry with another).

> If you want to see the unmodified input files, you can find their
> IDs with "git-ls-files -u" and then get a copy with "git-cat-file blob"
> or "git-unpack-file".  git-merge-index is basically a different way to
> process the output of git-ls-files -u.

Yes, in principle. But in practice you usually do not use these low level tools yourself. When git-merge returns with conflicting paths, most of them have already been collapsed into stage0 and git-ls-files --unmerged would not show. The only case I know of that you may still see higher stage entries in the index these days is merging paths with different mode bits. We used to leave higher stage entries when both sides added new file at the same path, but even that we show as merge from common these days.

Previous: linux@horizon.comNext: Junio C Hamano
Message 4 of 64 in “git-name-rev off-by-one bug”
  1. linux@horizon.comNov 28, 2005
  2. Junio C HamanoNov 29, 2005
  3. linux@horizon.comNov 29, 2005
  4. Junio C HamanoNov 29, 2005
  5. Junio C HamanoNov 30, 2005
  6. Petr BaudisNov 29, 2005
  7. Junio C HamanoNov 29, 2005
  8. Petr BaudisDec 4, 2005
  9. as promised, docs: git for the confusedlinux@horizon.com, Dec 8, 2005
  10. Junio C HamanoDec 8, 2005
  11. H. Peter AnvinDec 8, 2005
  12. Alan ChandlerDec 9, 2005
  13. Petr BaudisDec 9, 2005
  14. Josef WeidendorferDec 9, 2005
  15. linux@horizon.comNov 29, 2005
  16. Junio C HamanoNov 29, 2005
  17. linux@horizon.comNov 30, 2005
  18. Junio C HamanoNov 30, 2005
  19. Junio C HamanoNov 30, 2005
  20. Linus TorvaldsNov 30, 2005
  21. Junio C HamanoNov 30, 2005
  22. Junio C HamanoNov 30, 2005
  23. Linus TorvaldsNov 30, 2005
  24. Linus TorvaldsNov 30, 2005
  25. Junio C HamanoNov 30, 2005
  26. Junio C HamanoNov 30, 2005
  27. Linus TorvaldsNov 30, 2005
  28. Linus TorvaldsNov 30, 2005
  29. Junio C HamanoDec 2, 2005
  30. merge-one-file: make sure we create the merged file.Junio C Hamano, Dec 2, 2005
  31. merge-one-file: make sure we do not mismerge symbolic links.Junio C Hamano, Dec 2, 2005
  32. git-merge documentation: conflicting merge leaves higher stages in indexJunio C Hamano, Dec 2, 2005
  33. linux@horizon.comNov 30, 2005
  34. Junio C HamanoNov 30, 2005
  35. More merge questionslinux@horizon.com, Nov 30, 2005
  36. Daniel BarkalowNov 30, 2005
  37. Junio C HamanoNov 30, 2005
  38. linux@horizon.comDec 2, 2005
  39. Junio C HamanoDec 2, 2005
  40. Sven VerdoolaegeDec 2, 2005
  41. Junio C HamanoDec 2, 2005
  42. Sven VerdoolaegeDec 5, 2005
  43. linux@horizon.comDec 2, 2005
  44. Junio C HamanoDec 2, 2005
  45. linux@horizon.comDec 2, 2005
  46. Junio C HamanoDec 2, 2005
  47. Linus TorvaldsDec 2, 2005
  48. linux@horizon.comDec 2, 2005
  49. linux@horizon.comDec 2, 2005
  50. Linus TorvaldsNov 30, 2005
  51. Junio C HamanoNov 30, 2005
  52. Junio C HamanoNov 30, 2005
  53. Junio C HamanoNov 30, 2005
  54. linux@horizon.comNov 30, 2005
  55. Daniel BarkalowNov 30, 2005
  56. Daniel BarkalowNov 30, 2005
  57. Junio C HamanoNov 30, 2005
  58. Daniel BarkalowNov 30, 2005
  59. Junio C HamanoNov 30, 2005
  60. Daniel BarkalowNov 30, 2005
  61. Junio C HamanoDec 1, 2005
  62. Junio C HamanoDec 1, 2005
  63. Petr BaudisDec 1, 2005
  64. Randal L. SchwartzDec 1, 2005

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.