The problem I've seen is that there's two groups of people that are generally involved in a conversation like this
1. The group of people that think git is powerful, but the CLI makes it difficult to do anything that is even slightly outside the box (which, for example, makes fixing a mistake difficult).
2. The group of people that think git is powerful, and the CLI is easy to use, and refuse to acknowledge that it's difficult for some people; rather, they blame the people for being wrong.
I've been using git for 10+ years and I fall into the second group. Every time I get into a situation the isn't the normal workflow, I have to google how to fix it. And I need to check and double check what I'm doing because, if I do it wrong, I need to reclone the entire repo to undo my mistake (and heaven forbid I'm trying to correct something on the origin). I get it, my git skills are not good enough... but by this point they _should_ be, just by using the tool. The fact that they aren't says something bad about the tool.
And that being said, the people in the second group will still say that git is fine, and it must be a problem with me. Admittedly, I'm not perfect, but neither am I incompetent. It shouldn't require a decade plus (and lots of dedicate study) of use to become proficient with a tool.
- There's no group I've seen of that say git isn't powerful
- The group that doesn't want to use a CLI at all doesn't generally participate in this conversation (about the CLI), because they'd rather see a visual tool build on top of it that. (I know a lot of people in this group; I'm not, but I respect where they're coming from)
I fall into the first and third groups outlined. I love Git, but if the project I’m working on is in VS Code, I just use that because it’s less friction than breaking into a CLI workflow. I also use VS Code to resolve more complex things because I find the Git CLI to be unintuitive.
3 The group of people that think that git is powerful, and that CLI is not the best but still learnable, and that acknowledge that for some inexplicable reasons some people cannot seem to learn git somehow.
I think the problem is that the scope simply grew. Back in my svn days, "merge branch" is something only senior engineer does for entire team and not every day; patches are exchanged by emailing entire files or .patch files; rebase is imposible; you "stash" with "cp file file.old"; and history rewrite is something that happens once or twice in your carrer.
And with git, you are basically expected to do all of that, every day, even if you a just starting.
To address only one sentence of your comment and offer a pointer for anyone who needs it: the git reflog can get one out of some uh-oh-reclone-time mistakes and it's pretty easy to use.
To be fair, the CLI is pretty easy to use, and if you get into a situation where you need to redo your entire repo, that's entirely on you. In the 16 years I've been using Git I have never had an issue that wasn't solved by carefully reading the documentation (something that is lost on developers, these days).
- it's made for multiple remote first (e.g: manual syncing is assumed by everything) despite the fact most projects have one
- it forces you to craft your commit index to commit instead of letting you commit all changes by default, and optionally craft things
- rebase exist, and is used a lot
- you have to chose between easy merge and a clean history
- it's hard to get a lock, a big file, a ticket or a todo list in sync in this repo. It's not made for that at all, and requires additional services or apps.
- you have to chose between easy merge and a clean history
I will note that at least with GitHub we’ve been using squash merges for a couples years on a pretty large project and it’s solved this for us.
The devs that want a clean history (like me the project lead). Bisecting is very easy, every commit references a Jira ticket ticket.
People that want to land multiple patches with multiple messages can make multiple pull requests. If you think the changeset is so distinct that I don’t want it to be one commit in a bisect, each changeset deserves its own review.
When I started with git coming from CVS then Subversion, it was hard.
As soon as I developed a mental model that pretty closely matched git's everything pretty much clicked. Can't say I've ever got dead-end stuck, though I've made plenty a mess with rebasing, submodules, etc. Now I make temp branches before major operations (or merely save its hash in cmdline comment history) so I don't have to dig through reflog. Another tip, don't use stashes (unless very briefly, e.g. git stash; git pull --rebase; git stash pop), you'll end up with too many of them and forget/lose them.
The other thing I use extensively is the Resolve Conflicts UI of JetBrains IDEs on a 43" monitor to pick/choose edit what the resolution should look like.
What? That doesn't even make any sense. Aside from the CLI I can think of almost half a dozen GUIs off the top of my head. All different interfaces for Git.
For people who want Git's data model but a better CLI, check out https://github.com/martinvonz/jj. It's a more Mercurial-like CLI but you can use it with existing Git repos. It also includes undo functionality, anonymous branches and other nice features.
yeah agreed. Whats interesting is that my 14 yr old son picked it up faster and better than me. I suspect something about having to unlearn previous behaviors...
> Git as a version control system is great, but it desperately needs an "apt style" revamp.
I'd say that this is one of the reasons for why many prefer to use either integrations with their IDE, or graphical tools like SourceTree, GitKraken or even something more basic like Git Cola.
Git actually has a page listing other GUI software: https://git-scm.com/downloads/guis it's nice to have many options, some might also like the workflow of TortoiseGit, especially if they've previously used TortoiseSVN
Personally, I also fall into this camp: and if I need to do something "fancy", then it's quite likely that I've diverged from the usual "happy path" too far and should rethink my approach (and if necessary, then just drop down to CLI after some googling). Of course, there are various camps in regards to all of this, but being able to stage/unstage individual code chunks/blocks and spread out/group changes that have already been done in files over multiple commits feels like a nice quality of life improvement. Plus, the diffs that something like the JetBrains IDEs show you, as well as the ability to look at the history for a particular selection is also nice.
Then again, there are also many who don't rebase their branches, or even don't select squashing merge commits in whatever UI they might use (e.g. using GitLab/GitHub for their code review functionality and other features), which some might dislike for any number of reasons. I guess that just shows that there are many different workflows and people flock to whatever they feel comfortable with (or whatever their org/team mandates).
As for the actual CLI, in general there are few programs out there that actually feel good and usable to me, one of which is the Docker CLI (for the most part). I actually compared its discoverability/usability to something like tar previously here: https://news.ycombinator.com/item?id=29339018
Something like Typer actually let's you create your own interfaces like that, though the new formatting is a bit curious: https://typer.tiangolo.com/
Edit: actually one bit of functionality from Git that I miss would be telling it to treat certain changes in the working copy as something that shouldn't show up as modified, but also not even show up as something that can be staged/committed. Maybe something like stash, but whilst keeping the modified files in the working copy.
For example, a local database instance that I have doesn't work with how the app wants to use it (suppose that I cannot fix this for any number of reasons) and therefore I need to change every instance of:
ORDER BY NLSSORT(some_column, 'NLS_SORT = custom_nls_value')
to:
ORDER BY NLSSORT(some_column, 'NLS_SORT = standard_nls_value')
across the codebase, which means that I might have 100+ changed local files.
I just need those changes locally so the local database would launch and keep working, but I don't want to have to look at all of these files as "changed" when deciding what to commit. Of course, at that point you might run into some hot water regarding what would happen if the files that contain this value would actually be altered.
> actually one bit of functionality from Git that I miss would be telling it to treat certain changes in the working copy as something that shouldn't show up as modified, but also not even show up as something that can be staged/committed.
My guess of how git would like you to solve this problem would be with a throwaway commit that you then delete with an interactive rebase.
It requires you to keep track of which commits you need to push or remove but it is doable (Actually due to a particular situation I do something very similar at my job)
Which lead into what I think is a critical problem with git: lack of visualization of data; in my opinion git is unusable without a GUI because sometimes you need to juggle a few branches and you need good interactive graphical representations of a lot of the git database.
One of the major drawbacks is that git has no way (AFAIK) to rebase multiple branches, so if above that throwaway commit you have multiple branches, tags, or merges then it is not immediate to rebase the whole tree.
It is unintuitive and crappy in places (anyone who claims otherwise is out of their mind).
No one, I repeat no one, wants to consider VCS operations as graph operations. We endure it because it gets the job done.
The fact that “mine” and “theirs” is reversed for merge and rebase doesn’t even make sense after the explanation is made. There are dozens of examples like this.
And the worst wart of all in my opinion is that it’s designed around posix, even “mostly” expecting to be run in a posix shell. I guess I can forgive that (seeing as it was created by a Linux person) but I’m not interested in running git-bash or similar on windows, meaning it’s a pretty degraded experience. Making aliases under windows cmd/PS is… interesting.
Git served us well but I hope it is soon displaced by something else. We can do better.
Same for me but “It’s fine I can always Google the solution” or “It’s fine I just use 5% of the functionality and that bit works well and I can remember it” isn’t really a stellar review of an UX either.
The UX isn’t really tested at all when just using the 10% of the product even if that’s enough to do 90% of the job. It’s tested on that last 10% of tasks when we need to bring out that last 90% of git.
I’m the unfortunate “git guy” of our team so my job is resolving people’s problems. Hooks and aliases oh non posix shells. Auth plug-in uses like windows/Mac auth store, problems with CI servers having made a checkout without LFS so borked their working copy etc. People creating branches differing only in case like /feature/Foo/2 and feature/foo/3 and all hell breaks lose when you have systems with mixed case sensitivity.
Now add some monorepo pain like GVFS, or submodules or shallow checkouts etc and the warts really start to show.
The problem is that outside of those five or six commands, Git gets really hard REALLY FAST.
Let's use a common scenario as an example. Let's say someone accidentally committed a password into your codebase six months ago and pushed to remote.
You can't delete just that commit because Git is a graph, so you have to modify the parent commit that contains the password _and every other commit after it_.
So you discover `git filter-branch` which runs a shell script against matching SHAs. You run `man git-filter-branch` or `git filter-branch --help` but discover that (a) it can use special environment variables, none of which are documented here, (b) you notice that there are different types of filters, i.e. `env-filter`, `index-filter`, `tree-filter`, all of which require intimate knowledge of how Git works to use it.
(I train junior engineers on Git often. Once you mention the "staging area" and "index", you'll usually lose them. I can't blame them...they just want to track their work!)
You then try to run a `git filter-branch` command with the `--index-filter` since this can work against individual SHAs. Immediately, you get this:
$: git filter-branch --index-filter ''
WARNING: git-filter-branch has a glut of gotchas generating mangled history
rewrites. Hit Ctrl-C before proceeding to abort, then use an
alternative filtering tool such as 'git filter-repo'
(https://github.com/newren/git-filter-repo/) instead. See the
filter-branch manual page for more details; to squelch this warning,
set FILTER_BRANCH_SQUELCH_WARNING=1.
And then it just _hangs._ Since you know that going through six months of history can take a while, you think that it's working in the background. Nope, it just hangs there, waiting for you to CTRL-C instead of exiting with a non-zero exit code like EVERY OTHER CLI IN EXISTENCE.
You go back into the `man` page to better understand this warning. Surprise surprise, `FILTER_BRANCH_SQUELCH_WARNING` isn't documented!
So you provide the environment variable (if you know how, which isn't a given for junior engineers) and it finally runs...except you have no idea whether commits were rewritten or not (it does tell you whether the commits were rewritten, but you kind-of have to understand Git to understand the message).
Now let's say you actually powered through and got it to run...but it caused you to lose work! (Remember, you have to `git push --force` or `git push --force-with-lease` to apply your changes, so this is stupid dangerous already, but it must be done.) To get it back, you then need to learn about `git reflog` and `git reset --hard`, but since `git filter-branch` runs against every commit that matched your pattern, you have to spend time scrolling back at the reflog to find the one you want to reset to.
`bfg` exists to make this "simpler," but (a) it's a Java application, and you need to install the JRE to make it work, and (b) IT DOESN'T COME WITH GIT.
Again, since this is a really common use-case with Git, it would be really nice if `git` had something more user-friendly, like:
and a convenient message after the deed is done, like:
85 commits rewritten; run "git reset --hard [SHA_BEFORE_THE_CHANGES]" to undo.
(Note: You must run `git push --force-with-lease to sync changes with your HTTPS-backed remote, "NAME_OF_REMOTE")
However, since Git is maintained primarily for Linux development (afaict), this would most likely have to come from a third-party Git CLI. (I can already feel the rage from Linus for a proposal like this.)
Funny enough, making things easier against the desires of protocol/system maintainers is how decentralized systems eventually centralize. I can see a world where everyone uses `gh` instead of `git` or has `git` aliased to `gh`, which means that a single company has de-facto control over the future of Git...
git rocket-filter[0] is a friendlier CLI alternative to filter-branch or BFG, although it's a dotnet app and requires the (cross-platform) dotnet runtime.
I've used it successfully to remove huge or sensitive files people pushed to the repo by mistake, it removed them across many branches and merge commits.
That said, I agree with all your points. Personally I almost never use the CLI, I use a GUI front-end (Tortoise-Git, which is windows only). I do use the CLI for occasional scripting or complex operations, but that's rare.
I also train junior devs on git in our company. In fact I just spent part of the last couple months preparing an internal Git course, after having written a non-trivial Git integration for my internal app, which was a painful process and took over 2 years, mostly not Git's fault though.
The Git course I've prepared teaches git using only GUI tools, I now consider the CLI to be an impediment for teaching Git.
> (I train junior engineers on Git often. Once you mention the "staging area" and "index", you'll usually lose them. I can't blame them...they just want to track their work!)
I'm with you there. In fact in the course I have a slide which says something like "most git courses teach you about the Index/staging area at this point. We won't teach you about that. It's not very important right now and it's confusing. If you use Tortoise Git, you simply check the checkboxes for files you want to commit, and don't check the ones you don't. That's all. Now we move on. If you want to know more about these things, see those other courses.".
I'm not saying Git isn't complex, but this is the same guy everyone was lauding a couple of weeks ago for saying C/C++ should be deprecated in favor of Rust.
TortoiseGit + IDE tooling, CLI only for edge cases not taken by the IDE, when the repo gets borked, rename it, git clone, copy the latest changes on the freshly cloned repo.
No need to care more than that, I never needed a PhD in SCM systems since the RCS days and ain't starting now.
After a decade of having to craft precisely my commits, manually syncing, choosing between easy merge and clean history, and using tons of additional tools to make git bearable, I'm finally tired enough to give a try to fossil.
The CLI interface is very good at enforcing you to be aware of the underlying model (local state and the repo’s history). This allows for the user to draw an accurate user-model in his understanding of the system.
I have been using Git for around 15 years, without a fuss. Maybe because I was lucky enough to have found a good tutorial.
Instead of hiding the abstractions behind a “friendlier” CLI, Git shows you its real power and that of VCSs in general, by having a lower-level API.
Not even the multiple GUIs built on top of Git, adventure themselves into hiding or dumbing down the abstractions that allow you to do quite complex things with the code and its history.
Before that for a short period I really wanted to get into darcs, the first DVCS I used. I was constantly confused about what commands to use to rectify the off-the-happy-path situations that you find yourself in every now and then. The UI might have been better than git's in a lot of ways but it was distinctly higher-level.
When I learned git and understood the underlying model I had far fewer problems. The commands of early git could have been designed better, but they were more transparent in what they did.
The thought haven't struck me before, but maybe one of the great things about git is that even the low-level/plumbing commands (cat-files/ls-tree/show-ref) have well written man pages.
While I can navigate the Git CLI really easily these days, I don't disagree with Mark. Outside of the big four ("git clone", "git rebase", "git commit", "git push"), you're almost certainly engaging in some serious black magic fuckery. Hell, even "git rebase" straddles the fuckery border, especially when you're doing fix-up commits between commits.
If Git makes Russinovich want to shoot his computer, then a revamp of the CLI is _definitely_ in order.
Won't be surprised if GitHub goes for it by extending their awesome `gh` tool.
We can do better with version control for sure. Git hands down, even for some experienced developers, causes consternation whenever you have to go off the beaten path. Committing, merging, rebasing (in the happy path) and a few others are not so bad. Everything else starts getting more difficult, especially because the mental model of git is not intuitive.
I don't personally run into problems, but I've sure seen many, many other people struggle learning and using the git cli.
Another fan here. I am a terminal user so Git is 100% CLI for me. Maybe this has helped me learn it to a level where I feel confident with it. I was the sole Git CLI user in my longest role and I tended to be the 'git fixer'. I agree it has sharp edges (like a lot of things, though) but I'm happy to be adept at something powerful and useful. It's a transferrable tool across pretty much all stacks so it doesn't feel like a pointless investment.
I think it's biggest problem is that it is not intuitive at all for people who use it for not a long of time. (and I'm saying it as someone using git for more then 10 years :))
Let's say hypothetically you were teaching git to a group of 30 high schoolers. 25 of them struggle to grasp beyond a few commands and 5 of them do ok with it. As king for a day, what would you do to simplify git so that as many of those 25 kids as possible could become proficient with version control? Or would you just push forward with the 5 kids and tell the other 25 to find a different path in life?
I would like to know what your specific issues with git have been. Certainly they must to be substantial and well documented to warrant expressing such an arrogant opinion.
I guess the problem is people diving in to daily use of git without first educating themselves about how it works. In fact git is elegant and wonderfully designed, which makes it easy to use. It’s hard not to descend into a bit of snarkiness and say it's less than astonishing to see this from a Microsoft guy.
Yes, Magit solves the two main issues I had with git and made me avoid it for a while. It provides:
1) A simple interface, with good discoverability (options and functions shown);
2) Good visualization and operations on the current state, with work tree and index, in a simple and intuitive way.
People often complain about the CLI interface, but for me (2) is also important. Having a compact, simple representation of what's changed in the work tree and index, and easy manipulation, is important to reduce the cognitive load. No need to keep track of this in your head, just look at the Magit status window.
Came here to praise Magit. Even if you don't know Emacs, Magit is worth learning (and not entirely "emacsey", has its own interaction paradigms). Even if you don't plan on sticking with Magit for longer, it will illuminate your path towards better understanding of Git itself.
I have been using Git since college and for a few years since I began my job, can't say I have had any problem that I couldn't find a solution for oneline. Plus, I use Github Desktop now, so I do not have to worry about the pesky commands as much as I would have earlier.
> any problem that I couldn't find a solution for oneline.
That could still be the pulling my hair situation he mentions. Having too Google or even being up a documentation is a failure for a tool like this.
When I argue that git is bad it’s “unintuitive” I mean. I have to RTFM after years of use. I does the job but it’s a shit UX. It’s like getting in your car and having to Google how to put it in reverse, for the 10th time, after driving it for 10years.
Yes, I see. I don't mind doing it, cause anyway I google the solution to a bunch of problems I face at work every other day. My tolerance for Googling solutions would is very high. But it might not be the same for him, I suppose. And it would definitely vary from person to person..
> I have been using Git since college and for a few years since I began my job, can't say I have had any problem that I couldn't find a solution for oneline
I agree with this, but I don't think that's strong enough evidence to conclude that git's interface isn't clunky. Being able to find solutions online is worse than being able to figure them out on my own, and being able to figure them out on my own is worse than just not having them. Obviously no software will ever be free from issues, and most can have some sort of issue that isn't able to be figured out without searching online, but I'm not convinced that git does a particularly good job about minimizing the potential for these types of issues. Overall, I've learned to use git effectively for my work, and I've often helped teammates when they run into a git issue they don't understand, but this is mostly due to the fact that I've run into issues enough before to know how to avoid some of the pitfalls.
Git is a big step up from older code versions management tools and there is nothing particularly bad or difficult about its interface so I don't get the hate.
I suppose that once you become the standard you become a target as Microsoft knows very well.
Git was designed for a fully distributed open source environment where there is no canonical head and no continuous access to a source repository. It makes sense for the way that linux is developed. It makes less sense for the way that most corporate development is done.
Yes, SVN is worse. That doesn't mean that git has flaws in its most common deployment.
I want to roll back an accidental commit of an extra file to the previous, uncommitted state. Or even simpler, undo a commit to restore the exact state just before it happened.
Which makes perfect sense once you know that you are not ”undoing a commit” inasmuch as you are resetting the most recent state of an index to the second most previous one.
Just make an alias for it if it bothers you, that’s what is generally recommended by unix beards for hard to remember but oft-used commands anyway.
Making my point for me - the usage is "undo a commit" or "undo a file accidentally added to a commit", what you mentioned are implementation details that are leaking up to the interface.
If I'm doing cp file newFile, I don't need to know anything about ext3, APFS or anything about hard drives to operate on files.
Or do you imagine it as a subcommand with further parameters to describe what to undo and how?
I think a term like undo is a mistake if you think of the git history like accounting. There is, or there should be, no such thing as undo the way an unsophisticated layperson imagines they want. Instead undos are just changes like any other changes.
You don't fix entry errors by actually editing history, you make a new entry that both reverses the error and explains why.
If that leads to having to think about some problems a bit non-intuitively, I'm pretty tempted to just say tough shit, it's worse to try to simplify something if simpler really only means wrong and incomplete.
Perhaps undo was just a bad example of a git failing. There certainly are commands that could be more scrutable without becoming incomplete or wrong. But I only see it as an unavoidable process of development. It's not possible for anything to spring forth fully baked, and so it's pointless and wrong to complain that it didn't happen. So the crappiness of the early versions (of whatever, in general, not git in particular) is not damning and nothing else can ever be any different. Then the next, almost as unavoidable, at least certainly natural and typical, is that the process of imporoving necessarily means changing, and that leads to both redundancy and inconsistency. 4 different ways to do something because there is the old way and the next way and the next way...
I see only that git could improve some things in only the way is unavoidable and applies to everything everywhere, and is not a special git failing but simply life, and that most of the perceived complexity of git comes straight from the underlying job we need it to do. It may not be logically possible to have a fundamentally simple tool to do this complex job, only a simple tool that only actually does a simple job, which isn't good enough.
The best I even consider to wish for is just improvement over time figuring out more consistent interfaces and improving the predictability so that you can be more confident in understanding "when I say X, what will actially happen?".
I get what you mean, but really, the command is rewinding the index backwards in time by one ”snapshot”, i.e. commit, which is not a snapshot in the meaning that it would contain the entire filesystem tree at time of commit.
> cp file newFile, I don’t need to know
Depends on what you intend to do with that file.
If you’re fine with the British Railways approach / eventual consistency and don’t need distributed file access, I suppose you don’t need to know.
This right there is the what gives me pause. Every time I need to do something out of the box, I need to start googling. Rather than there being an easy to remember command to do it, one that has a good name that indicates what it does; or, more specifically, what one uses it to accomplish. It's like naming a field "list" in code; I know it's a list... but name it so I know what is in it or what it's for.
And to add to the fun, there's multiple other answers in this thread on how to accomplish the same task.
I have gotten used to git, and it is fine, I do like gnupg signing on commits.
The only thing I miss is "$Id$" that CVS/RCS would update with the rev. I could then print out the rev so I could see what version of the object is on one of the many servers at work. I wish git has something similar.
Whenever I hear someone making a broad hyperbolic politic rant about a technology which is otherwise used successfully by hundreds of thousands of people, I like to ask - what specifically is the problem you're running into? Usually it reveals a lot more about the person than the technology.
this is nothing more than a shot across the bow. you can't build an argument for why everyone should move away from git, unless you can point back to a tweet from a few years ago that you can say "i've been saying this for years" about. what better way to get an entire industry to move to your product, than to acquire its main "hub" and then replace the underlying tech. customer adoption strategy at its finest. as they have sunset atom ... next they'll sunset vs code and make you use straight up vs ... and they'll sunset typescript ... because ... this is conceptually just c# nowdays.
I work at a megacorp. We asked to pay Git folks to support monorepo sparse checkouts. They refused. Lo and behold Microsoft enters the ring, hires a Git committer to do it, and now it has it. Instead, we forked Mercurial, and got rid of staging and branching. Straight-line development is the way to go for most monorepos. Feature branches create a big mess. You also need sparse file systems for large mono repos otherwise the storage and network requirements exceed what is reasonable.
In addition, it's imperative pushes default to running server-side sanity lints (with break-glass bypass) before accepting commits. This means either disallow pushes to production repos with a CI/CD stage + code review in-between or have some sort of proof-of-work hooks that accept local testing results.
GPG has the same problem: powerful but the UX is a hot mess.
I had a couple of colleagues complaining about Git, so I asked what was the problem. "Hard to use", "commands doesn't makes sense" was among the answers.
Two hours on a whiteboard explaining how Git works in a little more detail and now the complaints are gone.
The gist of my anecdote is; learn your tools properly, not only does it save you headache but also makes you more productive.
(It's a bit dated, but Pro Git by Strauss is an good book to get a better understanding of Git)
The link has a bad title.
The CTO's problem isn't Git. It's the design of the Git CLI commands.
Which, to be frank, I think is pretty reasonable.
Git as a version control system is great, but it desperately needs an "apt style" revamp.