Hacker News new | ask | show | jobs
by jc_sec 2591 days ago
There's an article like this every week or so.. I don't get it. Git isn't that hard.. You can pretty much get by 99% of use cases with like four or five commands.
11 comments

The proliferation of articles like this is a very very good indication, that, yes, git is that hard, especially if you have to collaborate with other people.

Everyone has a different idea of what git does, what things are called, and different interpretations of the vast git vocabulary. What is a rebase? What is a branch? What is a reset? People have different mental models for all of these things.

Git would be easier if it weren't for all of the git users you have to work with. If you're a git solipsist, you develop your own mental model that works for you and you never have to care what anyone else does when they are using git.

I got a lot of mileage out of git with "do work on my own individual branch, never use `--force anything` even if a blog post on the internet says to, and don't rewrite history."

Reading just enough of the git-scm book to get a basic mental model of staging, branches, and pushing/pulling from a single remote (aka the things new people actually probably trying to do with git) can serve you well enough. I've since worked on teams that expected WIP commits to be squashed, used multiple remote repos, etc, but the above should be all the git most of the people complaining about git actually need.

    git remote add origin git@yabbadabbadoo:org/team
    git checkout -b feat/my-work-branch
    # do work
    git add -p .
    git reset HEAD accidental-file.txt
    git commit -m "Add sweet feature"
    git push -u origin feat/my-work-branch
    git pull origin feat/my-work-branch
I feel like there are two big reasons git gets the rap it does separate from any actual interface issues:

1. People tend to mess up with a tool more often when they are still getting acquainted with it. When things get hairy, people tend to just try random fixes so they can get back to work which makes the problem hairier still.

2. git might be one of the first tools someone uses that expects end users to map their mental model to it rather than trying to fit their pre-existing mental model.

Specifying the remote and branch name again when doing a `git pull` is not necessary after you've set it as the upstream branch (which the `-u` option in `git push` did in your example).
To play devil's advocate, I purposely never use push/pull without specifying the remote and branch because doing otherwise would cause issues if I accidentally forget which branch I'm on (which isn't super uncommon for me, as I've unfortunately gotten so used to seeing the branch name as part of my shell prompt that I don't notice it unless I actively look at it). I believe there's even an option you can put in your .gitconfig to enforce this.
Sorry, but it seems like you've worked in very low skilled teams. There are sometimes two different solutions to a problem, but they come with different pros and cons and you need to decide which to choose based on balancing reasons, not based on having different understandings of how git works.

For instance, when you have lots of parallel work, you have to decide whether to merge-commit each into the mainline or wether to rebase them. The first is an honest view of what happened, but might be harder to read. The other is easier to read, but might not represent well what actually happened. Git doesn't work one way or the other. Both is fine for git. And you should also be aware what it does under the hood for both options.

> Git would be easier if it weren't for all of the git users you have to work with.

Then you wouldn't really need distributed source control, would you ;)

There is loads of videos on yt on how to make pushups.
> Git isn't that hard.

It's not, but if you don't use it mostly every day, or if you decide to "Delete repository and clone again" every time there's a problem, you won't ever get to learn how to fix it.

The staging area is totally unnecessary IMO. I think git would be easier if we didn't have it.

The term `checkout` is multiplexed to do more things than I would've guessed.

I find the staging area useful. It especially helps when you only want to commit a change in part of a file or just generally reviewing a commit before it's a real commit. And also to double check I'm not going to be uploading any secret keys (which seems to happen to people more often than it should).
The staging area is incidental. It's yet another place in which your code can be, and it confuses users. This is why Gitless has removed it.

https://gitless.com/#vs

You don't need the staging area to select hunks into a commit. The selected hunks could go straight into a commit. Selecting hunks is a different thing than putting the selection into an extra intermediate area between working directory and commit.

You don't need an extra intermediate area to review a commit. Commits are flexible and modifiable, so you can review the draft commit, modify it as necessary, and then publish it.

I always assumed it was there as an analogue of the state tracked by a UI such as TortoiseSVN's Commit dialog, or (though it's a lot longer since I lasted used it...) Perforce's changelists view. It's a list of files you've got checked out or modified: you tick the ones you want in the commit, right click to delete files or revert, double click to get a diff, that kind of thing. Between each deletion/reversion/diff/etc., the state of the tickboxes is retained, so you can sort of just fool about until you've got what you want.

But this sort of multi-step thing is often a pain to do from the command line, I find: unless you have some way of tracking the state between commands, it's no fun working through this list of items, building up a to do list that you then have to get done at the end with one uber command. And the staging area is this way of tracking the state when it comes to putting together your commit.

The gitless examples look to have many common possibilities licked, though, and perhaps that will suffice for most cases?

