1. 34
  1.  

  2. 17

    I agree with the author, git concepts are non-orthogonal and subtle. When I think of quality UI software, I don’t think of git.

    That being said, I would not get rid of the index. The index is the primary reason I use git. I think git add -p is an invaluable tool. If you don’t use it, you’re missing out.

    1. 13

      I agree that git is awful to learn, but removing staging seems unnecessary. Even worse, they use funky flags where git uses commands, and they did away with push/pull in favor of publish/???.

      I’m not impressed. I’ll stick with git and will continue to teach people how to use git instead of some seemingly better shell.

      1. 3

        Yeah, it didn’t really feel to me like they changed much fundamentally. They just added some superficial aliases so you don’t have to run as many commands. I’ll write my own aliases when I need them.

      2. 8

        I’m perfectly happy using mercurial, which doesn’t have a staging area. Whenever I use git, I get annoyed because it has this extra useless concept. Mercurial has “hg commit -i”, which is analogous to “git add -p”, to commit only a subset of the changes to the working directory.

        1. 5

          I’ve always found a lot of utility in being able to stage certain things at once. Sometimes I make large changes without thinking about actual commits until I get to the end of a workstream, and having that all as one commit just seems generally not great, especially when there are atomic components that were tangentially related to the main work at best (like cleaning up a configuration file, or refactoring a particularly hairy section of code).

          Mainly breaking things up like that seems like the courteous thing to do for your fellow developers, because that way if you’re ripping out a large component and want to do it quickly with reverts, you don’t pull out the secondary changes by accident too. And you can also generally write better, more relevant commit messages too.

          1. 5

            You can do that workflow in mercurial as well using “hg histedit” and “hg commit –amend”.

            Having a staging area isn’t related to the workflow and just adds another concept to learn when learning or teaching the tool.

            1. 7

              You can also do git commit --amend if you want to amend a commit, however you don’t have a tool for implementing a commit queue in hg.

              If I have four things I’ve touched and I want to commit them separately, I want to verify that each of these things are in fact separate commits. I do not want to commit four things, and then try to uncommit them, and re-commit them once I’ve figured out what they should look like.

              In git, I can add -p the first one, then stash the rest, run my program and verify it works as I expect, then commit just that staged bit (or change it some more). Then I can pop the stash and move on to the next commit.

              This concept is useful to me. I can emulate it by creating four separate branches, or by copying my files around, but I find it actually useful to think in terms of the git concept of a stage so that this kind of committing is obvious to me. Tools that generate new intuition to the programmer are like candy to me.

              1. 2

                Given that I very much use hg with a commit queue, I can’t really agree, though I haven’t tried it much with the base command set (I use evolve).

                Still, the way I do something like that is to make my commits, then update to the first commit and test, then update to the next commit (by hash or using the children(.) revset) and test, etc. Then I can land any or all of them with one push. None of that requires evolve, btw, but in practice I will usually find that I’ve mixed up the changes a bit and have to move pieces between them, and that’s much easier to do with evolve and ©histedit.

                You’re using the stage+stash as your queue / working area. I’m using the actual dag. When doing so, it’s easy to get mixed up with what is “current work” vs stuff I’m basing the current work on, but hg has phases, which make it easy to distinguish work in progress vs base. (I uses aliases for it, but hg log -r 'not public() and only(.)' gives you a basic patch queue listing.)

                1. 1

                  In git, I can add -p the first one, then stash the rest, run my program and verify it works as I expect, then commit just that staged bit (or change it some more). Then I can pop the stash and move on to the next commit.

                  I find this the most confusing part of git, fwiw. I can never remember whether stash is going to stash changes that have been added or just changes that have not. Worse, stashing and unstashing seems to change which things have been added, which breaks my mental model of what stash is supposed to do.

                  1. 4

                    which breaks my mental model of what stash is supposed to do.

                    This is a variation on the “X isn’t intuitive”, and it doesn’t really offer any option to me in having a discussion about it.

                    Can I agree that the user-interface is bad without also agreeing that we need to hide/get-rid-of the index?

                    I can never remember whether stash is going to stash changes that have been added or just changes that have not. Worse, stashing and unstashing seems to change which things have been added

                    Read the manual page carefully. The first sentence begins: Use git stash when you want to record the current state of the working directory and the index, but want to go back to a clean working directory and that’s exactly what it does, but you need to understand what the index is.

                    The thing that I’m referring to is mentioned: If the --keep-index option is used, all changes already added to the index are left intact and that -p implies this.

                    1. 1

                      This is a variation on the “X isn’t intuitive”, and it doesn’t really offer any option to me in having a discussion about it.

                      Ok, I’ll be specific. The man page says: “Remove a single stashed state from the stash list and apply it on top of the current working tree state, i.e., do the inverse operation of git stash save. The working directory must match the index.”

                      $ git status
                      # On branch master
                      # Changes to be committed:
                      #   (use "git reset HEAD <file>..." to unstage)
                      #
                      #       modified:   foo
                      #
                      # Changes not staged for commit:
                      #   (use "git add <file>..." to update what will be committed)
                      #   (use "git checkout -- <file>..." to discard changes in working directory)
                      #
                      #       modified:   bar
                      #
                      $ git stash
                      Saved working directory and index state WIP on master: b12ed82 test
                      HEAD is now at b12ed82 test
                      $ git stash apply
                      # On branch master
                      # Changes not staged for commit:
                      #   (use "git add <file>..." to update what will be committed)
                      #   (use "git checkout -- <file>..." to discard changes in working directory)
                      #
                      #       modified:   bar
                      #       modified:   foo
                      #
                      no changes added to commit (use "git add" and/or "git commit -a")
                      

                      This is not what the word “inverse” conventionally means; it is extremely confusing to have an operation described as an “inverse” that doesn’t actually invert the thing it is supposedly the inverse of.

                      Can I agree that the user-interface is bad without also agreeing that we need to hide/get-rid-of the index?

                      I don’t think so, unless you have a better proposal for how to improve it.

                      1. 3

                        it is extremely confusing to have an operation described as an “inverse” that doesn’t actually invert the thing it is supposedly the inverse of.

                        I don’t see why that means I have to agree that the index is bad.

                        Can I agree that the user-interface is bad without also agreeing that we need to hide/get-rid-of the index?

                        I don’t think so, unless you have a better proposal for how to improve it.

                        “People understand things I don’t, so we need to get rid of them”.

                        I find that attitude really off-putting.

                        1. 1

                          I don’t see why that means I have to agree that the index is bad.

                          Well, the part that it doesn’t invert is the index. As far as I can see the index causes this problem and removing it would solve the problem.

                          “People understand things I don’t, so we need to get rid of them”.

                          That’s not what I’m saying (and I’ll thank you not to put words in my mouth). To agree the user-interface is bad, you must believe a better user-interface is possible (otherwise the idea of “bad” is meaningless). To believe that a better user-interface is possible you must believe that a specific possible alternative user-interface is better. If you don’t believe gitless is better, which possible alternative user-interface do you believe is better?

                          1. 1

                            This is where git stash –keep-index comes in handy. Stash then only would apply to changes to bar.

                            1. 1

                              Sure, and apparently there’s also a flag to the load to restore changes to the index. But neither of these is the default; fundamentally, stash is clearly confused about whether it’s operating on the index or the working copy or both. If even git’s own commands can’t get staged vs unstaged straight, what hope do us poor users have?

                              1. 1

                                I won’t argue that git is the most intuitive tool by any means, but it does have the ability to address the needs at the least.

                                That said, the git log man page to this day, after 9 years of use still contains things I don’t understand after having read through it numerous times.

                  2. 1

                    Both the mq and the shelve extension implement commit queues for hg and they come with hg’s default installation. Commit queues are a power user so it’s fine if this isn’t front and center for a new user yet but they are definitely there.

              2. 4

                Tools give us power and allow us to be individually more efficient, but they require we learn new skills which can take time and make us struggle which is not something many intermediate programmers are used to.

                To paraphrase:

                I’m perfectly happy using basic which doesn’t have lambdas or macros. Whenever I use lisp, I get annoyed because it has this extra useless concept. Basic has goto and gosub which is analogous to the use of lambadas and functions that I want to use.

                The real issues are whether, having this tool of thought you are more efficient (I am; others say they are) enough to make it worth learning (Others are more convinced than me on this point) or worth fighting inertia (i.e. Git is popular, so it is useful to think in git so that I’m better able to work in git).

                As a specific example, I never want to hg commit -i in git – I’ve checked my history and I’ve never typed git commit -p (which works the same way), and I noticed whenever I use git add -p it’s followed by a git stash so I’m pretty certain my goal is to make sure that my single staged commit works in isolation (i.e. if someone just cherry picks this commit, will it work?) This is important because we don’t really have patches in git (which actually solve this problem).

                1. 5

                  I wonder how we can better talk about this conflict. Is the investment of learning worth the trouble in later efficiency? We talk about usability often without putting it into context. Git is worth learning for a developer, because you use it everyday. The banking website that you use once a month should be much more aligned with the concepts that you can be expected to know, even if that makes you ineffective.

                  1. 1

                    This is something I often wonder about.

                    Too many people respond to things they do not understand with an opinion about them: How much they don’t like them. When I see someone do something I cannot do, I want to learn how they do it; If someone can program faster, and their programs are shorter or more correct than mine, I want to know how.

                    If they say “I use the git index”, then I know I need to learn it. Whatever opinion I might have had goes right out the window at that point.

                  2. 2

                    The need is not to have a stage or stash or whatever. As the paper says, there are highlevel goals that developers want to accomplish. The stage and stash are tools that can be used to accomplish those goals, but there are a number of other ways. And you can design systems with more or fewer separate concepts. I prefer systems with fewer concepts that can be used in flexible ways. For that reason, I prefer using the straight dag as much as possible, and figuring out the minimum necessary extensions needed to make the dag handle my goals. The stage feels like a big separate concept to me – not wrong, really, but big and different and I’d rather eliminate it if possible. Similarly, the stash feels like it explodes out the set of possible states unnecessarily. You need some extra states, but I’d rather express them in terms of dag nodes than some completely different thing.

                    Honestly, I’d like to think of my working directory state as just another node in the dag, one whose hash and exact contents are only determined when necessary. I should be able to use it the same way as any other node in the graph. True, if you go whole hog on immutability, then you need to record a hash for every single keystroke that modifies a file, but I like to think of not having those nodes as an optimization on top of the conceptual dag containing them. And it turns out that you kind of want the same optimization for other nodes – for example, if you rebase a patch stack on top of upstream changes a dozen different times, then all those intermediate nodes (almost length of patch stack x number of rebases of them) are similarly uninteresting, and I would happily discard them even if it means edges in the dag sometimes represent more than one intermediate (garbage collected) node.

                    1. 1

                      The need is not to have a stage or stash or whatever.

                      I certainly don’t have this need, to “not have a stage or stash or whatever” and so I reject the theory that this need exists.

                      there are highlevel goals that developers want to accomplish

                      I think this kind of thinking leads to mistakes.

                      I don’t want to accomplish any of them: I want to show my code to someone, or I want my feature to be on the production system. Everything else is a means to that end, and so I look at how I can do the things that I want. Tools enable that.

                      I prefer systems with fewer concepts that can be used in flexible ways.

                      If we say we should prefer hg because it is simpler than git, we are making a mistake. neither “git” nor “hg” are a calculus for version control, but both a set of very messy methods. If you want something mathematically satisfying – the scheme of version control, you should look at patch theory because it may fill that need.

                      However I have things to do now, and that means I’m looking at the common lisps of the world, not the schemes: I want a robust vocabulary, so I can say what I mean, and get what I want; succinct enough to avoid errors, but I do not want to do version control in brainfuck either.

                      Both git and hg are robust, but git is more robust. That’s important to me. Can you tell a computer what to do without an index? Sure, but there was a time when programmers used punch cards and paper tape. I certainly don’t want to return to that.

                      I’d like to think of my working directory state as just another node in the dag,

                      I’m not interested in this at all.

                      1. 1

                        I am not making most of the arguments you are disagreeing with. In fact, we are saying the same thing in your first two quotes. But never mind that.

                        While to me, hg feels conceptually simpler yet equally powerful to git, that was not my point. (Nor did I say it – where did I mention hg?)

                        I am saying that a small number of concepts, flexibly applied, results in a better tool than one built from a larger set of nonorthogonal concepts that cover the same space (ie, the space of tasks you actually need to accomplish.)

                        It is also the case that once you use a tool successfully for long enough, it gets harder to distinguish what you’re doing from how you’re doing it, and alternative ways of accomplishing the same thing appear to be pointless and overcomplicated, because you are evaluating them according to how well they mimic your current tools rather than how well they accomplish the task at hand. Perhaps you are doing that here. Perhaps I am too unfamiliar with the git toolkit to see some large advantages it has.

                        1. 1

                          hg feels conceptually simpler yet equally powerful to git, that was not my point. (Nor did I say it – where did I mention hg?)

                          Given that I very much use hg with a commit queue, I can’t really agree, though I haven’t tried it much with the base command set (I use evolve [a disabled-by-default extension that emulates something that has been in git since the beginning]).

                          I am saying that a small number of concepts, flexibly applied, results in a better tool than one built from a larger set of nonorthogonal concepts that cover the same space (ie, the space of tasks you actually need to accomplish.)

                          I’m not going to disagree with that theory, but it’s clearly not sufficient:

                          Git has a smaller number of concepts than hg: You can tell because things that are evocations of the alien things like the index require extensions in hg to be implemented.

                          Patch theory represents what might be the smallest possible number of concepts. It is worth some study and makes hg feel quite pointless because where patch theory also highlights something fundamentally wrong with git, hg has the exact same thing wrong.

                          It is also the case that once you use a tool successfully for long enough, it gets harder to distinguish what you’re doing from how you’re doing it, and alternative ways of accomplishing the same thing appear to be pointless and overcomplicated, because you are evaluating them according to how well they mimic your current tools rather than how well they accomplish the task at hand.

                          I think this is a silly way to think about things, but history is littered with people who cannot tell the difference between their opinions and reality.

                  3. 3

                    I often stage changes at a time, make some more changes, stage those, etc., before finally having something I want to commit. (i.e. I don’t immediately follow git add -p with git commit) Sometimes this process itself is enough to make me change the direction of what I’m doing or decide I don’t want to make a commit at all.

                    1. 3

                      I use “hg commit –amend” for that. If I end up deciding not to commit anything at all, “he strip” will delete the WIP commit.

                      The evolve extension also provides “hg uncommit”, to remove files from a commit.

                      1. 1

                        Sounds like we both have something that works for us then!

                  4. 4

                    git gui is my prefered way to use git. Gitg/gitk/cola are also invaluable. Github client was good originally, but thry simplified whioe also some how maing it harder for me to use.

                    1. 2

                      I think git add -p is an invaluable tool.

                      And it gets even better with Magit, if you’re an Emacs user

                    2. 12

                      I very much disagree with the representation of git. First, realize that git is just an immutable graph. Commits are nodes and the git commands simply manipulate these nodes. The staging area and the rest that the author describes is a lot more deducible if you consider the requirements for creating a new node.

                      I’ve not run into a problem helping people with a git problem that hasn’t been solved by drawing out the commits as a graph on the whiteboard.

                      1. 14

                        drawing out the commits as a graph on the whiteboard.

                        Whether one thinks this is a good thing or a bad thing is a pretty accurate litmus test for git appreciation.

                        1. 4

                          The TortoiseSVN client that I happened to use before using git did draw a graph of commits. But in SVN, you couldn’t easily manipulate it. This made the whole experience with SVN quite unintuitive. With git the internal model and the graphical representation had quite a few more things in common. For me, that made git much more intuitive than any other system I have used so far.

                          1. 3

                            I saw this comment late last night, and it’s stuck with me. I think it’s very interesting.

                            I’ve always felt similar to @goalieca in that git has mostly made sense to me, even the commands people complain about. But then again I also tend to think of git as being very visual, even though it’s a command-line tool.

                          2. 1

                            I envy you because I want to understand git’s ASCII graphs but even after years I cannot wrap my brain around what they mean and how they would “look” in a 3D space. I find that last bit is necessary for me to understand conceptual graphs.

                            1. 3

                              Draw each commit as a node. A commit will have one arrow pointing into it (the previous commit). A merge commit will have 2. Each commit node has a diff based on the previous commit. For a merge it will be the resolution of the differences.

                              I tend to draw vertically with time as a sort of pseudo y-axis. Branches are horizontal.

                              For rebasing I like to draw the original line then cut that line and draw a new one for where I’m rebasing on. Same thing for cherry pick.

                              Git log and the ASCII graphs are confusing because it is a 1.5D projection.

                          3. 8

                            The thing I don’t get about the gitless rationale is that it’s claiming to “fix” issues with the git conceptual model by papering over (mainly) the staging area. But understanding how staging works would fix most of the points brought up.

                            Of course that’s good evidence for a “stage-less git” being a decent idea, but now it’s a different thing

                            Lots of git weirdness exists if you don’t know how the staging area works, because it’s such a core part of the git workflow! A git-like without staging isn’t a bad idea, but it’s not “git better explained”, it’s just a different tool.

                            I can remove half the functionality of Photoshop to get paint, but that doesn’t make it “better-UX Photoshop”.

                            1. 4

                              Somewhat related, why doesn’t any VCS I know better expose the concept of resolving merge concepts. In particular, when I review a merge, there’s no way to see what the user had to resolve manually, which is the most important thing to review.

                              Similarly, when I do a complex merge, I feel like I am not using a VCS at all. It’s impossible to see only my changes as I work. Sometimes I have to do extensive changes to fix merge conflicts. I want these changes committed separately, in several “commits” distinct from the merge itself somehow. And yet, I don’t want to do these changes before the merge, as they are blind changes that won’t compile.

                              In short, merge is too blunt of a tool.

                              I am very aware why this is impossible with the pure graph model, yet I feel it’s important enough to warrant altering the purity of the graph model. Or introduce different types of nodes, or something.

                              1. 6

                                How can anyone do a study of the design basis of Git without a single reference to its origin as a clone of BitKeeper? It’s kind of mind boggling.

                                1. 9

                                  It’s not a history of the design of git? “How we got here” could be very interesting, but it’s not really relevant to “what users must learn”. Whether the git model was inspired by bitkeeper or a mescaline flavored dream sequence, I still need to learn it to understand git.

                                  1. 1

                                    To me, that’s such a strange line of reasoning. First of all in scientific paper, it’s good to document so that people who do want to look at the original concepts have a source. So they should have cited BK when they discussed the distributed character of Git. Second, if you are studying the design structure of Git, it helps a lot to know that many of the same operations were copied from BK or modified from BK - this gives you some intuition about design decisions. I can’t imagine anyone studying e.g. RISC V without at least mentioning MIPS. Anyways if it doesn’t interest you, that’s up to you, but to me one of the basic problems of the CS literature is that it’s allergic to the kinds of scholarship that you see in mathematics or traditional engineering subjects.

                                    1. 8

                                      I guess. The chrome team has a paper on how users react to invalid certificate warnings, but they don’t mention modular exponentiation, even though that’s how we decide if a certificate is valid or not.

                                      1. 5

                                        The mechanism of certificate signing is irrelevant to the UI of presenting the results of that check. The history of git is extremely relevant to its current state and structure.

                                      2. 2

                                        I’m with Ted on this. Users don’t need to know the history of something to understand how it works. Hell, many of the slowest ones still use Windows just fine whereas I just recently found the full (?) story behind its development and architecture in past year. Piece by piece over long period of time. I figured out how to use most of it in days, though. Just need to know what inputs cause what outputs with what assumptions and contexts.

                                        1. 2

                                          But humans aren’t historical-less robots!

                                          We have associations, and memories, and operate in the future with a loud, resounding beat of the past.

                                          Mentioning the historical context that git was produced in, reveals why for certain users (e.g. linux developers, many open source developers that interacted with it) grabbed onto git when there were many other interfaces for version control available.

                                          Read the abstract of this paper, it even mentions that it’s trying to figure out why git is popular in the first sentences. Examining the history of git will elucidate this research immensely. This paper is just someone that wanted to “improve git UI” and come up with why it was worthy of academia after the fact.

                                          1. 2

                                            “it even mentions that it’s trying to figure out why git is popular in the first sentences.”

                                            It’s most likely the Worse is Better effect. Same reason C is popular: it came with UNIX. The OS kernel that got the most contributions and adoption used git. That’s enough reason for git to take off. Add the Bitkeeper shenanigans with associated media coverage of git as alternative to get more people joining in. That’s before I even consider technical reasons people might use git. Such explorations you refer to might reveal that.

                                            Yet, testing your claim, I was able to use Windows at expert level without knowing it was an OpenVMS clone merged with DOS and OS/2 emulation developed on OS/2 with support and inspiration from both Xenix and AS/400 they used internally to manage their operation. I went nearly its whole existence without knowing those things. Even now, as the big picture amazes me, I still don’t need to know that. I just need to know what Windows does, how one uses it to do that, and preferably common problems and responses I’ll run into. That’s it. Just like most if not all software.

                                            It’s probably the case that nobody needs to know why git is the way it is to understand it. The evolution of git is probably a lot more complex than a simplified model or UI of its workflow plus commands. Like with Windows, you might some benefit understanding its heritage but have no need to. You can still use both as black boxes with heuristics and user-level models for effective use.

                                            1. 3

                                              Read the abstract of this paper, it even mentions that it’s trying to figure out why git is popular in the first sentences.

                                              Yet, testing your claim, I was able to use Windows at expert level [..]

                                              It’s fine to reject that people need to know why they end up using software, but it doesn’t change that the abstract of this very paper under discussion struggles with that question. And if you’re publishing something stating that people are puzzled why everyone is using git… maybe it’s something they should explore to understand more? Can you see how this paper feels very unfinished to me?

                                              1. 1

                                                And if you’re publishing something stating that people are puzzled why everyone is using git… maybe it’s something they should explore to understand more? Can you see how this paper feels very unfinished to me?

                                                I could see going further if we’re trying to understand specifically why it is the way it is. I just don’t think its prior history has much to do with why majority of GIt users are using Git. I’ve read many of their comments over the years where most of the justifications are what it lets them do vs non-distributed CVS they previously used, get on popular bandwagon effect, a job skill, or their favorite projects are on Git or GitHub. Such reasons are actually technology neutral in that they often apply to why adoption happens for a product regardless of what it does, how, or why. It’s sociologists, psychologists, marketing people, and historians mainly studying that stuff. Those fields would have more information on such patterns for people into that stuff.

                                                There might be some people using it specifically for the model in its original contexts, adaptations, justifications and so on. History will help understand that for acceptance, extension, or rebuttal. I’m just betting these people are so rare in Git’s userbase to be nearly non-existent in an assessment of why most are using it.

                                    2. 2

                                      One that was hacked together in a hurry, too. It shouldn’t surprise anyone it had issues. I heard BitKeeper was recently open-sourced. I never used it so how is it vs the Git it inspired or Mercurial these days? An artifact of history or still worth trying?

                                      1. 3

                                        I immediately preferred mercurial to bitkeeper ten years ago.

                                        1. 6

                                          I immediately preferred mercurial to git for years and years, but after I was forced to use git for a week or two for work-related reasons, now I can’t stand mercurial anymore. I am so unhappy if I have to use mercurial, that I try to avoid working on that project.

                                    3. 3

                                      Charles Bloom has some interesting comments on git on his rambles blog (ctrl + F for “10-18-16 | Maybe” if you’re reading this later)

                                      One of the things I dislike most about git is the ability to rewrite/clean up history. I think it’s a waste of time. I barely ever look at the git log to begin with, I absolutely couldn’t care less if your history is well formatted/free of merge commits/etc. I’m pretty sure I’ve also never checked out an entire old revision to build it so having clean builds 100% of the time is a total non issue too.

                                      But because the ability is there, everyone insists clean history is an important issue and we must spend effort to keep it tidy, and the tools we have for tidying/rewriting history are dangerous and destructive. I’ve been using git for a long time now (6 years maybe) and I still occasionally screw it up, and then it takes hours to fix, and the value lost of that time and frustration from a single screw up massively outweighs any positive value I’ve ever gained from having nicely rebased history.

                                      1. 6

                                        I barely ever look at the git log to begin with, I absolutely couldn’t care less if your history is well formatted/free of merge commits/etc.

                                        Can you appreciate that some peole do look at the log and care that it makes sense? When first getting into an existing project, I find it immensely helpful to be able to look back through its history and see where the thing I’m looking at came from, how it developed and what its rationale was.

                                      2. 1

                                        So in gitless, how do I move a diff that I made on the wrong branch onto the correct branch? I agree with not having staging, but I want to have a single working copy and branches only for commits - that’s the model that makes sense to me.