I'm aware that the concept can be difficult to grasp and that the cli commands seem weird at first.
Once it clicks however, it's an absolutely fantastic tool. I'm still often amazed by what is possible with selective resets, diffs, greps, and most impressively interactive rebases. It makes a lot of otherwise difficult tasks much easier, and more elegant.
Git is IMO one of the most important pieces of software made in the last couple of decades and should be celebrated more for it.
I disagree with this. I think the basic concept of Git is beautiful, but the implementation of some of the derivative operations are distinctly inelegant.
For example, I hate the use of "ours" and "theirs" in merges and rebases. I understand the theory of why it works the way it does and why it's different when merging versus rebasing, but I just think it's downright confusing, and I still have to double check every time to make sure I accept the right changes. I don't understand why they couldn't just use the branch name (or branch + commit hash).
One thing that confuses me about Git (but I guess isn't unique to it) is what happens when you merge and "git show" the merge commit. It seems the classes of changes are:
- things that were the same on both sides so aren't in the diff
- things that were different but auto merged, and aren't in the diff
- things that were different, were auto merged, and are in the diff
- merge conflicts
But how did it distinguish the last 3? And how does it get so confident about #2 that it doesn't show them and there isn't a single command to show them?
When hg was more popular I knew someone working on Google Code who told me it was better because it didn't have rebases, but I'm pretty rebases and linear history are safer than this.
Something that comes to mind is that Github, as part of a "papercuts" initiative to fix small things, added an arrow that points from the "theirs" branch to the "our" branch in pull requests. That was such a huge improvement for me.
I agree that the concept behind git is powerful and elegant. I very much disagree that the implementation of git is elegant. For example: how many things does `git checkout` do? And I still don't understand what the point is of having a staging area. Or why I need to edit files in order to provide Git with instructions on what to do when it rebases. Or why adding hunks is so much more difficult than adding complete files.
Git is built upon a powerful and beautiful concept, but the Git CLI is just about the worst viable interface to that concept that you can build. There's a reason that there are so many other Git UIs, such as Magit, SourceTree, GitKracken, etc.
> I still don't understand what the point is of having a staging area.
Nor do my coworkers who keep committing whitespace changes and machine-specific configuration changes unrelated to the tasks at hand.
For a more serious answer: I find it extremely useful to be able to control what goes exactly into each commit. Sometimes I refactor more than one part of the code at the same time. If one part passes tests and another one doesn't, I can commit just the one that does. If I spot an issue in one part of the codebase and I add a TODO or FIXME in a comment, or if add some logging, or some other inconsequential change, I can leave them in the working copy for later while still adding "atomic" changes to the repo.
But by far the most use I get out of it is as a last chance of reviewing the code I just wrote, or as a way of checking the results of an automatic merge before the actual merged commit gets written.
You would still be able to do that without a staging area by having `git commit` take roughly the same arguments as `git add`. So instead of running `git add foo bar baz` followed by `git commit`, you'd just write `git commit foo bar baz`, and it'd launch $EDITOR for the commit message.
My understanding is that other distributed version control systems, such as Mercurial or Bazaar, take a similar approach to the above.
The staging area is so you can get your upcoming commit pretty enough (by adding/removing hunks etc) ahead of time before creating it. If you were previously on SVN where there was no intermediate step between creating a commit and putting it in official server history, I think you'd appreciate all the safety you could get.
It does seem like it'd work without it, since there's commit --amend.
You might get a kick out of this. Tech Talk by Linus Torvalds at Google presenting Git: https://www.youtube.com/watch?v=4XpnKHJAok8 . He goes into his thought process of the pains with existing version control systems and how Git goes to address their shortcomings.
Not sure about that - yeah, git is a powerful tool, but I can't help thinking that lots of things could have been done in a more straightforward and less confusing way. Such as the "double responsibility" of "git checkout" which has recently been split into "git switch" (for switching branches) and "git restore" (for reverting files).
I think the core concepts behind git are extremely elegant, but the complexity of using it effectively and the very large number of operations make it substantially less elegant.
The CLI is so confusing that Stackoverflow has a bunch of questions for things that should be easy or trivial by default. Last thing I would call git is "elegant".
I knew there would be people commenting on this. But I don't think something has to be intuitive for newcomers to be elegant.
There are also posts here mentioning vim, which to most people is weird and useless at first.
Some tools takes effort to understand, but once you put in the effort, they become tremendously powerful.
I would say that they are elegant in that they allow you to do something otherwise difficult in an effortless and obvious way. Both vim and git does exactly that - once you've gotten to know how they work.
It's not intuitive to newcomers nor to experienced users. Its interface does not make sense; it can only be memorized. The data structure is beautiful; the tool is ugly.
Those commands look quite arcane to my eye. In Mercurial we do:
> hg pull --force <project-to-union-merge>
> hg merge
> hg commit
-----
So in a sense you are right, that's exactly the point of contention. However, simple (and hard) things in Git are done in a complicated and non-obvious way, which require you to memorize a bunch of commands and flags which require understanding the internal implementation of git. There are much easier and intuitive ways of doing version control, and Mercurial proves it.
As a side note, I can't be bothered to look it up right now but iirc even Torvalds said that originally Git's CLI was not actually meant to be used by end users (rather, another abstraction layer on top would provide a friendlier approach to version control). But people ended up using it as it was, for various reasons.
I'm aware that the concept can be difficult to grasp and that the cli commands seem weird at first.
Once it clicks however, it's an absolutely fantastic tool. I'm still often amazed by what is possible with selective resets, diffs, greps, and most impressively interactive rebases. It makes a lot of otherwise difficult tasks much easier, and more elegant.
Git is IMO one of the most important pieces of software made in the last couple of decades and should be celebrated more for it.