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

Re: GIT vs Other: Need argument

From
Junio C Hamano <junkio@cox.net>
Date
Apr 19, 2007, 06:02 UTC
Message-ID
<7vejmg9a1z.fsf@assigned-by-dhcp.cox.net>
In-Reply-To
<7vy7kpaz9s.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
Show 13 quoted lines
> Steven Grimm <koreth@midwinter.com> writes:
>
>> And in particular -- this being the original topic of the thread --
>> when an svn user sees me doing that, they do not immediately think of
>> the fact that merging between immutable revisions may have some
>> benefits. They see me typing four commands (commit, fetch, rebase,
>> reset) to do the same thing they can do in one command with svn, and
>> conclude that git is harder to use.
>
> No arguments there.  While I know I will never use such a
> workflow myself, I think it makes sense to _allow_ local
> changes to be merged to the new revision if the user chooses to
> use such a workflow.

Actually, there is one thing that makes this much easier to do in SVN. It is its centralized nature.

If you have this sequence:
	(1) update and sync with the repository
        (2) you work alone, without committing
        (3) while you do (2), other people make commits
        (4) you update from the repository

Because of its central nature, the commits made in (3) are always proper descendant of the commit you are basing your work on in (2). So at point (4), the resolution you would need to perform is this "merge".

          (2).............M?
         /               . 
	1-----3a-3b-3c-3d
    Notational convention: Solid lines and unparenthesized
    letters are actual commits and ancestry in these pictures.
    Letters in parentheses and dotted lines are locally modified
    states and derivations of these states from commits.

