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

Re: Cleaning up git user-interface warts

From
Nicolas Pitre <nico@cam.org>
Date
Nov 15, 2006, 04:32 UTC
Message-ID
<Pine.LNX.4.64.0611142048350.2591@xanadu.home>
In-Reply-To
<7virhhy76h.fsf@assigned-by-dhcp.cox.net>
On Tue, 14 Nov 2006, Junio C Hamano wrote:
Show 31 quoted lines
> Junio C Hamano <junkio@cox.net> writes:
> 
> >  - I think it would be sensible to make remote tracking branches
> >    less visible.  For example:
> >...
> >  - "git merge" to merge another branch into the current would
> >    make sense.  "git pull . remotes/origin/next" is showing too
> >    much implementation detail.  It should just be:
> >
> > 	git merge origin#next
> 
> This and other examples in "making remote tracking branches less
> visible" are hard to read because I used the word "origin" in
> two different sense.  So here is a needed clarification.
> 
> If you have remotes/upstream that says:
> 
> 	URL: git://git.xz/repo.git
>         Pull: refs/heads/master:remotes/origin/master
>         Pull: refs/heads/next:remotes/origin/next
> 
> Then, currently the users need to say:
> 
> 	git diff remotes/origin/master
>         git merge remotes/origin/next
> 
> By "making tracking branches less visible", what I mean is to
> let the users say this instead:
> 
> 	git diff upstream
>         git merge upstream#next

What is the point of hiding tracking branches? Why just not making them easier to use instead? There are currently so many ways to specify remote branches that even I get confused.

OK..... let's pretend this is my follow-up to your "If I were redoing git from scratch" query. Actually I would not redo it from scratch since the vast majority of it is rather sane already. But here's some changes that I would do:

1) make "git init" an alias for "git init-db".

What's the point of "-db"? Sure we're initializing the GIT database. But who cares? The user doesn't care if GIT uses a "database" or whatever. And according to some people's definition of a "database" it could be argued that GIT doesn't use a database at all in the purist sense of it. What the user wants is to get started and "init" (without the "-db" is so much more to the point. Doesn't matter if incidentally it happens to be the same keyword HG uses for the same operation because we are not afflicted by the NIH disease, right? And it has 3 chars less to type which is for sure a premium improvement to the very first GIT user experience!

2) "pull" and "push" should be symmetrical operations

They are symmetrical in the dictionary and in people's mind. OK but what if I merge content from another _local_ branch into the current one? Isn't that kind of a pull as well? Answer: NO IT IS NOT! Reason: because we already have "merge" for that very operation for damn sake! And because "merging" isn't a synonym for "pulling" at all, we cannot pretend it should sort of become more true if taken the other way around.

Actually, if we _merge_ stuff together, we certainly have to /pull/ some of it, meaning that "merge" might imply a "pull", even in real life situations outside of the GIT context (think merging Vodka and Kahlua in a glass where you might have to pull the Vodka bottle out of the freezer before you can merge it). And thankfully we got it right with git-merge which can take either a branch or an URL as argument which in the later case will perform a pull implicitly (OK currently a fetch but you know what I mean).

But trying to put in people's head that "pulling" implies a "merge"? No that doesn't work really well. OK if you pull too hard on the Vodka bottle that might imply a merge at some point but it would certainly be accidental. And it is not without coincidence that some people had accidental GIT merges by using git-pull.

Conclusion:  git-pull must not perform any merge.  It is the symmetrical 
operation of a push meaning that it pulls content from a remote branch 
and does no more.  People understands that pretty well, .  This makes 
git-fetch redundant (or an alias to git-pull) in that case, and again we 
don't mind it becoming similar to in HG because we admit HG was right 
about it.
3) remote branch handling should become more straight forward.

OK! Now that we've solved the pull issue and that everybody agrees with me (how can't you all agree with me anyway) let's have a look at remote branches. It should be simple:

a)	git-pull git://repo.com/time_machine.git

This pulls every branches from the time_machine.git repository and create identically named branches locally, except for the remote master becoming origin locally. All those branches are marked read-only (i.e. cannot commit to them) and _each_ of those branches get an URL associated to them somehow (the association is an implementation detail).

