820 comments

[ 4.0 ms ] story [ 332 ms ] thread
If you cannot explain it, you don't really understand it.
The ability to communicate is a separate skill from the ability to comprehend something.

Once you separate the two skills you get 4 classes of people (with gradations):

1. don't understand it, cannot explain it. 2. do understand it, cannot explain it well. 3. don't understand it well, can explain it well. 4. understand it well, explain it well.

Number 2 are good practitioners and not as good teachers. Number 3 are good teachers but not as good practitioners. Number 4 are good teachers and good practitioners.

Everyone wants to learn from a number 4, but they are more rare then the 3s and 2s. Between a 2 and a 3, you'd rather learn from a 3. If you don't need to learn, you'd probably rather work with a 2 than a 3. Basically, even if their mental model isn't perfect, they deliver explanations that can quickly lead others to at least be as good as them and possibly better quickly if you can see the mistakes in their mental models (their descriptions could potentially be 100% accurate without it reflecting their poor mental model).

Anyways, this observation leads to the standard cliche, "Those that can, do; those that cannot, teach."

(comment deleted)
Git is one of those technologies where it's super important to get a good grasp of how to internals work. Once you got that, it get easier to answer git questions for others or yourself, and to read the documentation or man pages, as you know what is happening.

With how software devs use git, it's 100% worth it to read a good book on it.

I would also love to get some recommendation on git. I'm using the github desktop gui atm (very new to this world), but I'd like to start learning git. it is kinda intimidating.
Use command line. Try creating playground repo and play with it. You can use github's private repos. Use separate accounts to emulate merge conflicts. Start with only those options you feel need: such as tags and so. Read about work models (git flow, and others). Try them in your playground repo.

Basically it's impossible to learn something without trying and making mistakes, and analysing what went wrong. No failing - no success. You will get it, not that hard. Good luck!

https://github.com/FredrikNoren/ungit is one of my favorite Git tools. IMHO it is the perfect compliment to the command-line interface since it provides a nice visual model of your commit graph and branches. The graph is interactive so you can use the GUI for things like merging, rebasing, cherry-picking, etc (very nice for visualizing those changes). But at the same time, the Ungit interface mostly just stays out of your way unless you need it. It does not try to force you into a certain workflow or usage pattern.
I am not sure that is true at all.

It’s way more important to understand that git has 0 consistency of what the command name is and what object it manipulates.

Git checkout can create both branches and files. Why? Wouldn’t it be easier to have two commands for checking out a file from a different branch and creating a new branch?

> Git is one of those technologies where it's super important to get a good grasp of how to internals work.

In my opinion relying too much on user understanding implementation is a mark of bad design. I don't care about more advanced functionalities of git, on daily basis I have very simple workflow that I want to "just work". Sure I can spend few days studying git internals, but it feels unnecessary. Especially given that in the past I've worked with simpler proprietary tools that "just work" (though did not have equivalent of "power" features).

On the other hand I think git is like bash - has some serious warts but it's good enough to be used widely; and unlikely to be replaced by anything else at this point.

> Git is one of those technologies where it's super important to get a good grasp of how to internals work.

That's just an excuse for Git being super confusing. Does Microsoft say "it's really important when using MS Word to get a good grasp of how its internals work"? Of course not.

Yes you need to get a good mental model of how Git works (basically, commits are efficient snapshots of your code), but that's not the same as knowing its internals. Do you need to know about packfiles and loose refs etc? No, obviously not.

Schoolchildren can write documents. They can't write software with many authors creating disparate, conflicting changes across vast space and time. Complaining that git is too hard is claiming this is easy.
The parts of it that involve Git are easy. By far the most difficult thing is resolving merge conflicts, but Git farms that out to third party software, and nobody here is talking about that.

The core idea of Git - a DAG of repo snapshots - can be explained in like 5 minutes. I could explain all of the other operations in 5 more minutes.

Maybe I should do a `Git in 10 minutes` video, but there are about a million of those already, and as I said, it wouldn't address the actual hard part of Git: the CLI.

I gained a lot when I learned the internals of TeX (of LaTeX fame.) Of course I did not learn _all_ of the internals. There's no need.

Is (La)TeX super confusing? Sure. Is it what the pros use? Definitely. Also, read "The TeXBook", it is a masterpiece.

I agree in the sense that it is important to understand the underlying concepts of Git. Once that is clear in your mind, it becomes much easier to use.

When I explain Git to other people I explain it as a tool for manipulating commit graphs, where every node in the graph is a (merge) commit with some unique hash, where a commit itself is just essentially a patch on the previous node(s) in the graph.

Implementation details on how this commit graph is manipulated or stored behind the scenes are not important to understand Git in my opinion.

> Git is one of those technologies where it's super important to get a good grasp of how to internals work.

I fully agree, that's why I built a tutorial where you learn about Git internals by implementing Git yourself in Python: https://www.leshenko.net/p/ugit/

To answer your question about deleting a remote branch: branches are usually features, e.g. fixes, new features, etc. Once I've pushed to the remote and merged, the branch is no longer necessary. This is why someone would delete a remote branch.
The article's point isn't that there's no reason to delete a remote branch, but that the concept of them is a conceptual leap that one doesn't naturally make until confronted with certain situations.

Otherwise I agree with you; with my team I documented the standard feature/bugfix development process including the git steps, last of which is the lead engineer merging the branch and deleting it on the remote.

I don't agree at all. Git is the simplest version control system I've ever used. The concept of merging, rebasing, cherry-picking, and resetting works so naturally that I'm basically going to expect this level of ease of use from any VCS I use going forward.

That being said, I know there are some who have trouble with Git. But IMO it isn't because Git is hard, but because they don't have to truly understand Git to use it. That's how easy it is.

People are being told git is complex and then they are confused when it feels easy when they do something. They assume they are doing something wrong.
I’d be inclined to disagree. I found the learning curve to be quite steep. When you’re used to having a centralised VCS hosted for you it can seem a bit of a chore to take on all this extra responsibility. Once you’re on top of it though it’s great I wouldn’t use anything else.
> When you’re used to having a centralised VCS hosted for you

I think this is the crucial part. Git will come off as difficult and strange if you're used to using a centralized VCS, and expect Git to work like it. But that isn't really indicative of Git's own complexity, just its differentness.

But you are free to use Git in the old centralised way. You don’t have to get into workflows and stuff if you don’t want to. The , just as in the purely centralised case you are still reliant on a oracle but that’s okay in most cases.
The only concept that I can't put into my muscle memory is reverting changes for one file before commit. This is very easy in SVN but for some reason it's not intuitive git (at least for me), why there can't be something like `git revert filename`. Thankfully I have GitKraren that is helping me with things like that.
‘git checkout filename’ is the equivalent of ‘svn revert filename’
Yes, it works but not intuitive. I mean why use the checkout for the file reversion? And I think that's the problem of git: it's powerful and it works, but it's really not easy to get started.
There are numerous git <-> svn cheat sheets ... this is literally one of the first things I learned. I’m kind of bewildered by this to be honest ... I don’t know how somebody with a technical qualification could have trouble with this ...
We shouldn't need a cheat sheet. We shouldn't need Linus's brain dump to be able to use a tool. The Git UI directly models the Git internal model and that's just bad design. It's a completely leaky abstraction.

I can use git all right but the fact that I need about 20 different commands to do my job, 95% of them with extra parameters and almost all of them with names that don't reflect what I want to do from a functional point of view is utterly dumb. Again, functional! not technical! The UI should reflect end user functionality, not internal technical details.

I hope I never end up working with you bud. “Where is the code?” “Oh I’m sorry I couldn’t do it because it was hard can I still be paid please?”
I refer to my comment from a couple of days ago: https://news.ycombinator.com/item?id=25080013
Oh my, that comment is pure gold :-)

Its putting into words something I've been thinking for a long time, thank you for the great comment!

That's just stupid. We're not talking about "users" here, we're talking about "engineers". If you can't grasp the complexity of Git, you've no business using it. You need to be working in an environment with a centralised VCS and somebody administering it.

Unless you mean just VCS for yourself, in which case you could probably just use anything you liked rather than complaining about it ...

And it's not manliness to say that if you can't grasp complexity you really shouldn't be writing code. That's self evident. It's the whole point of what we do. I'm not looking down on people who can't code - but it's horses for courses. To suggest anything else is just bonkers.

You could have read their comment as saying that they have things they'd rather be doing than learning Git. Instead you took the position that expressing a desire for nice tools is a sign of their total incompetence at programming, that they are complaining because they cannot grasp its complexity (despite them saying "I can use Git" which suggests they can grasp its complexity). You dismissed "The Git UI directly models the Git internal model and that's just bad design", launching straight into calling them stupid and saying they need handholding, for merely wanting good design - because good design makes things easier to use, and things being easier to use is for stupid people.

You could have argued that Git is easy to use and therefore they are stupid for not being able to use it. Or that the interface modelling the internal workings is a good design. Or that Git's complexity is necessary and no simpler interface is possible. Instead you agree that it is complex and thrill about the complexity and use it as a showoff point about how it makes you superior. That's the manliness part. Not as you willfully misrepresent it "if you can't grasp complexity you really shouldn't be writing code" but "if you don't want to spend your life on the complexity of a supporting tool unrelated to the problem you really want to solve you really shouldn't be writing code".

Git is a tool in support of programming, learning Git is not the whole point. Programming involves dealing with complexity (often in the sense of simplifying complexity and hiding it away), but that doesn't mean everything has to be complex to use, and it doesn't mean that someone has to enjoy the complexity in everything to be a good programmer.

With that attitude, I definitely wouldn't want to work with you either. I also love the assumptions about me and the thinly veiled ad-hominem :-)

We should be able to admit that a tool has a crap UI and cut out the macho geek attitude.

I've been working in this field for about of 15 years and the amount of needless pain we endure from core tools is unimaginable. I'm waaaay past the learning curve for Unix tools, git, etc., but let's not pretend that they're awesome UX wise. They're awful.

We've just learned to endure the pain and we've internalized it.

Stockholm syndrome at its finest.

I'm really not sure what to say to this.

I'm guessing you're not an engineer. It's only product management types that cast around technical criticisms without proposing any solutions so I guess you are of that strain. I don't believe you're stupid, far from it but I think your perspective needs some correction.

We've been using VCS fairly universally for the last 25-30 or so. There's been RCS, CVS, SVN, Perforce, Clearcase ... the list goes on. They all have their warts. Git as it stands at this point in time is the best VCS system that the global software development community has come up with. It's exactly as easy to use as the community that developed it needs to be.

You are free to explore alternatives. You can get commercial products for this kind of thing, and they may well be easier to use, but in my experience these are more buggy, though they do try to provide a more user friendly experience.

You are also free to use the many freely available front-ends to git that are available, or you can use Git in the old centralised model if you like, and go crying to the admin when things get too tricky, as with any other VCS.

By far the biggest gripe with Git is the inconsistency of the tooling, and I guess you could fork it and make whatever improvements you feel are appropriate and then set about getting people to use it. But again, there are numerous front ends (IntelliJ is my favourite) that shield you from these minutiae if needs be.

