Hacker News new | ask | show | jobs
by alex_smart 947 days ago
Essentially, the problem with git is - it is a tool that is simple in its internals, but with a complex/confusing UI. The only way for someone to feel somewhat in comfortable with git is to have a good conceptual model for how it works internally. Once you have that mental model, you feel like a magician with git, but for beginners, it is a source of endless confusion and fear.
2 comments

GIT is a tool. Like a swiss army knife, it looks tricky and you need some experience to master all what it provides. But you never actually need everything and, surely, you should also shy away from features if you do not really need them. In this respect GIT is a bit like Perl or C++. You have to apply some discipline to avoid unnecessary complexity. Personally, I have never used GIT's "octopus" merge support but I am sure in some situation it may well be a useful feature to have. So I respect that while scratching my head. ;)

Those are basically all commands I am really ever using:

git status

git add

git rm

git commit

git branch

git checkout -t -b ...

git merge

Learn those and you'll mostly good to go.

Sure, I could to rebase my branches all day and make sure my version history looks "pretty" but I find obsessing with the commit history is a major source of complexity people face when using git. Another usual source of confusion is the branching model. However, that totally depends on your organization. GIT is flexible enough to support all kinds of weird development processes but if it comes over as complicated then don't put the blame on the tool but on its users.

I like the in-progress `git checkout` split to `git switch` and `git restore`. (switch and restore are still marked "experimental" in the official documentation in case their arguments change again, but in my experience they are already pretty dependable.) It's much less likely to accidentally do the wrong thing with either of the two replacements. That's one of the things that I think if that split had been done years ago there would be a lot fewer complaints about git being confusing in the base commands; `git checkout` was always an odd duck sadly (it makes sense why it was a single command from a technical sense but it probably shouldn't have ever been from a UX/DX sense).
I like it too, unfortunately it will take decades before books, tutorials and google search results can catch up.

It is the same fate as any cli application that needs to maintain backwards compatibility because it is used both by humans and programmatically as part of scripts. My favorite example of this dd. Most tutorials still show using dd against /dev/sda1 etc instead of using device names as humans should, and meanwhile people keep shooting themselves in the foot.

Although I understand all these commands and can use them, it's a typical Linux tool. Sure, if you understand the internals you can use the tools and the horrendous GUIs that are nothing more than a thin layer of paint.

But a truly user-centric tool would actually help you with something like

"I want to work on a new Feature A" "I want to continue working on Feature B" "I want my changes in the software/product" "I want to review a pull request (haha!) locally, in order to have IDE support." "I did an oopsie and need to go back."

Imagine navigating to a website by specifing its hash, or seeing changes to a PowerPoint file using "git status" and seeing "++slide1.pp". It would be terrible.

It's a low-level tool. Imagine writing code with Microsoft Word. There are layers on top of Git that give you more of what you're looking for.

- https://github.com/extrawurst/gitui

- https://github.com/jesseduffield/lazygit

- https://magit.vc/

> you should also shy away from features if you do not really need them

>Learn those and you'll mostly good to go.

I wasn't really talking about "fancy" features of git, like rebasing history to try to make your history pretty or using things like git bisect. You need to develop basic understanding of git internals, even in the most basic workflow.

I would argue that your list of commands is not in any way complete for being "mostly good to go". At the minimum, you also need to know `git clone`, `git push`, `git pull`, `git fetch`, `git diff`, `git log`, `git blame`, and `git reset` as well. You need to save progress on your current feature branch to context switch to review some PR or analyze some production bug, well add `git stash` to the list. Your boss asked you to hotfix your recent commits onto the release branch? Better not forget `git cherry-pick`.

That brings us to 17 commands (up from the 7 you listed). Fine, it is still a finite number. Can you at least use them as a black box without bothering about the internals? NOPE. You also have to learn a lot of concepts to even understand the help and error messages for these commands - the worktree, the index, the stash, HEAD, ours vs theirs, conflicts, remotes, tracking branches.

Besides, so many commands come with their own gotchas (git checkout will happily overwrite your local changes - without any warning). Some have bad defaults, so you need to figure out which of the hundreds of options that command supports to make it do what you actually want (e.g. git log --oneline and git diff -w -b). Still others have overloaded semantics and do two completely different things (git checkout switches branches but also restores files).

I find it interesting how many tutorials praise the simplicity of git while simultaneously assume nothing goes ever wrong. It's when you have to pull the main branch into the feature branch you're working on (because you sure don't want to do the big merge in a few weeks when you're done, not the least, because you don't even know whether you're still there to do it), but aren't ready to commit all changes made yet, when Murphy assures that there are conflicts. Then you have to do the stash/pop dance and since you manage to not fix all conflicts, the stash wasn't dropped, which you do manually and you just lost some changes. Then you wished you'd done a back-up before the pull ...

Sure, if you always commit your changes before pulling, then you won't need the stash and (even old CVS documentation reminded us that a VCS tool cannot replace communication) if there are no unrelated changes in the files you're working on, there won't be conflicts, but that just aren't realistic assumptions.

Sounds like you should commit more often inside you topic branches.

In case you are talking about merge conflicts: That's the nature of distributed development other people might trump on places you are currently working on.

I guess there are more intelligent merge strategies. But GIT gives you a list of files that need a manual merge and you have to look into them one by one. GIT even tells you what to do in this case.

I think the idiosyncratic command names are rooted in the fact that git is designed as a peer to peer distributed system as opposed to how it is generally used right now, the server/client workflow. Github even follows and adds to this tradition with the always weird sounding "pull request", since the pull request is normally a mail to a mailgroup with the description of the changes and an actual request to pull that person's changes to the maintainers local repositories.

I'm not sure what is currently being done at developing git, but adapting/creating some porcelain commands accommodating a more centralized workflow even mainly on a semantic level could help with the UX friction.

Also, the obligatory joke "git gets easier once you get the basic idea that branches are homeomorphic endofunctors mapping submanifolds of a Hilbert space"

> Also, the obligatory joke "git gets easier once you get the basic idea that branches are homeomorphic endofunctors mapping submanifolds of a Hilbert space"

The scary thing about that one is that I still don't know whether it's just a joke, or if it's the "it's funny because it's true" kind of joke.