If then you do:
b)	git-pull origin

Then it will pull the git://repo.com/time_machine.git:master branch into the local "origin" branch. IOW, local tracking branches becomes synonyms for their remote URLs after they've been pulled once. If the remote branch "next" became a local "next" with the first pull (because it didn't specify any branch meaning that they were all pulled), doing a:

c)	git-pull next
would actually be the same as:
d)	git-pull git://repo.com/time_machine.git:next

Now to have different remote and local names for those tracking branches:

e)	git-pull git://repo.com/time_machine.git:master upstream

would be a variation where a remote branch gets a different local name. This pulls the remote master branch but calls it "upstream" locally. If that "upstream" branch does exist locally already then fail with appropriate error message, unless the local branch happens to have the same URL attribute already. You then have two local branches tracking the same remote branch which is weird but still fine if someone wants to have different views (today's pull and yesterday's pull). This is not necessarily something to encourage but only a fallout of the branch semantic. And again a simple:

f)	git-pull upstream
would update the "upstream" branch from the remote master branch.

I think the concept of "branch group" should be preserved too. So if you create a group called "warp", then add "origin", "next", and "upstream" to it, then:

g)	git-pull warp

would pull all the included branches. One way to create a branch group with the initial pull is not to specify the remote branch but only the repository URL, like:

h)	git-pull git://repo.com/time_machine.git warp

Because no specific branch in the remote repository was specified just like in (a) then all branches are pulled, but because a local name was provided then this becomes a branch group.

Branch groups could be used to extend the branch namespace as well to avoid clashes with different remote repositories. In this case the branch groups could be a way to arrange branches in a hierarchy so "warp" refer to all branches included in the warp group while "warp/upstream" refer to only one branch. In this case "upstream" and "warp/upstream" would be the same branch if "upstream" was effectively added to the "warp" group, but it doesn't need to be so. And branches in a group don't have to come from the same remote repository either since the source of each branch (the URL) is a per branch attribute.

To make it "easy" on the user, I think that any branch (or tag) down the hierarchy should be used without the "path" leading to it if there is no conflict. We already do that with heads and tags, So if for example the "warp" group contained a branch named "lightspeed" but no such branch (or tag) existed anywhere else then it could be referenced with simply "lightspeed" or "warp/lightspeed".

Then you don't need any strange scheme for diff and merge. Just using "git-diff upstream" or "git-merge origin next" suffice. Oh and I don't think it would be a good idea to have a completely separate namespace for local vs remote aka tracking branches. Maybe in .git/refs/ they should be separate to distinguish which ones are read-only remote tracking ones and which ones are local, but that must not be forced on the UI.