So please, spare me your injured animal grandstanding. Git is for the choir, not the masses, and to make it suitable for the masses would be a waste of everybody's time because the masses have no interest. You have an interest that would be better served by just sitting down and learning how to use the damn tools that the rest of your colleagues do.

15 years. LOL.

EDIT - if you want something that is "like git" but "easy to use" then, in all seriousness you should check out Mercurial. I always thought it looked nice, but it's of little use if none of my collaborators are on it.

> [you] types

> of that strain [of people]

> injured animal grandstanding

...

Plus, sooo many assumptions in there. As an engineer, I know that assumptions are bad :-)

Thanks for the :-) makes me feel like we're not having an argument any more.

As an engineer you should also know, that often assumptions are all you've got to go on. The only way to address uncertainty is to get into the details and figure out what's going on. Complaining loudly and fruitlessly about things is good for getting emotional support but it's not generally a good strategy for getting things done.

It's like shorthand for git checkout <current branch> -- <files>. You're only omitting the current branch which is the default. I'm not sure if it's intuitive but it seems pretty coherent.

edit: on second thought no it's really not very coherent. If you exclude <files> it means checkout all files if you write a <branch>, but no files if you write no <branch>. So excluding <branch> doesn't consistently do the same as using <current branch>. I guess git does kind of suck.

I had no idea that checkout does that to files. In my head checkout was only for manipulating branches and revisions of whole repo
There is now (as of version 2.23.0), you can use:

git restore filename

Thank you that will help me a lot.
I slightly disagree. I think git is simple, but the UX (the way the commands and flags are designed) is really bad so that's why it's perceived as hard.
It's the case with most UNIX CLI tools and if the author's complaints are true, do we then have to change all UNIX CLI tools? Maybe? The reality is we can't and probably don't need to.
Then you have never used Mercurial.
“How do I branch in Mercurial?” seems to have four long answers, and maybe a patch queue makes five?

https://stevelosh.com/blog/2009/08/a-guide-to-branching-in-m...

You could easily write pages about local/remote branches, heads behaviour, etc. in git. Mercurial also gives you an extra option - bookmarks, but you don't have to use them at all.

The deeper explanation doesn't mean more complex system.

I don't get that either. There have been people here arguing that svn and mercurial were both easier to use than git.

But the moment I could import SVN to git I immediately switched to Git for everything. And Mercurial... I guess it's a matter of preference, but I personally never got the hang of it. And the fact that they had both SVN style continuous IDs AND hashes was deeply confusing to me.

The only thing I did find confusing in the beginning was a) the distinction between pull and fetch. b) getting used to the fact that I don't really care about continuous IDs (or hashes for the most part ) and think more about commits relative to where I currently am.

In addition to that things such as `git add -p` or `tig` are so much more convenient compared to other VCS CLIs. But even if CLI isn't what you want we're now a couple years beyond having beautiful third party Git GUIs

If anyone is looking for a git GUI, Fork is great https://git-fork.com/
Fork is great, I paid for it happily. It's UI makes sense, radiates the right level of information, and you can use the keyboard almost exclusively. Heavily recommended.
I'm not an idiot, but I don't fully understand git. I am coding for a living, and I use git every day. I probably could sit down for a couple of days and fully understand how git works, but I've never needed it, I understand how basic git operations work, and I stay away from commands that I don't understand. With GitHub desktop you don't need to open the command line for any standard operations, I only need to use the terminal for cherry picking.

The reason I want to stick to the basics is because of one interesting thing I've noticed: a lot of engineers sincerely believe that they are git experts when they are nowhere close. And until I locked down the GitHub repo with admin privileges, that was a dangerous thing. So I'm trying to work a system where no one in a team where not everyone is truly expert at git only uses the basic commandset from git.

One thing I can say again to emphasize - git maybe the simplest Vcs you've used, but it's not a simple tool, and its most definitely not intuitive for everyone. If it is for you, that's great, but maybe there's a lesson here about how not everyone's brains are wired the same.

I've definitely been the victim of my own git hubris.

Once, when leaving a job, I decided to copy all of my local WIP branches to the server.

I whipped out this fancy --mirror option I had just heard of:

  git push --mirror $remote
Surprise! All branches on the remote repo got wiped. My local refs replaced the refs on the remote.

Somehow I found the right commits floating around in the git ether. I was able to recreate the branches, but I had to recreate their names by reading the commit log.

Did I mention this happened on my way out the door from a job? In retrospect, I shouldn't have panicked so much -- there were daily backups -- but the sheer terror I felt has made me read the man pages really closely to this day.

I get it, but I'm not sure you should fault Git for that. Nothing like that has ever happened to me and I wouldn't use a command I don't know in a critical setting...
Any sane piece of software should warn you before doing a highly destructive operation.

Something like

  You are trying to remove commits from twelve branches.
  Are you sure that's what you want to do?  
  Include the --force option to go ahead with this change.
would be a whole lot better.

Even if it gives you the tools to undo the mistakes, it saves you time and stress if it keeps you from making the mistakes in the first place.

I have a horrible feeling your answer to this is going to stress me out, but does that work even without a force push?
Yes, --mirror implies a level of force. The man page contains this:

"...locally updated refs will be force updated on the remote end, and deleted refs will be removed from the remote end..."

That breaks a very simple rule that a VCS tools should adhere consistently. Do not make destructive changes unless explicitly told to. Since most other commands to not allow you to do this without -f, the same should apply here.
I'm not sure I see your point. The entire reason `git push --mirror` exists is to turn the remote end into a mirror of the local end. By definition that's a destructive operation. What would it do without a further --force?

If you just want to push all branches or tags you should use --all or --tags.

Because you normally cannot make remote destructive changes without the --force. Unless you know the commands that does that by default. That is bad UX.
Probably because removing branches from the remote doesn't make the commit history inconsistent with any copies made before the push. That seems to be the only case where git second-guesses what you tell it to do.
mistakes happen. it is a testament to the power of git that your command didn't cause permanent damage. and yes, it could have been worse.

but if you want a system that protects you from these mistakes by making mistakes impossible, then you get a system that is very rigit and actually harder to use.

git protects you from these mistakes by making it possible to recover.

in this particular instance though, there could probably be some extra help to recover. (some way restore the removed refs)

this definitely shouldn't happen if shared branches are properly protected against non fastforward pushes
...and if you didn't know that, you shouldn't be using git!

To be fair, one should always look up options you are unfamiliar with before using - and Stack Exchange is not an authoritative source.

--mirror

...Newly created local refs will be pushed to the remote end, locally updated refs will be force updated on the remote end, and deleted refs will be removed from the remote end... [my emphasis.]

On the other hand, if you are on a system where the behavior can be fundamentally altered by multiple configuration options, this will not necessarily help you much.

...This is the default if the configuration option remote.<remote>.mirror is set.

>To be fair, one should always look up options you are unfamiliar with before using - and Stack Exchange is not an authoritative source

https://xkcd.com/293/

I'm not sure I follow your logic: why not take a few days to learn the fundamentals of git? I did that a few years back (and I'm not saying I read the source code, just learned about the base concepts from a few blogs and played around with some more advanced commands), and it has paid dividends _every single day for the last several years_. For example, I avoid tracking branches and have started using `git fetch`, `git merge --ff-only <remote>/<branch>`, `git reset --hard <remote>/<branch>` and `git push <remote> <branch>` to push and pull remote code. Even these slightly lower level commands will start to help you understand what's going on behind the scenes and take the mystery out of, say, rebase conflicts.
I am limited by time on what I can learn, every day I have five other things I'd rather spend my time learning about instead of git. The "git experts" that I know of are no more productive than me and more often than not do annoying things like rewriting commit histories after I made comments in their PRs, that I'm not convinced it's worth the day or two I need to learn it fully. In the end git is not in production, it's just a tool to manage code, I'd rather be an expert on the code than the coding tool. This is probably akin to trying to understand how your car works when all you need it to do is get you to work. Changing tires is about as much as anyone who's trying to be productive should know about their car. Call a mechanic for anything else.
Before undertaking his craft, the artisan first sharpens his tools.
A good cook doesn't need to own 5 stones to sharpen his knife, he just needs to have the number of the sharpening guy.
You would be surprised how many cooks sharpen their knives themselves.

It is also a very wholesome and meditative activity.

No? Good cooks most definitely sharpen their own knives.
Cooks and knives are a bad example, because sharpening knives is easy. I am not a cook and sharpen mine too. It takes like 15 minutes to learn how to do it, and a similar time to actually do it.

Most piano players don't have a clue about how to tune their pianos, though.

Oddly enough, pianists not knowing how to tune a piano is an anomaly in the music world, as most other artists know their instruments inside and out. The Times did a piece on this just the other day: https://www.nytimes.com/2020/11/12/arts/music/piano-tuning.h...
It is not binary in my experience.

Most professional musicians know their instrument very well - and still know a man for the "hard" stuff, e.g. for thorough maintenance or repairs that require craftsmanship.

And there are obviously variants. The guys that fix their instruments regularly and experiment with e.g. cooking your stings, and musicians that hand them in for the tiniest, easiest tasks.

> In the end git is not in production

Git ends in my production multiple times.

1. In my side project game, auto update and replay system is based on Git. For every update, there will be a commit appended to the code repo which is the most recent update. If a player wants to replay a game in previous version, just checkout the appropriate commit, and run the replay using exact the same code. I'm freed from backward compatibility issue & update subsystem which handles diffing, compression, transporting by a single decision. https://github.com/feisuzhu/thbattle/blob/master/src/autoupd...

2. Another project written by me, which is a monitoring system, distributes it's rules by a git repo. Monitoring agents in the nodes cares about authenticity of distributed rules. So I just sign the tree hash and embed the signature in commit message, which will be later validated by monitoring agents. https://github.com/leancloud/satori/blob/master/satori-rules...

That's a very shortsighted view on the world. Particularly if you're working with other people.

Once you are collaborating, there is simply more to good code than what you our your peers know about the code or the language. Working well and effective with others has a huge impact on you, your peers, the "company" and in the end the product.

Further, I know a lot more about my cars than just how to change the tires. E.g. there are know issues with certain popular car models. Knowing about them does help, not every random mechanic does.

Also, if my car does certain things (surprise, they do all the time, they are complex nowadays) that are easily explainable or even somewhere in the manual, I am not going to ask for help every.single.time. I have stuff to do, be somewhere. I am not going to put my car in the dealership all the time.

Git for me is a productivity tool, in particular when I'm working with others.

You sound like the guy I once collaborated with that didn't want to use git (because why should he learn it now?) and instead sending the whole code via skype every day.

"The 'git experts' that I know of are no more productive than me and more often than not do annoying things like rewriting commit histories after I made comments in their PRs, that I'm not convinced it's worth the day or two I need to learn it fully."

You're annoyed at them... because they do things that you don't know how to do? How is that their fault?

"In the end git is not in production, it's just a tool to manage code, I'd rather be an expert on the code than the coding tool."

That's a very short-sighted attitude. It's like saying, "I don't want to learn how to operate a bulldozer, because I'd rather be an expert on dirt rather than the tools to move dirt."

> do annoying things like rewriting commit histories after I made comments in their PRs

That's exactly what I'd expect someone to do after I commented on their PR.

> ewriting commit histories after I made comments in their PRs