But because there is no "commit" that records the work you did in (2) alone, you can afford to 3-way merge whatever conflict you get at M and you do not even record M as a merge. The result simply becomes a proper descendant of 3, which is still uncommitted local change.

                          (2')
                         .
	1-----3a-3b-3c-3d

The patch series I "vaguely recalled" in my previous message handled this special case where the branch being merged (i.e. 3d) was a fast-forward of the current commit (i.e. 1).

However, in git, you do not necessarily work that way. As you admitted, the ability to commit locally is what's different.

          2a---2b..(2c)...M?
         /               .
	1-----3a-3b-3c-3d

If (4) happened after you've accmulated local commits 2a, and 2b, and you have local changes (your state 2c is different from your tip, 2b, but is uncommitted, and kept in the working tree alone), you usually do not want to resolve the mess to make a commit M, pretend M is a proper descendant of 3d, depending on the final structure you are trying to achieve (the mess may come from interactions between 3's and 2a or 2b, or interactions between 3's and 2c).

There are three possible commit ancestry structures you would want to eventually reach, and three distinct sets of steps to reach those structures.

 1. Perfect what you were in the middle of, and then perform a
    merge.  IOW, you don't have to update from remote when you
    are not ready.
          2a---2b---2c----M
         /               / 
	1-----3a-3b-3c-3d
 2. Merge what has already been committed, excluding your
    unproven WIP that is in the working tree, and roll forward
    your local changes on top of it.
          2a---2b---------M..(2c')
         /               / 
	1-----3a-3b-3c-3d
 3. Always serialize by rebasing.  The structure you would want
    to end up with is like this:
                         2a'-2b'.(2c')
                        /
	1-----3a-3b-3c-3d

Among these three workflows, what is most natural in git is the first one. The tool natively supports it well.

For the second workflow, you would:
    2-a. first make a tentative commit 2c
	$ git commit
                 --2c
                /
          2a---2b
         /
	1-----3a-3b-3c-3d
    2-b. merge what was ready on your end and the other side:
	$ git checkout HEAD^ && git merge origin
                 --2c
                /
          2a---2b---------M
         /               / 
	1-----3a-3b-3c-3d
    2-c. roll forward the local change you have in 2c:
	$ git rebase --onto HEAD master
        $ git reset HEAD^
          2a---2b---------M...(2c')
         /               / 
	1-----3a-3b-3c-3d

This probably is the next best organization. But you have to realize that this requires you to resolve potential conflict when creating M and then another conflict when rolling forward your local changes.

    We probably could help automating this, but your "git pull"
    session transcript need to look like this:
	$ git pull origin
        First stashing away of your local changes...
	Resolving conflicts between 2b and 3d.
	Conflicted merge.  Please resolve and commit.
	$ edit ; test
        $ git commit ;# to record M
	Committed the merge result.
        You have stashed local changes further to roll forward.
        $ git unstash local-changes
        Resolving conflicts between M and 2c.
	Local changes conflicted during roll-forward.
        Leaving resulting mess in the working tree for you to sort out.
	$ 
To end up with the third graph, you would:
    3-a. first make a tentative commit 2c
	$ git commit
                 --2c
                /
          2a---2b
         /
	1-----3a-3b-3c-3d
    3-b. rebase
	$ git rebase origin
                          2a'--2b'--2c
                         /
	1-----3a-3b-3c-3d
    3-c. reset
	$ git reset HEAD^
                          2a'--2b'..(2c')
                         /
	1-----3a-3b-3c-3d

and I think that is what you have been doing. Both the final structure and the workflow are least "git-like" among these three.

    If you want to automate this, you can use this four-liner
    shell script:
	#!/bin/sh
        git commit || exit
	git fetch origin || exit
        git rebase origin || exit
	git reset HEAD^
    Store this in $HOME/bin/git-sgpull, if you may, and you can
    even say "git sgpull" to invoke it.
    When 'rebase' does not get conflict, which is the bast case
    you are primarily complaining about, having to type three
    commands, this will run to the end with this single command
    and you will feel happier.
    When 'rebase' gets conflict, however, you would need to
    resolve and have it keep going, but that is something you
    cannot avoid.  You would need to remember that the final
    "reset HEAD^" needs to be issued from your shell, but that
    should be obvious.
Previous: Junio C HamanoNext: Steven Grimm
Message 99 of 120 in “GIT vs Other: Need argument”
  1. Pietro MascagniApr 17, 2007
  2. Matthieu MoyApr 17, 2007
  3. Andy ParkinsApr 17, 2007
  4. Alex RiesenApr 17, 2007
  5. Martin LanghoffApr 17, 2007
  6. Linus TorvaldsApr 17, 2007
  7. Matthieu MoyApr 17, 2007
  8. Martin LanghoffApr 17, 2007
  9. Alex RiesenApr 17, 2007
  10. Dana HowApr 25, 2007
  11. Alex RiesenApr 25, 2007
  12. Tomash BrechkoApr 17, 2007
  13. Guilhem BonnefilleApr 17, 2007
  14. Andy ParkinsApr 17, 2007
  15. Shawn O. PearceApr 17, 2007
  16. Marcin KasperskiApr 17, 2007
  17. Johannes SchindelinApr 18, 2007
  18. Linus TorvaldsApr 18, 2007
  19. Nicolas PitreApr 18, 2007
  20. Bill LearApr 18, 2007
  21. Matthieu MoyApr 18, 2007
  22. Nicolas PitreApr 18, 2007
  23. Matthieu MoyApr 19, 2007
  24. Petr BaudisApr 19, 2007
  25. Matthieu MoyApr 20, 2007
  26. Theodore TsoApr 18, 2007
  27. Guilhem BonnefilleApr 18, 2007
  28. Linus TorvaldsApr 18, 2007
  29. Daniel BarkalowApr 18, 2007
  30. Michael K. EdwardsApr 18, 2007
  31. Johannes SchindelinApr 19, 2007
  32. Matthieu MoyApr 19, 2007
  33. Johannes SchindelinApr 19, 2007
  34. Alex RiesenApr 19, 2007
  35. Christian MICHONApr 19, 2007
  36. Johannes SchindelinApr 19, 2007
  37. Christian MICHONApr 19, 2007
  38. Linus TorvaldsApr 19, 2007
  39. Marcin KasperskiApr 19, 2007
  40. Linus TorvaldsApr 19, 2007
  41. Carl WorthApr 23, 2007
  42. Josef WeidendorferApr 23, 2007
  43. Carl WorthApr 23, 2007
  44. Junio C HamanoApr 23, 2007
  45. Carl WorthApr 23, 2007
  46. Linus TorvaldsApr 23, 2007
  47. Brian GernhardtApr 23, 2007
  48. Daniel BarkalowApr 24, 2007
  49. Junio C HamanoApr 24, 2007
  50. J. Bruce FieldsApr 24, 2007
  51. Linus TorvaldsApr 24, 2007
  52. J. Bruce FieldsApr 30, 2007
  53. Making git disappear when talking about my code (was: Re: GIT vs Other: Need argument)Carl Worth, Apr 25, 2007
  54. Carl WorthApr 25, 2007
  55. Linus TorvaldsApr 25, 2007
  56. Carl WorthApr 25, 2007
  57. Nicolas PitreApr 25, 2007
  58. Carl WorthApr 25, 2007
  59. Junio C HamanoApr 25, 2007
  60. Nicolas PitreApr 25, 2007
  61. Carl WorthApr 25, 2007
  62. Nicolas PitreApr 25, 2007
  63. Linus TorvaldsApr 25, 2007
  64. Daniel BarkalowApr 25, 2007
  65. Junio C HamanoApr 25, 2007
  66. Linus TorvaldsApr 25, 2007
  67. Nicolas PitreApr 25, 2007
  68. Daniel BarkalowApr 25, 2007
  69. Carl WorthApr 25, 2007
  70. Daniel BarkalowApr 25, 2007
  71. Nicolas PitreApr 25, 2007
  72. Junio C HamanoApr 23, 2007
  73. Johannes SchindelinApr 19, 2007
  74. History cleanup/rewriting script for gitJan Harkes, Apr 20, 2007
  75. Johannes SchindelinApr 20, 2007
  76. Petr BaudisApr 20, 2007
  77. Jan HarkesApr 20, 2007
  78. Marcin KasperskiApr 19, 2007
  79. Johannes SchindelinApr 19, 2007
  80. Marcin KasperskiApr 19, 2007
  81. Johannes SchindelinApr 19, 2007
  82. J. Bruce FieldsApr 19, 2007
  83. Theodore TsoApr 19, 2007
  84. [ANNOUNCE] Cogito is for salePetr Baudis, Apr 19, 2007
  85. Matthieu MoyApr 19, 2007
  86. Junio C HamanoApr 19, 2007
  87. Johannes SchindelinApr 19, 2007
  88. Guilhem BonnefilleApr 18, 2007
  89. Andy ParkinsApr 18, 2007
  90. Steven GrimmApr 18, 2007
  91. Jakub NarebskiApr 19, 2007
  92. Steven GrimmApr 19, 2007
  93. Jakub NarebskiApr 19, 2007
  94. Johannes SchindelinApr 19, 2007
  95. Julian PhillipsApr 19, 2007
  96. Steven GrimmApr 19, 2007
  97. Johannes SchindelinApr 19, 2007
  98. Junio C HamanoApr 19, 2007
  99. Junio C HamanoApr 19, 2007
  100. Steven GrimmApr 19, 2007
  101. Junio C HamanoApr 19, 2007
  102. Shawn O. PearceApr 20, 2007
  103. Jakub NarebskiApr 20, 2007
  104. Karl HasselströmApr 20, 2007
  105. Junio C HamanoApr 20, 2007
  106. Petr BaudisApr 20, 2007
  107. Junio C HamanoApr 20, 2007
  108. Steven GrimmApr 20, 2007
  109. Yann DirsonApr 18, 2007
  110. Sam VilainApr 18, 2007
  111. Yann DirsonApr 18, 2007
  112. Dana HowApr 25, 2007
  113. Marcin KasperskiApr 19, 2007
  114. Alex RiesenApr 19, 2007
  115. Andy ParkinsApr 19, 2007
  116. Shawn O. PearceApr 20, 2007
  117. Eric BlakeApr 20, 2007
  118. Johannes SchindelinApr 19, 2007
  119. Marcin KasperskiApr 19, 2007
  120. Johannes SchindelinApr 19, 2007

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.