Thinking about it some more, maybe (a) should create a default branch group if the remote repository has more than one branches, say "origin". This way, git-pull without any argument would be the same as "git-pull origin" by default. If "origin" is a single branch then (git-pull" would pull only one branch, but if "origin" is a branch group then all included branches would be pulled.

This becomes formalized as:
	git_pull [<URL>] [<local_name>]

If <URL> includes a branch name then <local_name> is a single branch name. If <URL> doesn't include any branch name then <local_name> becomes a local branch group name containing all branches in the remote repository. If <URL> is specified but not <local_name> then <local_name> is set to "origin" by default, unless it already exists in which case it is an error and the pull fails. If <URL> is not specified then the URL attribute to the specified branch(es) is used. If nothing is specified then "origin" is used for <local_name> by default and URL attribute of the origin branch or the origin branch group is/are used.

*****

OK I think this is enough for now. I know that parts of what I've said can already be found in GIT, but I wanted the explanation to be complete and therefore tentatively coherent.

Previous: Junio C HamanoNext: Junio C Hamano
Message 194 of 240 in “commit: Steer new users toward "git commit -a" rather than update-index”
  1. commit: Steer new users toward "git commit -a" rather than update-indexCarl Worth, Nov 14, 2006
  2. Andy WhitcroftNov 14, 2006
  3. Cleaning up git user-interface wartsCarl Worth, Nov 14, 2006
  4. Shawn PearceNov 14, 2006
  5. Carl WorthNov 14, 2006
  6. Petr BaudisNov 14, 2006
  7. Carl WorthNov 14, 2006
  8. Junio C HamanoNov 15, 2006
  9. Petr BaudisNov 15, 2006
  10. Junio C HamanoNov 15, 2006
  11. Nicolas PitreNov 15, 2006
  12. Jakub NarebskiNov 15, 2006
  13. Santi BéjarNov 15, 2006
  14. Jakub NarebskiNov 15, 2006
  15. Petr BaudisNov 16, 2006
  16. Nicolas PitreNov 15, 2006
  17. Petr BaudisNov 15, 2006
  18. Jakub NarebskiNov 15, 2006
  19. Karl HasselströmNov 15, 2006
  20. Carl WorthNov 15, 2006
  21. Jakub NarebskiNov 15, 2006
  22. Shawn PearceNov 15, 2006
  23. Carl WorthNov 15, 2006
  24. Steven GrimmNov 17, 2006
  25. Junio C HamanoNov 17, 2006
  26. Petr BaudisNov 17, 2006
  27. Karl HasselströmNov 14, 2006
  28. Nicolas PitreNov 14, 2006
  29. Jakub NarebskiNov 14, 2006
  30. Nicolas PitreNov 14, 2006
  31. Jakub NarebskiNov 14, 2006
  32. Nicolas PitreNov 14, 2006
  33. Carl WorthNov 14, 2006
  34. Jakub NarebskiNov 14, 2006
  35. Nicolas PitreNov 14, 2006
  36. Junio C HamanoNov 14, 2006
  37. Nicolas PitreNov 15, 2006
  38. Junio C HamanoNov 15, 2006
  39. Michael K. EdwardsNov 15, 2006
  40. Nicolas PitreNov 15, 2006
  41. Junio C HamanoNov 15, 2006
  42. Linus TorvaldsNov 15, 2006
  43. Jakub NarebskiNov 15, 2006
  44. Josef WeidendorferNov 15, 2006
  45. Petr BaudisNov 15, 2006
  46. Josef WeidendorferNov 15, 2006
  47. Linus TorvaldsNov 15, 2006
  48. Nicolas PitreNov 15, 2006
  49. Shawn PearceNov 15, 2006
  50. Marko MacekNov 15, 2006
  51. Junio C HamanoNov 15, 2006
  52. Shawn PearceNov 15, 2006
  53. Marko MacekNov 16, 2006
  54. Junio C HamanoNov 16, 2006
  55. Jakub NarebskiNov 17, 2006
  56. SeanNov 15, 2006
  57. Andy ParkinsNov 15, 2006
  58. Linus TorvaldsNov 15, 2006
  59. Michael K. EdwardsNov 15, 2006
  60. Linus TorvaldsNov 15, 2006
  61. Nicolas PitreNov 15, 2006
  62. Linus TorvaldsNov 15, 2006
  63. Carl WorthNov 15, 2006
  64. Junio C HamanoNov 15, 2006
  65. Nicolas PitreNov 15, 2006
  66. Junio C HamanoNov 15, 2006
  67. Nicolas PitreNov 15, 2006
  68. Karl HasselströmNov 17, 2006
  69. Linus TorvaldsNov 15, 2006
  70. Carl WorthNov 15, 2006
  71. Shawn PearceNov 15, 2006
  72. Linus TorvaldsNov 15, 2006
  73. Nicolas PitreNov 16, 2006
  74. Linus TorvaldsNov 16, 2006
  75. Nicolas PitreNov 16, 2006
  76. Michael K. EdwardsNov 16, 2006
  77. Andreas EricssonNov 16, 2006
  78. Carl WorthNov 16, 2006
  79. Michael K. EdwardsNov 16, 2006
  80. Carl WorthNov 16, 2006
  81. Junio C HamanoNov 17, 2006
  82. Carl WorthNov 17, 2006
  83. Johannes SchindelinNov 17, 2006
  84. Junio C HamanoNov 17, 2006
  85. Shawn PearceNov 17, 2006
  86. Junio C HamanoNov 17, 2006
  87. SeanNov 15, 2006
  88. Jerome LovyNov 21, 2006
  89. Theodore TsoNov 16, 2006
  90. Andreas EricssonNov 16, 2006
  91. Linus TorvaldsNov 16, 2006
  92. Carl WorthNov 16, 2006
  93. Linus TorvaldsNov 16, 2006
  94. SeanNov 16, 2006
  95. Anand KumriaNov 16, 2006
  96. Junio C HamanoNov 15, 2006
  97. Theodore TsoNov 16, 2006
  98. Junio C HamanoNov 16, 2006
  99. Alexandre JulliardNov 16, 2006
  100. Petr BaudisNov 16, 2006
  101. Alexandre JulliardNov 16, 2006
  102. Jakub NarebskiNov 17, 2006
  103. Alexandre JulliardNov 17, 2006
  104. Jakub NarebskiNov 17, 2006
  105. Han-Wen NienhuysNov 16, 2006
  106. Jakub NarebskiNov 16, 2006
  107. Junio C HamanoNov 16, 2006
  108. Han-Wen NienhuysNov 16, 2006
  109. Junio C HamanoNov 16, 2006
  110. Junio C HamanoNov 16, 2006
  111. Junio C HamanoNov 16, 2006
  112. Linus TorvaldsNov 16, 2006
  113. Junio C HamanoNov 16, 2006
  114. Han-Wen NienhuysNov 16, 2006
  115. Junio C HamanoNov 16, 2006
  116. Han-Wen NienhuysNov 16, 2006
  117. Han-Wen NienhuysNov 16, 2006
  118. Jakub NarebskiNov 17, 2006
  119. Han-Wen NienhuysNov 24, 2006
  120. Jakub NarebskiNov 24, 2006
  121. Johannes SchindelinDec 5, 2006
  122. Junio C HamanoDec 5, 2006
  123. pretty-formats: add 'format:<string>'Johannes Schindelin, Feb 23, 2007
  124. Han-Wen NienhuysFeb 23, 2007
  125. Johannes SchindelinFeb 23, 2007
  126. Robin RosenbergFeb 23, 2007
  127. Johannes SchindelinFeb 24, 2007
  128. Junio C HamanoFeb 23, 2007
  129. Johannes SchindelinFeb 23, 2007
  130. Junio C HamanoFeb 23, 2007
  131. Johannes SchindelinFeb 23, 2007
  132. Linus TorvaldsNov 16, 2006
  133. Han-Wen NienhuysNov 16, 2006
  134. Linus TorvaldsNov 16, 2006
  135. multi-project repos (was Re: Cleaning up git user-interface warts)Han-Wen Nienhuys, Nov 16, 2006
  136. Linus TorvaldsNov 16, 2006
  137. Junio C HamanoNov 16, 2006
  138. Linus TorvaldsNov 16, 2006
  139. Shawn PearceNov 17, 2006
  140. Linus TorvaldsNov 17, 2006
  141. Carl WorthNov 17, 2006
  142. Shawn PearceNov 17, 2006
  143. Carl WorthNov 17, 2006
  144. Shawn PearceNov 17, 2006
  145. Marko MacekNov 17, 2006
  146. Junio C HamanoNov 17, 2006
  147. Junio C HamanoNov 17, 2006
  148. Shawn PearceNov 18, 2006
  149. Junio C HamanoNov 18, 2006
  150. Shawn PearceNov 18, 2006
  151. Johannes SchindelinNov 16, 2006
  152. Junio C HamanoNov 16, 2006
  153. Johannes SchindelinNov 17, 2006
  154. Linus TorvaldsNov 16, 2006
  155. Linus TorvaldsNov 16, 2006
  156. Johannes SchindelinNov 16, 2006
  157. Linus TorvaldsNov 17, 2006
  158. Carl WorthNov 17, 2006
  159. Johannes SchindelinNov 17, 2006
  160. Petr BaudisNov 17, 2006
  161. Johannes SchindelinNov 17, 2006
  162. Han-Wen NienhuysNov 16, 2006
  163. Han-Wen NienhuysNov 16, 2006
  164. Jakub NarebskiNov 17, 2006
  165. Linus TorvaldsNov 16, 2006
  166. Junio C HamanoNov 16, 2006
  167. Linus TorvaldsNov 16, 2006
  168. Junio C HamanoNov 16, 2006
  169. Linus TorvaldsNov 16, 2006
  170. Carl WorthNov 16, 2006
  171. Johannes SchindelinNov 16, 2006
  172. Linus TorvaldsNov 16, 2006
  173. Han-Wen NienhuysNov 17, 2006
  174. Junio C HamanoNov 17, 2006
  175. Han-Wen NienhuysNov 17, 2006
  176. Petr BaudisNov 17, 2006
  177. Carl WorthNov 17, 2006
  178. Carl WorthNov 17, 2006
  179. Linus TorvaldsNov 17, 2006
  180. Han-Wen NienhuysNov 17, 2006
  181. Michael K. EdwardsNov 17, 2006
  182. Michael K. EdwardsNov 17, 2006
  183. Junio C HamanoNov 17, 2006
  184. Michael K. EdwardsNov 18, 2006
  185. Jakub NarebskiNov 17, 2006
  186. Petr BaudisNov 16, 2006
  187. Petr BaudisNov 15, 2006
  188. Nicolas PitreNov 15, 2006
  189. Linus TorvaldsNov 15, 2006
  190. Nicolas PitreNov 15, 2006
  191. Anand KumriaNov 16, 2006
  192. Junio C HamanoNov 14, 2006
  193. Junio C HamanoNov 14, 2006
  194. Nicolas PitreNov 15, 2006
  195. Junio C HamanoNov 15, 2006
  196. Shawn PearceNov 15, 2006
  197. Junio C HamanoNov 15, 2006
  198. Johannes SchindelinNov 15, 2006
  199. SeanNov 15, 2006
  200. Nicolas PitreNov 15, 2006
  201. Junio C HamanoNov 15, 2006
  202. Andy ParkinsNov 15, 2006
  203. Junio C HamanoNov 15, 2006
  204. Nicolas PitreNov 15, 2006
  205. Carl WorthNov 15, 2006
  206. Junio C HamanoNov 15, 2006
  207. Carl WorthNov 15, 2006
  208. Petr BaudisNov 16, 2006
  209. Robin RosenbergNov 16, 2006
  210. Petr BaudisNov 16, 2006
  211. Han-Wen NienhuysNov 16, 2006
  212. Andy ParkinsNov 15, 2006
  213. Jakub NarebskiNov 15, 2006
  214. Andy ParkinsNov 15, 2006
  215. Karl HasselströmNov 15, 2006
  216. Andy ParkinsNov 15, 2006
  217. Nicolas PitreNov 15, 2006
  218. Junio C HamanoNov 15, 2006
  219. Nicolas PitreNov 15, 2006
  220. Karl HasselströmNov 16, 2006
  221. Alan ChandlerNov 18, 2006
  222. Junio C HamanoNov 15, 2006
  223. Andy ParkinsNov 15, 2006
  224. Petr BaudisNov 16, 2006
  225. Andreas EricssonNov 15, 2006
  226. Jakub NarebskiNov 15, 2006
  227. Petr BaudisNov 16, 2006
  228. Petr BaudisNov 16, 2006
  229. Junio C HamanoNov 16, 2006
  230. Petr BaudisNov 16, 2006
  231. Junio C HamanoNov 16, 2006
  232. Petr BaudisNov 16, 2006
  233. Junio C HamanoNov 17, 2006
  234. Han-Wen NienhuysNov 17, 2006
  235. Alan ChandlerNov 18, 2006
  236. Junio C HamanoNov 14, 2006
  237. Shawn PearceNov 15, 2006
  238. Richard CURNOWNov 16, 2006
  239. Johannes SchindelinNov 16, 2006
  240. Petr BaudisNov 16, 2006

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.