> That's exactly what I'd expect someone to do after I commented on their PR.

The vast majority of people do not. I certainly wouldn't expect someone to waste time on that.

> The vast majority of people do not.

That's a very bold claim.

It's certainly been the expected workflow everywhere I've worked. You might consider it a waste of time but I'd wager the resulting mess of commits from not doing so wastes far more time in the long run.

I've never worked in an environment where it was expected or used. As far as I can tell, no time has been wasted as a result. How would it cause time wasting?
Without a clean history it takes longer to find which commit changed things and why.
I believe I've really only needed to do that once. git bisect handled it in about 10 minutes IIRC. It's hard for me to imagine how I could achieve a net time savings against that level of commit-hunting.
I envy you then. I spend a great deal of time looking through history to find bugs.

An unclean history is less likely to work well with bisect too, as the individual commits may be broken.

> I spend a great deal of time looking through history to find bugs.

You mean when where and how a change was introduced? I dont think bugs are located in the history, since bugs are operational failures on a deployed branch.

Yes, I phrased that badly. Let's say looking through history to understand the context of when bugs were introduced and how to fix them
No one I work with does that. They do one of two things.

1) argue that they really don't need to change anything 2) push more commit(s)

Why would it be better to rewrite history?

Your insistence in purposefully not understanding how to use a tool in your toolbox is frankly saddening. It's literally part of your job. You interact with it presumably daily, yet you have no clue how to be effective with that tool. And you say others are annoying for learning how to use their tools.
The problem is - if you're not using some feature every month you won't remember how to do it anyway when you finally need to use it.

So there's little point reading about exotic features upfront other than to know they exist. And which features are exotic depends on your workflow.

It would help if git interface was consistent enough to make remembering this stuff easier.

For example I never remember the exact options for git reset because I'm using it just rarely enough to forget them when I need them again.

I would suggest it's far better to understand the data structures inherent in git and how those data structure changes are tracked and merged. Then almost all operations in git become clear.

And as a side bonus it will probably make you a better coder.

How would knowing the structure (which I already do) help me remembering what was that option called?
Because most options are named after parts of the underlying structure. At least for me that makes them much easier to remember. There are some exceptions, but in general there is a logical system behind the naming.
> For example I never remember the exact options for git reset because I'm using it just rarely enough to forget them when I need them again.

I would argue the value is in knowing that something is possible using the `git reset` command so you know to go looking for the exact option to do what you want. And more likely you'll remember the operation if it's one you find yourself using frequently.

"Education is what is left after you have forgotten all you have learned."

-- someone or someone else. I forgot.

That’s a similar approach to mine. I tend to learn enough about something to “get the job done.”

This is both good and bad. I get a lot done, but not always as efficiently as possible, and I do find myself realizing, down the road, that I didn’t need to do it that way.

But it’s entirely possible to get caught in “tool rabbitholes,” where the main goal becomes subservient to the infrastructure.

I remember dealing with folks that would spend three days, writing CLI tools that saved, maybe two hours, over the course of a year.

I learn similarly (breadth first search + going deeper when needed) and my wife just does depth first seach. I've tried studying with her when we were at university and we just couldn't make it work - she would want to go 10 levels deep into the first subject and I would get insane trying to remember all the nested questions that get us there withotu understanding where the thing I'm learning about will be used :)

Her problem is she gets discouraged halfway through and never gets to use the stuff she learned.

My problem is I got good at winging it and looking up stuff as needed so I never learn the stuff I didn't needed even when it could be useful if I knew about it.

Probably some compromise would be the best - start with what you need and force yourself to go deep into one random topic each month.

> I remember dealing with folks that would spend three days, writing CLI tools that saved, maybe two hours, over the course of a year.

My friend is like that, but I learnt to aprecciate this when I worked with him. The script maybe only saved 1 minute of work 10 times a year, but more importantly it's self-checking documentation of how we are doing stuff we rarely do.

> I probably could sit down for a couple of days and fully understand how git works

This means it isn't hard. If you are capable of understanding algorithms of any complexity you should be able to learn how to use git (and how much of it) without treading on ground that is dangerous for you to use. All of this "it's too hard" rhetoric is infantilising or coddling people who frankly shouldn't be trusted to code anything of importance anyway. There's no shame in admitting your own limitations, but there is definitely shame in lowering the bar for others so much you are actively harming the industry.

Everyone starts at the ground floor. What would you tell a beginner who has to figure out 20 different technologies including git to get a basic web project going?

Besides, nobody is arguing git needs to be made weaker, just that it would be nice if it had a more gradual learning curve. Easy things easy, hard things possible. If you can’t see how git is hard you’ve forgotten what it is like to be a beginner.

>What would you tell a beginner who has to figure out 20 different technologies including git to get a basic web project going?

Software development is hard. That's why we have to spend years studying it and earn conspicuously good wages.

A basic project doesn't need git anyway.

eh, git is perfectly fine even for trivial projects.

Agree on the need for education to be a good developer though.

> What would you tell a beginner who has to figure out 20 different technologies including git to get a basic web project going?

We have the whole education system to deal with that. It's the same problem as in mechanics, chemistry, biology, etc.

I would tell them they don't need to figure out 20 different technologies. If they think they do, they've missed the point of the "basic" in "basic web project". If the 20 different technologies in your example include such basic things as an IDE and version control (evidently it includes at least the latter), I would tell them to start at the basics and learn the tools before they expect to be able to use them.
This is a disgusting, harmful take. You should really step back and rethink your assumptions here. Git is a tool that’s meant to make things easier. It’s complex enough, though, that it’s a stumbling block for a lot of folks for a workflow that really shouldn’t be so complicated.

If you intuitively grok how git works, that’s great. I’m going to guess you probably don’t really use it in any challenging or new situations and are just comfortable with your particular workflow. But maybe you do have that mastery level over this one tool in your code management system.

But guess what, other folks, true genius folks, either can’t or don’t have the mental bandwidth to learn every nook and cranny of this tool. If you don’t recognize that, you are willfully dismissing a lot of really smart people because their brains don’t work the same way yours does. But when you do that you are weakening yourself and your own capabilities.

So step back and re-assess your take here. It’s wrong, and it’s toxic to your own outlook as well as those around you.

It's evident that you think requiring basic competence is toxic, but you don't really compel me to feel differently. You have told me what I think is the case is toxic, wrong, disgusting and harmful. I now know you feel strongly about this.

I don't hugely feel like seeing things from your point of view because the only thing you've really told me that might change my mind is that you lose people when you require a basic amount of capability. I'm sorry to hear that this grievously wounds you on an emotional level, but I don't see that as a loss.

Not the person you're responding to, but I have my own two cents:

Saying "basic competence" is horrifically abusing language here. Git is a glorified save/share/undo tool, demanding people spend several days reading the manual is an absolute caricature and yet you're seriously saying that.

The reason people are mad at you is that people have lived experience of the interface sucking and failing to do the job an interface does - convey via context what it does and you're basically blaming them for wanting to fix the problem they've experienced instead of sucking it up and Being A Real Man and solving problems they don't have as a workaround for the tool failing to solve problems they do have.

And it's not like Git's interface problems are subtle. It's an absolute joke, and you're not even claiming it's an acceptable interface so much as rejecting the entire concept of user interfaces at all. I'm not sure how to explain how utterly infuriating that is.

You're saying "you're doing it wrong, so I don't care" while simultaneously complaining that some of the solutions could hurt other peoples' use-cases.

What is the correct response here? Reject their own memories and emotions and yield to your blame, or call you a willfully-oblivious fuckhead?

You're not the first one to say that it's hard to use right and I agree with that. This is true for a lot of powerful tools. At the end of the day, what is intuitive is what you have used a lot. If you're using a tool that fits an entirely different paradigm from what you are normally used to, it's going to be unintuitive. It's fair to say this frustrates everyone, especially in the beginning.

All that being said, this is not a reason to then take the next step and claim that basic competence in what is today an essential tool is optional. It is necessary and to work well you must know it well, otherwise the frustration you point out will be part of your life every day. As opposed to something that you live through and say goodbye to.

The fact that everyone is taking this as toxic or willfully oblivious is as far as I'm concerned infantile. It has nothing to do with "being a real man" (whatever that means to you), it has something to do with having the maturity to realise that you are making your own problems.

That is not to say we cannot build a better tool. Perhaps we can! Up until this point I have not seen it done without losing something else in turn.

Yeah this is incorrect.

One of the reasons that we able to achieve so much with computers is that there is a separation of concerns between different areas.

Requiring everyone to fully understand git is like requiring people who code in high-level languages to understand and apply chip design in their day-to-day work.

Imagine if when you tested some Python or Java code you got an error from your CPU and needed to take it out and debug it with an electron microscope.

Contemporary git has this disease. Its (command line) user interface is a mess. I could say more about what you would do to make a better version but a comment isn't the place for that.

The defence that you are using - that smart people should be able to learn git fully - is like saying that any and every smart programmer should learn IC design and buy their own electron microscope, and that's why it's OK that the chips keep breaking.

>I could say more about what you would do to make a better version but a comment isn't the place for that.

I'd be very interested because it's rare for me to see anyone attempt and, when I do, they break a basic use case.

Probably the biggest problem with the git interface is that the interface exposed to the user isn't sufficiently abstracted from the implementation.

Insanely complicated commands to undo things are one symptom of this.

As a user, you want to "save" some code and you also want to "share" it with others. You also want a historical record of what you did.

But obviously you will occasionally save and share things you didn't mean to. Like your Python virtual environment, like a bunch of pictures in their binary format, etc.

A sane version control would provide a point-and-click way to make these disappear from history (though with adequate security protections to make sure that only authorized people can do it).

Then you'd need centralised protections to decide who can delete and you instantly lose the distributed features.

If I'm a user and I want to save, I do it with my text editor. If I want to share, I can do it with Github, Gerrit, Gitlab, email, pigeon.

I never email people things I didn't mean to and, if I did, I wouldn't expect my email software to let me delete it. The centralised services allow it to some degree but even they don't allow information to be un-disseminated.

VCS is necessary to deal with changes that overlap and conflict. It's not for backup and it's not a method of communication. If all you need to do is save and share, you don't need VCS.

Github already has centralised protections to do with who can and cannot do various things, and so do other similar systems like gitlab.

So nothing is really gained but not allowing this, but it makes git very user-hostile because mistakes cannot easily be undone.

Github isn't git
That doesn't matter, the way people actually use git is that almost all repositories have someone or some small group who rule them, so nothing is really lost by having an easy option to purge things from history. And an inconvenient option (possibly more than one!) does exist.
It matters a lot, because the use cases you've seen aren't the only ones that exist. In a tool so widespread as git, that is really not surprising.

By removing it's decentralised nature you've fundamentally built a different VCS. Perhaps SVN is acceptable for your use case, that's great! It's definitely not git though - basic expected use cases were lost as predicted at the start of this thread.

Any system will get dragged down by the need to support all sorts of legacy use-cases. I think there's an xkcd cartoon about this?

The core task of a VCS is versioning and collaborating on text of some kind. Git doesn't do this in an optimal way, so eventually it will get replaced by something better. In the meantime we'll all get on with learning its ins and outs, just like previous generations learned how to use punchcards.