I didn't know about Gitless. The other interesting thing I see about it is that switching branches also switches out any uncommitted changes. On balance I think I find that less useful.
Also helpful for committing changes in smaller atomic units
I think the staging area should be a more intermediate usage pattern, at least.
But you could also review the commit before pushing and then modify it instead.
> The staging area is totally unnecessary IMO. I think git would be easier if we didn't have it.

Staging area / Index is one of the best features of Git for me.

If I end up having a bunch of semi related changes in-progress; being able to easily group those into individual commits is great.

> The term `checkout` is multiplexed to do more things than I would've guessed.

Agree

You can do that in svn too with the "changelist".
svn cannot do partial file commits
> The staging area is totally unnecessary IMO

Honestly, I think that 'stash' is the more problematic concept for me. Not that it's particularly bad, just that it's extra. Make a new branch for your awful code, check out your old head and keep going. I learned hg and then git, and IIRC stash was more comfortable for my team's established workflow.

And maybe I have good reason to hate it. One of the only times I've ever broken a repo is by attempting to stash partway through a messy merge. Never did figure out if that was pebcak or a bug, or if I could gracefully recover, because I was in the middle of something. I shed a tear, nuked the repo and found a better direction to merge.

Ever since that happened I've gotten much more comfortable making and deleting branches. Among other things, they're easier to clean up and have proper histories.

> The staging area is totally unnecessary IMO. I think git would be easier if we didn't have it.

I can't even imagine not having it, I extremely rarely commit all changes, to the point where I really might as well alias add=add -p, and now I've thought of it I probably will.

> The term `checkout` is multiplexed to do more things than I would've guessed.

My rule is that if I think that, I've probably got the 'wrong' mental model.

Checkout gets the state of the worktree from somewhere else.

In its simplest usage, from another ref and changes to it.

With -b, as above, but with a new branch name.

With -- files, filter for only the given files, leaving HEAD where it is because moving it would be the opposite operation - taking the inverse list of files from current location to the specified one.

Etc.

> The term `checkout` is multiplexed to do more things than I would've guessed.

Do you mean `pull`?

> The staging area is totally unnecessary IMO. I think git would be easier if we didn't have it.

It's an interesting POV. Especially since you can easily amend and rebase -i before pushing without any consequence. Thanks for the idea. I implement a git-like for a special use case at the moment and will certainly consider this.

I didn't use the staging area until I started to use git add -p. Now I use it very often to properly separate mixed changes into more logical commits.

It makes the staging very convenient to use. But without this command, I agree that it is a pain to use.

"Everyone knows four or five git commands, but they're all different ones."
Just learn all ten and be done with it. You wouldn't work in a factory with professional tools without learning to use the tools either. So why not just learn this professional version control system in and out. It's not that hard either.
Because a lot of people have a terrible workflow. Then they spend 1 hour on StackOverflow searching a magic solution to fix their mess.

And there are also those people who inflict themselves unnecessary strict rules for whatever reason. Like those who refuse to rebase and push -f on their own branches. Or those who refuse to use a GUI but keep messing up when diffing, resolving conflicts and staging specific files/lines.

I really do not like `push -f` because in the past git default configuration was to push all branches; things have improved now that the default is to push to the current branch.

Recently got turned onto `git push --force-with-lease` which is great.

http://blog.developer.atlassian.com/force-with-lease/

I agree it's not hard once you get it, but the main thing is people don't get it. It's unintuitive. That's not to say the model is wrong (I think it's correct), just that there's a huge gap between what people think git is doing and what it's actually doing and so they end up fighting it to do what they think it should do.

I had a coworker explain that he did a merge and something unexpected happened to his branch. I had to explain to him that what happened was totally expected and that his understanding was what was wrong.

Those "four or five commands" do like seven seemingly unrelated things each.
1 time out of 100 you get those cases where the four or five commands you have memorized are not enough. Those cases are hard.
It's not hard but the UX is horrible.
Yeah! I find git to be easy to understand conceptually, but the CLI is unintuitive and sometimes inconsistent. I often know exactly what I want to do, but don't know how to phrase it in a git command.
Agreed. Specially, flags of these commands are actual magic when it comes to productivity, at least for me. For example, not all flags of git commit command are used frequently but they perform a lot of different operations and can be easily combined to save the day.

https://git-scm.com/docs/git-commit#_options

git is super hard, because it has too many sharp edges.

Quick quiz: What does 'git checkout a/b' do? I've seen users end up with 3 different meanings.

My thoughts exactly. Maybe it's because I've used SVM and Mercurial before but I learned Git very easily. I find the commands and options fairly intuitive once you know you're manipulating a graph of patches.

But I guess this is very subjective. After all, I've never been able to master gnupg despite how long I've been using it for.

> I find the commands and options fairly intuitive once you know you're manipulating a graph of patches.

On the contrary, I find the "graph of patchs/Merkel tree/whatever" model pretty easy to understand, and have difficulty in using the commands to make the tree look like how I want it to.

The plumbing is nice, but the porcelain is covered in shit.