You mostly lost me at "point-and-click", but I'll bite.

    git rebase -i {hash before your changes}
    git push -f
And since you talked about point and click, you could easily enough use github permissions on branches to prevent this on protected branches or you could configure your git repo to disallow force pushes. To get specific branch protections on a normal git repo you would need to use a hook to validate the update before it's accepted.
That only works in some circumstances.

For example, suppose I init a new repo and accidentally commit my entire virtual environment, then push, then do some real work, push a few times more and then a colleague notices (after they have pulled, worked on and pushed) that the venv stuff is there.

In an ideal VCS, you would have a simple command like git purge /badfolder that would make it as if it never existed.

But AFAIK that doesn't exist, or at least the ways to accomplish that are pretty gnarly and dangerous.

Well, first I'd argue that you are misusing the tool if you managed to commit a large chunk of unrelated code, but that's another story.

Second, I would tell you that git has a command for just your situation.

   git filter-branch
https://git-scm.com/docs/git-filter-branch

You can run a command against every commit and it will then recommit. That would let you remove, for instance, an entire subdirectory. The downside here being that you are rewriting history on something you've shared with the world and that has larger potentials for causing issues with contributors.

I guess my point is really this, git is simply one of the many tools you likely have to use on a daily basis. If you have to use a tool in your daily job it's in your interest to really grok the various ways your tool can be used. You'll want to really understand the primary use cases in detail and the less used ones you'll want to know in passing at least. That allows you to realize that something is possible with the tool, even if you don't recall the exact specifics. A machinist would have the Machinery's Handbook, a programmer will have multiple internet references. Maybe the real point is that it's _ok_ to not know the exact syntax and need to reference it for more esoteric operations.

I use an x86 CPU every day for work and I have no idea how it works in detail, and thanks to the magic of separation of concerns I don't have to (perhaps apart from a few specific things like vecorizing instead of loops that I really do need to know about).

Git demanding a large chuck of user mindspace isn't an advantage for git, it's a signal that git is bad and needs replacing.

So do interpreters, compilers, package managers, virtual environments, build systems, CI systems, test frameworks, targets, hosts. Your code doesn't exist in isolation, you need to grok how it works with the codes others have written and will write.
But for each one of these, the less I have to know about its internals, the better.

The ideal option for each of these things is that it "just works". When you have to think about the internals of your package manager or your CI or your virtual environment, that's a flaw in it, not a reason to celebrate.

You want simple internals, and one would expect programmers to understand those internals. You want the userspace to do obvious things with those internals. You don't want magic in between. Understanding internals is a feature, not a bug.

I picked Debian over Red Hat since, at the time, I could understand how .deb packages worked, and look over the state of the system. Red Hat had more opaque internals. If something broke on a Debian system, rare as it was, I could go in and fix it manually. If something broke on a Red Hat system, it was generally in a binary database file, and meant a reinstall. Red Hat also broke more often, I think for very similar reasons in design philosophy.

If I were making a tool for grandma to manage her photos, that's be something different. If you're making a coding tool for 3rd graders, perhaps you want to hide more stuff too, but even there, many modern coding environments translate blockly into Python/JS/etc. code, and show the code to kids so they can see under the hood.

I have a car, and as a car user, I want thinks to just work. As a car mechanic, I'd like things to be understandable, fixable, documented, and transparent.

git is like that. It has simple internals. Once you understand them, the userspace become very understandable too. The upsides of the elegant internals far outweigh the downside of a slightly clumsy userspace, which is why it's the dominant VCS right now.

It took over precisely from things which "just worked" with a simple userspace, and clumsy internals, like SVN and CVS.

I take the view that developers shouldn't be spending their time fixing their VCS.

I use PyCharm. I don't know how PyCharm works internally. I don't even know what language it is written in. I know that it provides syntax highlighting, smart replace, code completion, etc.

Similarly, my car mechanic has a bunch of tools that he doesn't understand in detail; they have interfaces (like a gauge on a pressure sensor).

Progress requires these interfaces, it requires these abstractions, and over time I'm pretty confident that we'll get a better VCS than git that has better, more user-friendly abstractions and it will take over the market.

It comes down to your distance from a specific 'tool' or system.

You aren't writing x86 assembler. You are presumably writing some other, higher-level language. I would fully expect you to know that language in detail and even better to understand the performance implications of the choices you make in that language. Knowing the lower level details helps there, but it's not 100% required.

With git, it's something you _directly_ interact with so I would expect you to understand it in great detail.

> With git, it's something you _directly_ interact with so I would expect you to understand it in great detail.

Yes, you are describing what is broken about git: its abstractions are leaking too much so people who touch it have to know all its internals.

I touch x86 assembler every time I run high-level code, it's just that other kind folks have gone to a lot of effort to make it so that I don't have know how the internals of that low-level stuff work.

Abstractions allow people to be productive without knowing in great detail how absolutely everything in the universe works. A good tool has simple, non-leaky abstractions with a simple interface. Git is not a good tool.

Yes but filter-branch is horrendous and could very easily result in unintended side-effects, as well as potentially being very slow. I think this command is a great example of the problem; what a user really wants is an undo button but what git gives them is this thing.
There is a minimum bar for programmers I'd want to work with. Fully understanding git, for me, is part of that bar. The problem is that many programmers don't know how fundamental git is:

1) It's like understanding the basics of databases, network protocols, or compilers. It gives a lot of insight to how things work in a pretty deep and generalizable way. How do you organize data, and why are DAGs, Merkle trees, and hashes awesome? It's a beautiful case study in data engineering.

2) It's like knowing the shortcuts in your editor. It makes you more productive. If a programmer is hunt-and-pecking to type, and gets confused by shortcut keys, they'll be less productive.

Yes, I understand not all programmers will know how important it is to know this stuff, and I won't disadvantage someone who hasn't done this YET in hiring. But I would never hire the type of programmer who says "I don't need to know this." You do.

I'm sorry, but it takes a couple weekends of work to write yourself a git end-to-end from scratch. That's 0.5% of the time you put into a CS degree. If you don't have the interest, discipline, or drive to do that, there are plenty of jobs out there.

git internals are simple, but hard. Like Go. If you don't understand them, the userspace is a near-infinite pile or arcane complexity, incantations, half of which break something in counter-intuitive ways. If you do, it's a matter looking up the right command in the docs in a few minutes.

Yes, compilers, database, and other tools abstract away a lot of stuff. But if you don't understand the internals, you're likely to hurt yourself and my system in very bad ways. I don't want that on my team. My experience is good programmers are fluent one or two abstractions up and down, to not e.g. make a database query that does a full table walk, run out of stack space with a compiler that doesn't do tail recursion (and conversely, know they can use tail recursion with ones that do), etc. A tool you use every day definitely falls into the category of Stuff You Ought to Know, in a way that understanding how quantum tunneling is used in an SSD is in the category of Stuff You Don't Need to Know.

If you're hurting yourself with git, that's a good signal it's in the Stuff to Know category. And if you've wasted more than a few hours fighting git, as it sounds you have, it sounds like making a focused effort to learn it will save you time in the long term. Probably in a few months, even.

> A tool you use every day definitely falls into the category of Stuff You Ought to Know, in a way that understanding how quantum tunneling is used in an SSD is in the category of Stuff You Don't Need to Know.

I use an SSD every day though, as well as an LCD display and a laser in my mouse. So by this reasoning, I need to study quantum mechanics; it would only take a few weekends of focused study to understand the Schrodinger Equation etc.

These things fall into the "Don't need to know" category because we as a species have made very effective user interfaces to them whereby you really need to know almost nothing about their internals to use them.

The ideal version control system would work like a mouse or a monitor. Completely intuitive, just works™.

With that attitude, I would never, ever, ever, hire you.

As a footnote, I would expect you to be able to understand things like SSD performance and reliability, and how it's affected by complex algorithms in the drive controller (e.g. wear leveling, garbage collection, write block size, etc.). I would also expect you to be able to understand things like how subpixel rendering works, how rendering engines coordinate within LCD refresh, or how displays advertise their parameters to computers.

You shouldn't take those as black boxes either. You do get into bugs and issues which relate there, and an experienced software engineer will have a depth of knowledge around oddball topics like that. That brings huge value.

It sounds like you're not a nerd. Why did you go into software engineering? It sounds like you're not interested in the stuff. There are lots of career tracks which don't expect people to do those sorts of deep dives, and where willful ignorance is okay. Engineering, including software engineering, just doesn't happen to be one of them. All the good software engineers I know will do dives into this stuff, and that expertise accumulates over time.

The key thing is most of us enjoy those deep dives. That's what makes the career track a good fit.

If you don't, you'll be doing the equivalent of maintaining a COBOL database on a mainframe as you get older.

For my engineers, I'm not looking for tools which are "Completely intuitive, just works™." That's Scratch. I'd advise you to code in Scratch if that's what you want. I want tools which enable people to be productive, efficient, and get stuff done at a high level of quality. If that has a learning curve, that's okay. People are coding 40 hours per week. If my programmers spend a month learning each year, and that makes them 50% more productive, they'll beat your Scratch team. That's why good programmers get paid the big bucks, and mediocre programmers can't find jobs.

> With that attitude, I would never, ever, ever, hire you.

There are two separate issue here though.

(A) How much work does a given person want to put in

(B) How much work does a given tool require.

It can simultaneously be the case that git is bad/overcomplicated AND that you should only hire people who bother to learn it really well.

Why?

Well, learning hard things is a reliable signal of diligence and hard work, which are generally useful traits.

But at the same time, forcing everyone to learn something annoying and time-consuming just as a test of grit isn't maximally efficient. The same effort could be put into more productive tasks.

> Why did you go into software engineering?

Well, I'm not a software engineer - in the Data/ML area so I am much more interested in the properties of data than the properties of code. But having said that I certainly like clean, efficient code and I care about languages (maybe just spoiled by python?!).

I can't see myself as a software engineer so I think your instinct is right. My passion is data and ML.

It's not a test of grit. git happens to exemplify -- as well as any system I know -- many aspects of good data engineering. If you're into data and ML, those are things you ought to know too.

For a data/ML position, in most cases, I'd expect you to be able to handle data cleanly and efficiently.

If you can't, there are jobs far over on the data side, but:

1) As a business data analyst, you're fine with Excel and PPT, but you'll be paid roughly 1/3 of an ML/SWE position, and you should have excellent communication skills.

2) There are primary mathematical positions, where you work with a data engineer, but you'd better be awesome at math. AND it still helps to be able to handle data cleanly.

Even so, good data workflows require knowing what you did, when, and to which version of data. Properly used, git provides an archival log of some of that. I use very similar data structures when I build some of my own data pipelines too, with data stored under its hashes, Merkle trees, DAGs, and similar. If you find that "annoying and time-consuming," I'd hire you for a business data analyst, and not much more.

It sounds like you find that stuff boring, though. It's a test of interest, passion, and drive, much more so than diligence and grit. Although those are important too.

A good data management system (with hashes of datasets etc) is great. Data mess is not fun.

Merkle trees are also fun and have applications elsewhere like cryptocurrency/blockchain.

I don't have a problem with computer science in general, it's a fascinating subject.

+1

These commands will get you 99% of the way:

- git status

- git branch

- git pull

- git add

- git commit

- git diff

- git merge

- git push

- git checkout

For everything else there's StackOverflow, but the info in there comes with the risk of being stale.

--------------

Edit commit abaeb3b4: Add missing commands and improve formatting

Edit commit 842babda: Add git checkout

`git status` is required to determine which untracked files you need to add. And then, of course, `git add` would be need to be added to the list too. To add untracked files you could use interactive mode `git add -i` and forgo reading `status`. But you can also `git commit -p` if you only modified files and forgo the `add` step.

And to give yourself a sense of the commit graph, these aliases come in handy

    [alias]
        lol = log --graph --decorate --pretty=oneline --abbrev-commit
        lola = log --graph --date=short --pretty=format:'%C(auto)%h %C(dim)%ad%C(auto)%d %s' --all
The only 'advanced' thing I commonly do is `git rebase -i` to squash a bunch of WIP commits. And a shell script I have to turn merged branch into a tag, and remove the branch.

The other day I had to remove a sensitive file that accidentally got checked into the repo for a couple of commits behind HEAD, and was glad that git had the power to do this in one line and without fuss. (Edit: but yes, I had to look it up on SE)

Indeed, I forgot 'git status', and 'git add'

I've honestly ever felt the need, or had the requirement, to look at the graph.

I've found it indispensable when tracking and integrating other peoples' branches. I wouldn't use it so much if I was working solo.
I've never worked solo. My teams tend to be around 6-8. Across a dozen teams, myself and nobody on the team save a couple even looked at the graph. One who loved a clean history showed it off, people thought it was pretty, and went back to work as normal. `git commit -am 'slightly helpful message' && git push origin $branch` does about 90%+ of what I've needed. When we merge the branch, squash merge works fine. History graphs, I've never felt the need for them.
We're the exact same except for the squashed merge (which I have no real objection to doing)
Each to their own. I use it in situations where i want to know what other people are basing their branch from. Which, for projects I've worked on, can have real consequences. For instance, it may prompt me to rebase upon their work sooner, or even give them a heads up that theirs some useful change I'm submitting to the trunk.
ah, that is likely part of it. We always branch from master and merge back to master. Builds prevent failing code from merging. It is rare that we branch from a branch, and that 2nd branch would never be merged before the first.
During rapid mobile and frontend development, occasionally I'll be working on someone where there's co-depending feature branches, but for the most part the team usually follow something like git-flow. But I take your point that viewing the graph isn't essential, and those aliases might look scary on a one-page crash course. (I really think `git lol` and `git lola` should be first class citizens of a git installation though)
So this, to me, is not a 'benefit of git' it articulates in some ways how bad it is (although very powerful).

Most people can get going with those 99% commands quite quickly, the problem with git is any move from the known path creates some pretty amazingly complicated scenarios.

And those '1% of the time' commands blow up into time-consuming rabbit holes of complexity. Often, Stack Exchange has several answers for the same question, highlighting just how much inherent complexity there is in the product.

Managing software versions across repo can be a very, very complicated problem. Git provides you with a pile of tools to do 'almost anything'.

A 'well designed product' would make the toolsets and concepts focus heavily on the 'main operations' and then have clear, clean rational idioms, practices and tools for the odd cases, and 'dangerous cases' wouldn't be allowed without some kind of special command.

They have the 'Golden Rule of Git' which is to not rebase on a public branch - this is an excellent example of poor product design. There should be no 'golden rule' that developers have to understand - it shouldn't be possible (without special admin commands). If branches are named/tagged and managed properly, the system would be smart enough to let you know you can't do that, and why.

Administrators exist for a reason, 'sudo' exists for a reason etc.

People who love powerful things, and have an inclination towards complexity seem to love git, people who have a product orientation see it differently.

You can't push a rebased branch without`--force`, and the server can be configured to disallow it entirely. This is exactly how it should be: I want to be able to rebase my by public branches but not the public branch.
" I want to be able to rebase my by public branches but not the public branch."

Already that's a little bit complicated though.

Even though yes, this use case probably does exist, it might be a tricky thing to unwind for some people - what would they do when they have already changed the history of 'their' public branch (?) is something they'd have to carefully think about.

you shouldn't change history once you make it public, how hard is that? that's the golden rule, if you promise something to be immutable, stick to your promise
Tags are immutable. Branches are mutable.

You can add to them and refactor patch series that are on them, equally valid in the eyes of git.

For example a development branch has no implied "promise" about stability of its history, it is much better to not only refactor the code but also refactor the history so sub-patches are squashed into the single feature patch that they logically belong to, and not spawn lives of their own. There is no reason to run that kind of development branch like a stable "branch of record".

'Don't shoot yourself in the foot with a gun - how hard can that be to understand'?

And yet people do it all the time.

The 'rule' is easy enough to understand.

But it's not always clear 'why' that is (in many cases, it won't matter), or when exactly it applies.

In the lowest common denominator cases, the rule is not so hard to follow, but it can get messy quickly and there are many ways to break the rule.

Stack exchange has multiple answers for most questions. It's not a useful metric; the domain is inherently complex. git has warts, like c++, go, react, npm, rust and all their cousins.

It comes with the territory. We're dealing with tools borne into world where they are, more and more, expected to be suitable for any purpose. Tough mandate, and not the tools fault.

One day git will be supplanted with something that has a different set of issues. Progress.

I use git daily. I never use merge. I use git rebase, and its interactive version all day.
You'll potentially need to use merge if you're collaborating with others on feature branches.
Ya, I'm the opposite, I never use rebase. Horses for courses...
You should, or do you just merge updated remote branches into your stale local branches? A lot of new developers seem to do that here until we explain to them how it messes up the history.
> do you just merge updated remote branches into your stale local branches?

Every single developer I work with (or have in the last 8 years) does this. "Messes up the history" ? The merge commit describes that there are uptaken changes from the "main" branch. It doesn't seem to be a problem in practice.

It's also not a problem for me, because I squash the commits on merge to master or other remote branch.
I've been doing that for years, and it's never messed up the history.
We don't merge one-off branches into other one-off branches unless they're all under the same feature. Everything goes via develop when they're complete, and new one-off branches are created from develop.

When we release to production, develop gets merged to master.

We consider a 'feature' a large piece of work that will take several weeks, during which time several releases to production may be done for other work/tickets.

I think `git checkout` definitely needs to be there. Also `git reset` in case you make a mistake while `git add`ing
I think the most common usage of that - switching branches - could be replaced with `git switch` now. That leaves `git checkout` in the set of more advanced operations for more niche use cases.

Same goes I think for `git restore` over `git reset`.

Added checkout. I'm not sure about classifying 'git reset' as an 'everyday' command.
Correct. The use case falls under `git status` really, it will give you boilerplate commands like `git add`, `git reset`, `git checkout -- file`, or even `git rebase --abort` depending on a situation.
I use git-show a lot to look at individual commits. Would add that to the list.
> I'm not an idiot, but I don't fully understand git. I am coding for a living, and I use git every day. I probably could sit down for a couple of days and fully understand how git works, but I've never needed it, I understand how basic git operations work, and I stay away from commands that I don't understand.

That's a great summary for the majority of Git users. I am still motivating people to spend the time to learn it "properly" if they're using Git daily.

First of all, it will make them more efficient. I've seen too many people literally redoing their changes, because a cherry-pick/rebase is "an operation they don't understand".

Secondly, they will be able to solve most issues when (not if) they occur. Sure, I am more than happy to help my colleagues solving their issues. From "why are those changes in my PR" to "our Jenkins job went rogue and now we've got hundreds of MB of data in our repository that we would like to remove". But the time of me explaining things the "learning by doing" style would be better spent actually learning Git.

Imho Mercurial is much easier than Git. I have seen team members who lost data with Git but never with Mercurial.

I still miss Mercurial. Unfortunately most people moved to Git so I also moved to it.

Quite some years ago we switched from git to Mercurial and the amount of VSC mentoring and unfucking the "VCS guys" had do became almost zero. People seriously just got it. Some argued that is was because they had to learn with git, but... since then we've made the switch back to git for other reasons and we've back at wrangling with the tool again. I'd much much rather use Mercurial with Evolve extension - that is really good.
>Unfortunately most people moved to Git so I also moved to it.

The Lemming Effect.

Agreed - I started to use version control back with SCCS somewhen in the early nineties, and RCS, CVS, Subversion, ClearCase, some Microsoft horror with a name I can't recall, and a few others. My conclusion is exactly the same as yours: "Git is the simplest version control system I've ever used." And it also improved my overview over what happens and has happened in the past - I can jump back in for stuff I haven't touched for many years. So I now think of the older version control systems I used over the years as simple "snapshot backup" systems, not real version control. (NB: I've never actively used Mercurial, other than because some projects use it, so I'm not comparing Git and Mercurial, or the other one or two systems with similarities.)
The version control system your subconscious mind recoils in horror from is the dreaded Visual SourceSafe, one of the worst-named product ever.
That's possibly the one.. I worked for a year on a customer's site, and the source we delivered had to be put into their MS VC every time we delivered it. The major pain was that the namespace was flat.. you couldn't have more than one file in the whole tree called "Makefile" or "ChangeLog", for example.. so we made a transformation tool to make every file name unique before it got pushed into the version control system, and a reverse tool which transformed back when you checked it out, so that one could build the software.
Oh wow, ClearCase. That's a blast from the past that I'd forgotten even existed. CC was the stuff of nightmares.
A blast from the past that some of us still have to use on a daily basis, sadly.
I've used a lot of different version control systems over my many years in the industry and git definitely isn't easy. The basics aren't hard but it's easy to get into a pickle if you need to delve slightly out of common patterns.

The git CLI tool isn't great either -- that's probably the hardest part of git.

Exactly.

I like to say that git is a "white box". You need to understand the internals to be able to use it.

Contrast this with "black boxes" where you don't have to or even can't understand what's going on.

Some would argue that software shouldn't be built that way, but I will respectfully disagree. It's not an end user facing consumer product, it's a tool for professionals. You wouldn't expect anyone to operate a table saw or a milling machine without some understanding of what's inside the machine.

I do agree that the git user interface is inconsistent and full of caveats. But as long as you understand it's just a directed acyclic graph of commits, you can dig yourself out of any hole you get into.

"You wouldn't expect anyone to operate a table saw"

? Coming from a family of carpenters, I can assure you none of them really know that much at all about the internals of the table saw. Maybe a little bit.

The 'black box' analogy is upside down: there are a million artifacts of the computer that you use every day for which you have no understanding. We use encapsulated concepts to be able to leverage much more complexity than we would otherwise.

Having to deal with the 'inner workings' of git, is like having to have the instruction set for the chipset your computer is running on handy 'just in case'.

Git is very powerful, but very poorly designed from a product perspective, there was no 'strategy' just 'add commands and flags that do this and that'.

When products expose considerably more complexity than they need to for most uses cases, it's just bad design.

I also have a sneaking suspicion that so many 'git experts' are really just expert within a fairly narrow range of commands/options - because when I start to ask more detailed questions, the answers are never clear.

No other product has consistently caused so much confusion, wasted time. Though 95% of my personal interactions are fine, there are just too many times where we have Senior Developers, huddled on someone's machine, trying to solve some arcane problem - this is the 'not very hidden cost' of git.

I would say: "Within Git, there is a much smaller and clearer CVS struggling to get out."

> Coming from a family of carpenters, I can assure you none of them really know that much at all about the internals of the table saw. Maybe a little bit.

Every carpenter I know knows how to change the blade, tighten the arbor, check the fence, adjust riving knives, clean away the dust, tension the belts (if applicable) and maybe even change the motor. And there isn't much more to a table saw.

Getting back to Git, I agree with your sentiment "Within Git, there is a much smaller and clearer CVS struggling to get out.". Most of us should strive to stay within the set of simple git operations.

However, then there's all the other corner cases that are sometimes applicable. Such as clearing away your accidentally published private keys using `git filter-branch`. Most of us will never need this, but it's there for a reason.

But if one groks the "DAG of commits" concept behind git, you can understand what filter-branch does and why and how. It's not a very complex concept.

Again, I won't defend the inconsistent user interface. It could be better. But even that can be understood when needed by looking at the documentation as long as the concept is clear.

The underyling concepts are fine, the problem with git for me is the inconsistent command line interface. Stuff I'm doing less often than once a month I have to check in the manual every time. And it's nothing inherently hard - stuff like removing one change from staging or cleaning up local branch to be exactly like remote. The interface just feels like stuff is arbitrarily assigned to different commands :)
> stuff like removing one change from staging

I click on the file and click on "unstage". I don't know why people insist on using the command line for their dvcs. Is it even possible to selectively unstage or reset only a part of a file without a GUI?

> I don't know why people insist on using the command line for their dvcs.

I use both. More complicated stuff I usually do from the command line because I do them rarely enough, and I change IDEs often enough - that I just don't know how to do them in IDEs.

I used git regularly for last 6 years and in that time I've been using eclipse, netbeans, kdevelop, qtcreator, visual studio and intelliJ. And a few fringe IDEs as one-offs. I would have to remember 7 different paths in nested context menus for everything. I believe it's not "unstage" but "rollback" in IntelliJ, but I would have to check that in documentation before I do it anyway.

> Is it even possible to selectively unstage or reset only a part of a file without a GUI?

Sure - it's even faster than in gui, because you do it with keyboard only. I just can't remember the exact options.

You don't have to learn 7 IDEs, I've never used git commands in my IDEs. Just use one git client.

And you don't have to remember the menus because they are contextual. Select a portion of text: unstage selected lines, reset selected lines, etc. Select a commit: checkout, create tag, revert, etc.

Things that are complicated on the CLI become routine and that changes the way you work.

(comment deleted)
Git is I think objectively more complicated any other popular VCS, simply due to the fact it has much more in the design model.

It's also more powerful.

But the tradeoff is ugly within the context of the nature of the UI.

Git is like C++, it has a lot of features, the UI is not well thought out and it creates countless corner cases.

Git was not designed to focus on the core cases, making things simple.

Git is one of the great 'litmus tests' for product design thinkers. People who don't understand why git is problematic (even if they are really good at it) I think would have trouble with product design.

Git is more popular because Github used Git and Github was better than google code or sourceforge. Bitbucket got like 80% of the way there but was always a few steps behind. Had bitbucket taken off rather than github (which is much more to do with the web UI and network effects than the underlying VCS), we'd all be using hg now.
(comment deleted)
I don’t believe this. If you manage to use the git CLI you’re not put off by bad bitbucket UI.

My explanation would be:

Git won because it was used for Linux and because it was fastest where it mattered.

Sounds like Betamax vs. VHS!
>But IMO it isn't because Git is hard, but because they don't have to truly understand Git to use it. That's how easy it is.

A copy&paste of my previous comment:

Everybody's brain is different but I actually understand all of git's internals (the "plumbing") but it doesn't help me with the git CLI (the "porcelain").

Yes, I know that Git is a DAG (Directed Acyclic Graph), and that HEAD is a pointer, and the file format of BLOBs and SHAs, etc. If I were to implement a DVCS, I would inevitably end up reinventing many of the same technical architecture decisions that Linus came up with. But none of that insider knowledge really helps me remember git syntax if I haven't been using it in more than a month. Even though I grok git's mental model, I still can't answer the top-voted "git" questions on Stackoverflow without a cheat sheet: https://stackoverflow.com/questions/tagged/git?tab=Votes

The git UI and unintuitive syntax is just too hard for me to remember unless I use it every day.

Also to add.. the concept of "git index" as a staging area adds some complexity as well. Yes, there are good reasons for it (1) it lets one craft a specific subset instead of all changed files to commit and (2) it's a performance boost because a Big-O type O(n) loop runs faster when iterating through the staging index (small "n" of dozens) to detect changes instead of looping through the entire source code tree (large "n" of 10,000+ files in a big repo). But that flexibility adds an extra cognitive burden when a newbie just wants to save a "backup snapshot of the repo". For a newbie, the extra indirection layer of "staging index" seems superfluous and confusing. That's why some present an alternative porcelain to git that doesn't expose the staging concept: e.g. https://gitless.com/

(To clarify, I'm not recommending Gitless but just giving an example of why some felt motivated to simplify Git's porcelain.)

Totally agree on the "staging area". I've always thought that the staging area should only activate when you `git add` or otherwise add files to it. If there are no staged files, then git commit should act like git commit -A.
Oh hell no, Visual Studio has this behaviour by default (commit all changes if nothing staged) and what we end up with is that some people keep checking in various experiments and privately modified launch config files (that should not be in the repo anyhow but that's another story related to the tools) that end up causing a lot of unnecessary merge conflicts when you pull in their changes (where you were really only expecting some other part).
We deal with this via code review. Anything with such files is going to get instantly rejected. And people soon learn not to do it.
So with every new hire, you have burden the reviewer again? Wouldn't it be better to make the default so that Visual Studio burdens the primary developer, instead of the reviewer?
We prefer to automate everything that's automatable, and then a bit more, because reviewing is hard work.
> Even though I grok git's mental model, I still can't answer the top-voted "git" questions on Stackoverflow without a cheat sheet: https://stackoverflow.com/questions/tagged/git?tab=Votes

This was surprising to me, and shows how different people's experiences of git can be. My workplace switched to git from an obsolete centralized VCS earlier this year, and I could easily answer these.

Something like this is probably where the line between those in this thread who agree that git is too hard, and those who think the detractors are just lazy and stupid, runs. Folks, people are more different than you expect!

> I could easily answer these

Maybe you find it easy because you don't see the subtleties. The answer to reverting the last commit for example can't really be that simple because it depends on what the user really wants to do. Do you want to keep the changes in staging? Reset the index but keep the changes in your working copy? Or reset the files to their state at the previous commit?

I fully agree that the default porcelain has poor UX for managing the staging area, but doesn’t a porcelain without it encourage overly large commits?

All sorts of workflows become substantially more difficult (if not impossible) with kitchen sink commits. Undoing a single-line change, for instance. I dislike large pull requests, let alone commits that introduce a half dozen different changes.

Sure, if you’re really disciplined you can produce small commits without staging, by committing as you go along, but you’re breaking flow every time you commit in this style.

I say all this because I would love a CLI that has half-way sane handling of (e.g.) restoring staged, deleted files; doesn’t conflate restoring files with switching branches; has consistency of flags between commands (such as commit vs stash message); etc., etc. I should try gitless ;)

> I fully agree that the default porcelain has poor UX for managing the staging area, but doesn’t a porcelain without it encourage overly large commits?

No, I'd say the opposite. The staging area encourages me to think that I can make my change and split it up into logical commits afterwards, even though I know I'll actually just give up and make it a big commit. When I didn't know about the staging area and just committed whenever I could, I produced better, smaller commits.

> The staging area encourages me to think that I can make my change and split it up into logical commits afterwards, even though I know I'll actually just give up and make it a big commit.

That sounds like a personal discipline problem and not a poor tool.

The whole point of a tool like git is so that I don't have to expend personal discipline.
That's like claiming a gun is just used for shooting other things and that the point of the gun is so you don't have to understand how to handle it. Then when you shoot yourself in the foot you get mad at the gun and not yourself.
Guns are expected to be drop-safe. Some people say "well you shouldn't be so careless with a lethal weapon anyway", and yet most people will want their gun to avoid firing a bullet when dropped.
That's how you get good commits... you do a bunch of changes to understand what you should have done and then you retell the story by carving it into commits. I have been doing this constantly for like a decade now and almost never "give up"... in contrast, Subversion, which doesn't have a staging area, is almost impossible to use as it requires you to somehow code in order the first time, which is ridiculous: no one is that perfect.
> porcelain without it encourage overly large commits?

Not for me. When using Mercurial back in the day I would manually split up commit, usually by copying over sets of files into a clean repo and committing there.

In Git tho the staging area is a lie. It encourages you commit half-truths. What I'd really want is to be able to enter a commit mode where the on-disk and staging area roles are flipped.

I want the stuff on disk to be what I commit, I want the "staging area" to be the changes that I've made that are not yet committed. This way I can pick a set of changes, compile, run tests and commit.

With Mercurial you could sorta do this with stashing I think, but I swore off it after losing changes a few times.

You can do the same with git stash, but it's also inadvisable because of how easy it is to lose changes. My workflow in this case is to checkout a new branch and commit the work-in-progress there, then switch back to the previous branch to check the commit. I've seen numerous pre-push scripts that do exactly that.

I wish git didn't use the disk at all! It gets in the way of parallelizing work. For instance, I'd love to be able to make a bunch of trial commits, then in parallel verify that none of them breaks the build. Or while a build/test loop is happening on one branch, switch to another to continue working.

> In Git tho the staging area is a lie. It encourages you commit half-truths. What I'd really want is to be able to enter a commit mode where the on-disk and staging area roles are flipped.

https://github.com/tv42/staged does something like that by writing the staged content to a temp dir.

(It has some smarts for Go GOPATH adjusting on top, but might not do things right with modules, at this time.)

Thinking about it, I guess it should be possible to flip this around by using a temporary local branch. Commit everything there, then cherry-pick into repo dir and commit proper.

Once done delete temp branch and push.

Maybe what we really need is not a new VCS, just a new CLI frontend for git.
If it was easy to create a frontend that worked seemlessly on a git repo then it would have been done already.
Buzzkill! I think it's more a matter of that those who are in a position to do so are used enough with git-cli that they are happy with the status quo.
It has been. There are numerous such projects; gitless comes to mind since somebody else brought it up in a comment here.
So the problem is solved and the OP blog shouldn't exist?
Your point being?
> But that flexibility adds an extra cognitive burden when a newbie just wants to save a "backup snapshot of the repo".

Simple needs have simple answers.

    git add .
    git commit -am '2020-11-17'
Sure, you can ask "why are there two commands?", but this is not so much an issue of cognitive burden as of typing burden. If you only want one thing, you only have to know how to do one thing. If you don't want to know why the procedure does what it does, you don't have to.
When you're writing into a text file and then save it, you don't have to manually select what lines or pages you're saving - you're saving all of it.

This is the mental model 99% of newbies will have for something that basically pledges to save and sync each version of your files.

Deviating from the user's mental model will create roadbumps and should not be done without a very strong rationale. Especially not for a feature that's fundamentally optional.

When you're writing into a text file and then save it, you don't have to manually select what lines or pages you're saving - you're saving all of it

So? When you're saving a file, you're also overwriting its entire contents. Good luck reverting back to the file before you saved it.

There is no automatic model for "this change is worth tracking" and "this change is not important enough to annotate". That's the model that git is enabling, and it has nothing to do with the "save" button in an editor. If anything, it has more to do with the "track changes" feature in Word, but more powerful because it allows you to group multiple edits in the same change.

> When you're writing into a text file and then save it, you don't have to manually select what lines or pages you're saving - you're saving all of it.

I don't understand the point you're trying to make; this is just as true of the command I gave.

"Simple needs have simple answers."

  zfs snapshot pool/home/git@2020-09-07
For snapshots use backups. Git is not a backup.

For the questions, what's bad with quick help on SO? It's maybe less effective than reading the documentation that ships with git itself but for sure much more popular and less to read.

Git truly is a command-line utility, little known is that it ships with more than one gui in the base package out of the box. handling the staging area with git gui for example is straight forward unless you have more than 5000 unstaged files, then the gui informs you about it's limit and mass handling is far easier on the command-line anyway.

> Even though I grok git's mental model, I still can't answer the top-voted "git" questions on Stackoverflow without a cheat sheet

This sounds like you just don't use or need those things much, which is fine if it works for you. Of the top 10, I can answer 9 of them without doing any research because I've used these commands a lot and they've become a part of my workflow. The one I'm missing? I've never renamed a git branch. If I needed to, I'd probably just do git branch --help or google it and figure it out in five seconds.

You don't need to commit every command of the program to memory. Just like anything else in tech, knowing how to find the knowledge you need is good enough.

I feel the same way, I understand git pretty well but cannot for the life of me use the CLI. Fortunatly there are some pretty good GUI around, I personally use GitExtensions and find it suits my brain nicely. Its windows only though, not a problem for me since my work forces me to use Windows and I don't code at home but surely they are nice git GUI for Linux no ?
It doesn't matter how easy the concept is if the information it contains is not something I can estimate, and in the case of git all the power is coming from indirection, which is famously inestimable stuff.

Can I use git like a simpleton? Absolutely. Can I gracefully recover from errors in its application? Nope, it never happens. It's a chainsaw and I ultimately have to solve the problem by using it like one.

Imagine SQL databases worked exactly like they do now under the hood, but instead of current SELECT/UPDATE/INSERT/DELETE they used like 15 different commands with at least 4 switches each.

So instead of SELECT you'd have FETCH, PULL, CHECKOUT, CLONE, READ, PEEK, and OBSERVE. And each of them could in some cases also modify or even delete the data depending on the switches.

Imagine there was no division between DML and DDL - you just have to remember which option switches change the schema in addition to doing some other things.

And then people would say "SQL is very simple, just learn relational algebra".

That's how I feel about git :)

With SQL I know for sure I can't break the database by doing a select. I know I can't change schema by doing a DML.

With git I'm pretty sure I can't break anything by doing git status, but other than that all bets are off.

In distributed databases, with support for merges and conflict resolution, we have these commands. :-/
Imagine if SQL databases had reflog.
You're still imagining a centralized solution with a single source of truth and less power than Git. Git history is a directed acyclic graph, not a single linear timeline.
"less power" definitely depends on what you value when comparing Git against real databases, e.g. https://stackoverflow.com/questions/984707/what-are-the-file...

There is at least one database that exists which does support a Git-like DAG for transaction-time temporality: https://terminusdb.com/

It should also be pointed out that "temporal databases" usually offer a lot more besides a linear transaction-time history. Although I've not seen anything that offers a DAG for valid-time histories yet :)

SQL presents an static picture. It doesn't really provide a way for you to manage and integrate several different views of the world or provide a means to retrieve the history of all changes you have made throughout all of history.

In your list of shout commands I don't see anything that could be used for merging? I guess the "language" of git could be tweaked to make it more consistent, but otherwise the problems it is trying to solve are more complex than what could be dealt with in a SQL dialect.

> It doesn't really provide a way for you to manage and integrate several different views of the world or provide a means to retrieve the history of all changes you have made throughout all of history.

    select ... as of timestamp;
> In your list of shout commands I don't see anything that could be used for merging?

I'm not arguing for using SQL as a git interface, I'm just saying git would greatly benefit from better interface based on some consistent and clear separation of concerns.

> the problems it is trying to solve are more complex than what could be dealt with in a SQL dialect.

It's not. SQL simplified A LOT of underlying details. There are dozens of types of indexes. There's partitioning and sharding. There's online backups. There are transactions - local and distributed ones. There's savepoints and rollbacks.

If SQL databases were like GIT - selects with joins using different indexes would have different syntax because "you need to understand the underlying structure" :)

Perhaps what's needed is an ISO committee to standardise git, or even version control semantics in general, similar to C, and in particular SQL. Once everybody agrees on how it should look, the community can swallow the pain of migration safe in the knowledge that new possibilities are unlocked.

Based on how SQL and C/C++ faired in these kinds of processes we could have a standard abstraction layer in perhaps 10-15 years ...

It's years ago, but I recall as a rookie I found mercurial way more approachable and easy to grok. Still distributed and a similar model to git, but considerably more approachable CLI interface and manpages.
Git's hard when you see googling for syntax as a failure in the system. If you see getting SO answers as working as designed, it's quite easy. The main learning curve is just the idea of everything being branched, which is an increasingly common concept in many spaces.
A lot of people don't truly understand operating systems and yet they manage to use Windows.

You are setting a very low bar.

I've always found linear algebra to be far simpler than any other advanced mathematics. It's basically just a lot of book-keeping and consequences from that. Yet I know smart people who failed it multiple times and had to change majors to avoid it. That makes me pause before dismissing people who complain about it.

The article has a better way to assess difficulty, based on how easy it is to teach other how to use it.

"Truly understood" is close to a holy church I guess.

However it's perhaps really that too many people are thinking they need to use git because their church says so and then have to deal with the self chosen authority.

(comment deleted)
Having used a few of these version controls over the years each one has its kind of 'core' strength. Most of them evolved next to each other and borrowed the shorthand of each other and copied each others API/GUI/CLI (mostly), and the shorthand of a physical library. git on the other hand stands alone in its interface. in many source controls 'checkout' for example means I get exclusive control of this file on this branch. Where as in git it does not mean that at all. That is where much of the misunderstanding comes in for git. The commands are kind of the same names but do very different things.
I think there are many aspects of Git that are obscure/error-prone regardless of how well you understand its implementation.

For example, the concepts of "ours" and "theirs" when looking at changes depends on the current operation mode (rebase vs merge).

Merging is unsafe-by-default, because it auto-merges even if both branches have modifications to the same file, and there is no guarantee that the resulting file is correct.

There are numerous ways to collaborate on a git repo, with vastly different performance/usability implications, none of which is obvious when you start up (merging remote into local, rebasing local onto remote, squashing local commits; patches vs pushes).

Not to mention that, for teams that work with a centralized remote repo, the whole concept of local tracking branches adds mental overhead for nothing, and extra work every time you want to push a change to a remote branch. You have to first pull, even if your changes and the remote ones don't touch the same files. Which of course means that, if you had a dirty worktree, you actually need to run 3 commands - one to stash your changes, one to pull, the actual push, and now an unstash.

Mental model to use SVN for example was quite simplified.

No connection to the server no committing - no confusion about local vs remote. Branching only on the server, merging totally useless - no branches, no merging, no conflicts. Want to have your local development versioned - zipfile + date time.

I would never go back to that, but from people complains some might want to.

Do you really think the .. and ... notations semantic differences between git-log and git-diff are reasonable?

I personally think if a..b in git log shows me a set of commits then a..b in git diff should show me the code contained within those commits, the patch files that would generate from them.

I guess this is a foolish expectation?

This sort of developer blindness once you have learned something is why we need user interface people as a whole separate discipline.

The "concept" of resetting? "git reset" does different things in one command: there is no one concept. It can discard your staged changes and working tree so that your workspace looks like your head. It can move your head ref while doing that. It can move your head without changing the working tree. It can interactively stage the changes to another commit (e.g. to selectively revert).

To be fair I have seen a company who had a dedicated git guy who was committing, merging, pushing whatever on behalf of the developer after nth time some of them screwed the repo completely. When I started learning how to use I had people telling me it is difficult, but were not able to explain why they think it is difficult and I started learning having this in mind and that made it unnecessarily complicated. I think once you know all the terminology and a few workflow scenarios, then it is very easy.
Some companies have a commit queue that takes care of actually merging a PR as part of their CI that mitigates this problem.
I have this view with calculus. Basic integration and differentiation is just simple arithmetic.
I work with people who continue to struggle with it, and occasionally make a mess that I have to clean up. They've watched the tinker toy video, and others.
I don't think git is hard at all, it's lightweight and elegant, and quite frankly, extremely logical to understand.. Sure, the syntax can be hard to grasp at first, but that's a reasonable price to pay for brevity tbh.
The syntax is also a bit inconsistent, and reflects git's own development history.

We could probably make a new and better command line interface that brings out the underlying simplicity more.

It's important to distinguish the UX from the internals. I don't know the internals, so they may be elegant and extremely logical, but the UX is terrible.

Git's UX, like a famous programming language, was never designed in a strict sense. It's clearly been written to solve immediate requirement, one by one, without a vision (again, from a UX perspective).

Result: the horrible checkout command, which does a zillion different things, and I bet only few users know all of them. Same goes for reset.

I don't remember all the checkout forms, and I couldn't use git without aliases.

The porcelain interface is another one. Excerpt:

  This is my fault, to some degree.
  The "short-status" form is meant for human eyeballs, and was designed by Junio.
  Some people wanted a scriptable status output, too, so I slapped a "--porcelain"
  on the same format that turns off configurable features like relative pathnames
  and colorizing, and makes an implicit promise that we won't make further changes
  to the format.
  The idea was to prevent people from scripting around --short, because it was never
  intended to be stable.
  So yeah, while --porcelain by itself is stable and scriptable, it is perhaps not
  the most friendly to parsers. The "-z --porcelain" format is much more so, and I
  would recommend it to anyone scripting around "git status"
Note the "slap" here; it's not random.
The directed graph isn't the problem. I think people can deal with the idea that other people have a different version of the code from them. The parts that are hard are the horribly inconsistent commands and the complete mess that is how the staging area interacts with everything else.
Exactly. Reading a book about git will not help you understand why commands are named so weirdly.
The commands suffer from backwards compatibility. And at some point in git's development it was easier to get new options to existing commands approved than new commands. So that's eg the reason 'checkout' and 'reset' do lots of different things.

I wonder whether we could create a much better and more consistent command line interface from scratch?

Not Git is which is hard. Distributed systems are hard! So there is a really hard problem to begin with. One specific example from the post to delete a branch. There is no way to simplify that if you want to make a truly distributed system.
Complaining instead of learning that's what hard. Hard for those who pays attention to it too much.
This feels similar to the no/low code idea. Saying you want to make it more human and doing so without losing some of the power and crispness of it seems hard if not impossible
I fully agree.

I particularly think about this because I had some conversations with people from the open science community. It's really often where I'd like to tell them: "This problem, you really want to use something like git. Although... it's kinda hard to learn."

There's a lot of workflows outside of software development or from people who develop software, but for whom software development is not their primary thing, where a version control system would be really useful. But our current state-of-the-art version control system isn't very well suited for that, particularly not for people who have a limited capacity to learn things or might only use it every now and then.

It's amazing how this often comes from people that's quite accustomed to spend a considerable amount of time in learning their tools, being it complex math, programming, scientific instrumentation, scientific type-setting. But when it comes to version control they expect it to be able to just use it without any effort. I believe git being hard is just an excuse to not change their current workflow.
I would say that people only need to initially learn: checkout, add, commit, push and pull. Those operations cover most of a devs daily workflow (for most companies I've worked at at least). Anything else can be figured out/taught as needed, it's much easier to learn a new concept when you have a use case specific to you.
I know git internals. But I still struggle to have a correct mental model of developping features on branches that you then merge into a very distant branch.

It is ok when you create a branch from develop, code your feature and merge back to develop.

But then things get messy: you need to backport that feature to some release branches.

And all that is asynchronous (backport feature « n+1 » but not feature « n » nor « n-1 » from develop onto branch 1.0 LTS and branch 2.0-SNAPSHOP. ok done? Perfect, let’s ship that. Good feedback from users? Ok cool. Now do the same with « n-1 »)

you want to keep track of code movements between branches, so you use merge (not rebase or cherry-pick).

Pffffiou I honestly do not know how to handle that at scale with Git.

Complaining is not the best strategy for marketing anything. If one cannot use it, why bothering onesepf with more complex problems comes up in software engineering?

A free market theory says anyone can prosper if one does what can do great. Do something else. Learn git. Or drive trucks. Do not complain.

You complain about a blog post right here right now. Time to switch to trucking?
> Click here to listen along while you read. It's better!

No. It really isn't.

Sounds like we need a new, higher-level interface on top of git.
All of those questions in this blog post comes from people who don’t even look into documentation or try to find answers (e.g. learning), and someone is even hiring them.

It’s a sad state of a world we live in. :)

As a user who knows absolutely zero Git, I often fumble around for a good 20 minutes at times trying to figure out how to just install someone's project for consumer use.
Honestly I don't think that is git's fault
Git is different from TFS/SVN. I wonder if Bitkeeper and other DCVS solved the user friendliness part. Not every programmer nowadays is a greybeard, nor do they need to be. If Git can be made easier to use without displeasing greybeards, it should (or: please don't make it into a useless toy).

That being said, I think Git's command-line is becoming simpler -- I don't use GUIs since SourceTree failed to make me notice I was in the middle of a merge.

I find it a little confusing, especially when trying to do something a little unusual.

For example, I had a git repo on a web host and wanted it moved to another host (they cloned it easily enough), but then I wanted to make the cloned repository "authoritative", but I after several hours of looking for an answer I finally gave up. I was able to clone the new repo to my local machine, but I couldn't push changes to the new repo, and had to log into the new host using the console and commit changes there, which was still looking at the original repository.

There is a relatively easy way to accomplish this by editing your .git/config file to point at the new "authoritative" repo.

But there is a simpler (although less efficient) method. Just simply git clone the new repository onto any machine you want. The clones will naturally be configured to point to that new repository as their upstream.

You don't need to change config files.

`git remote rm origin`

`git remote add origin new-url`

`git remote set-url origin new-url`
All those commands do is change the .git/config file. Such commands are great for scripting, but really don't need to be learned if you're comfortable editing simple config files with your preferred editor.
There is a technical difference between an local repo and a remote repo (bare repository) - although I think you can clone from a repo and make this "authoritative", what you usually do is (in your client, not the server)

- add a new remote

- push your tree to this new remote

- remove the old remote (optional)

And that's it.

You're further not supposed to make commits on a remote directly. Usually this fails hard, for a reason.

Is it git that's too hard, or is it that version control is too hard? I suspect that it's the latter.

That is, version control is difficult and git is a powerful tool that exposes that difficulty and the many (complex) ways to approach version control.

The whole point of software is to reduce or manage complexity. Git cli fails miserably at this.

Google's perforce with mercurial client has been the best VCS I've ever used and I now have a deep hatred of everything that isn't that system, especially git.

Git is hard because it precisely models the complexities of concurrently modifying source code on multiple computers. It explicitly models all of the concepts and operations that are relevant in that domain - branching, merging, my local changes, the server that my local branch is kept in sync with, rewriting local history, rewriting public history. Can you shoot yourself in the foot? Absolutely, because this stuff really is non-trivial. Could it be made easier? Yes, by limiting what operations you're even allowed to make, and streamlining those (c.f. git flow).
It would be great to have a GUI tool that allows you to do common tasks with a sort of Wizard interface with validation, precise human-understandable explanations, delayed execution (like GParted) and Undo functions. Personally, I don't use GUI tools for Git because they are either as complex as the command line version or I'm afraid they do something under the hood that is not what I intended. I'm not sure GUI tools for Git are programmed in a way that makes data loss impossible.

Some kind of troubleshooter GUI tool that covers 90% of all use cases would be great. I'd certainly be willing to pay for it.

Exactly what I feel about this tool. I don't get it what is the structure of the inner tree of git changes. Once I though I understand those graphical graphs where branches go out of other branches and than after some commits are merged back. But then I learnt something more and I lost confidence in what I believed before.
yes agreed. very well said.
Why can't there be an equivalent of stash that keeps track of which parts were added and which weren't?

If switching branches wouldn't conflict with my current change, why do I have to stash/checkout/unstash instead of just doing it?

Why can't I pull without fetching?

Why will none of the 5 or so push configurations just do "push the current branch to the branch of the same name on the remote"?

Why is there no way to stop git from setting master as the upstream every time I do git checkout -b myfeature origin/master?

Why do I have to detach from a branch before deleting it?

None of this stuff is inherent to the problem or due to being a precise model of things; quite the opposite.

> Why can't there be an equivalent of stash that keeps track of which parts were added and which weren't?

What do you mean by this? It sounds like how stash already works.

> If switching branches wouldn't conflict with my current change, why do I have to stash/checkout/unstash instead of just doing it?

This is how git has worked for years: you can checkout a non-conflicting branch without stashing.

> Why can't I pull without fetching?

Have you customized Git to not support this?

> Why do I have to detach from a branch before deleting it?

When does it make sense to do this? I can understand deleting a remote branch (which doesn’t require this) but deleting the current local branch doesn’t seem to make sense in any normal workflow.

> What do you mean by this? It sounds like how stash already works.

I want to switch branches when I have some added (staged) changes and some unstaged changes, and keep the same set of staged and unstaged changes afterwards.

> This is how git has worked for years: you can checkout a non-conflicting branch without stashing.

Only if none of the changes are to the same file, even if they don't conflict.

> Have you customized Git to not support this?

If I do "git pull" it does a fetch and then something else. I'd like to do just the part that's not a fetch (because I fetched the same remote recently).

> When does it make sense to do this? I can understand deleting a remote branch (which doesn’t require this) but deleting the current local branch doesn’t seem to make sense in any normal workflow.

When I've finished working on something and aren't going to work on that repo again for a bit, I'd like to delete the feature branch that I just merged remotely, but I don't want to check out anything else in particular. So I usually end up doing a git checkout --detach just so that I can delete the branch, which feels cumbersome.

> If I do "git pull" it does a fetch and then something else. I'd like to do just the part that's not a fetch (because I fetched the same remote recently).

Pull = fetch remote branches + merge remotes -> local tracking branches

If you want to do the second part without the first, the git merge command will do it.

From the first line in the man page for git-pull:

"Incorporates changes from a remote repository into the current branch. In its default mode, git pull is shorthand for git fetch followed by git merge FETCH_HEAD."

But FETCH_HEAD only exists because of the fetch command. Git knows what the upstream branch for this branch is. It should know what the remote-tracking branch for that branch is. So why isn't there a command to merge that branch in?

Git remote-tracking branches are just a cache except when they're not. A better model would be for every command that can interact with remote refs to fetch first by default (like pull does) but take an option to "work offline" and use the remote-tracking version (which would then be a proper cache). Or vice versa, for every command to not fetch unless given a parameter that tells it to. It's ridiculous to have to guess which commands will fetch or not.

1. This isn't currently possible. It would require git to track the staging area for each commmit and branch.

2. See 1.

3. `git pull` by definition conducts a fetch because it Incorporates changes from a remote repository into the current branch.

4. Use `git config push.default current`.

5. Use `git branch --no-track new existing`.

6. I assume this is something to do with the reflog.

> Why can't there be an equivalent of stash that keeps track of which parts were added and which weren't?

But git stash does keep track of what it added?

> If switching branches wouldn't conflict with my current change, why do I have to stash/checkout/unstash instead of just doing it?

If your current changes apply to files which haven't changed between said branches, you don't need to stash your changes when switching between them.

> Why can't I pull without fetching?

The command for that is `git merge`.

> Why will none of the 5 or so push configurations just do "push the current branch to the branch of the same name on the remote"?

The command for that is `git push origin HEAD`.

> Why is there no way to stop git from setting master as the upstream every time I do git checkout -b myfeature origin/master?

The option for that is `--no-track`.

> Why do I have to detach from a branch before deleting it?

Because the `git branch` command never changes the working tree, which in this case uses the branch name to identify its location. If the branch were to be deleted without first detaching (or switching to a different branch), stuff would break.

> But git stash does keep track of what it added?

Added as in staged

> If your current changes apply to files which haven't changed between said branches, you don't need to stash your changes when switching between them.

Yeah, I know. So why do I have to stash when I've changed an unrelated part of the same file?

> The command for that is `git merge`.

But that doesn't know which branch is upstream, I have to tell it explicitly each time.

> The command for that is `git push origin HEAD`.

I want "git push" to just do that.

> The option for that is `--no-track`.

Yeah, I know, but I wish I could just turn it off for when I forget, or when I'm doing it from an IDE or similar.

Earlier this year, I wrote a blog titled 'A simple Git workflow' https://www.iwriteiam.nl/D2009.html#30 and now that I am rereading it, it does not feel simple at all for a first time user. And note, this simple workflow does not even use branches. It was only recently that I found the two global settings that makes lives for first time users so much easier. Why not make them default?
"There is still a chance that between since the last git pull command someone has pushed a new commit. In that case a merge will occur in your history." If you want to prevent these merge commits (I do, I think they're really ugly), you can add git config --global pull.ff = only
I loved using Mercurial. It provides such a nice UX and it is very intuitive to use.

It's a shame that github was created and not MercurialHub and now we are stuck with Git.

Now even Atlassian abandoned Mercurial.

I think one of the reasons as to why that happened is that Git is a much better piece of software in pretty much every aspect.
expect stuff like ease of use, learning curve and more intuitive.
I disagree. Git definitely has a learning curve just like all tools do. But as an engineer, you should learn it accordingly.

And honestly, once you understand the concepts of git, you don't need to remember the commands, you need to search for it. Just like you search for all sorts of problems in whatever language you're writing in.