Things I just don't like about Git
cohost.org
cohost.org
There's no danger of me dropping Git, the best alternative I've seen is Fossil and (opinion me) I think Fossil makes more mistakes than Git does. But Git definitely still has flaws; a lot of this post rings true to me.
I do think that Git gets a lot better the more that you understand how it works. Not perfect, a lot of the flaws being pointed out here are core flaws with Git's internals and have nothing to do with the UI. But it does get significantly better; some of the failure modes are much easier to avoid if you've spent time digging into how Git works, and the whole thing starts to feel a lot more elegant the more that the abstractions are stripped away. But that's also kind of a flaw in itself: Git's user interface is much more complicated than the underlying program or concepts are, which is obviously not great.
The fossil developers (myself included) would be interested in hearing what those mistakes are. We're open to improvement so long as they don't break backwards compatibility (e.g. rewriting history, as is necessary for kernel-scale projects, is an unwavering absolute no-no in fossil).
We could go further, but yeah, this is basically the biggest problem. I know this is a fundamental attribute of Fossil and that's fine, but to me it makes Fossil unusable as a VC system for most serious projects. I don't think of VC as an immutable record, I think of it as a tool for organization and collaboration that also allows me to have documentation around repository history, and I don't think that immutable history helps with either documentation or collaboration.
Obviously some people disagree with me on that, but the really short answer is that I think the way Fossil defines version control is misguided, so it's unlikely I would ever make the switch over.
I think that proper version control should be immutable. If history is changeable, what's the point in having history at all? It ceases to be "history" and becomes just a fable or hagiography.
Mistakes happen, and it is important to be able to correct them, which Fossil does do. In many ways Fossil's mistake-correction logic is far better than Git's. If you make a check-in to the wrong branch, you can move it after the fact in Fossil. If you check-in with the wrong user-id, or a with a goofy check-in comment, you can edit those too. Was your system clock wonky when you did the commit, resulting in a bad timestamp on the check-in, that too can be fixed. I say "edit" - really you are not modifying the original check-in at all. The original check-in is immutable. But Fossil supports the ability to add correction records (tags) on top of check-ins. The original history is preserved and you can always drill down to find out exactly what happened. But for routine day-to-day usage, only the corrected values are shown on displays and reports. So it is like being able to change history, except that you are left with an audit trail.
This is how accounting and legal systems work. You never erase - you only add corrections.
It's not so much "the people who are designing Fossil are bad at designing it" as much as it is "I disagree with their starting premises and their goals for the thing they're building." If someone comes to me and asks why they would want to use Git over Fossil, the primary thing I would point at is:
> This is how accounting and legal systems work. You never erase - you only add corrections.
I just personally think that can be in many situations an unhelpful way to think about what a VC is at a fundamental level; I don't think a VC is inherently an accountability system or a legal system, and I think that having that rigidity can get in the way of certain workflows. Again, opinion me, I know you're quite happy with Fossil for SQLite, and that's great and I'm sure it works great. It's not like it's bad to have opinionated tools, I just think that it gets in the way of treating Fossil as something I would recommend as a general Git replacement for everyone.
It comes down to: is the ability to rewrite "history" (which is not even really history at all in Git, it's just a collection of ordered changes) a feature or a problem? Fossil thinks it's a problem, I think it's a feature. Fossil looks at repository history like a historical record, I look at repository "history" as purely an organizational tool for checkpointing/documentation.
The Devil's Advocate in me feels compelled to point out that git is (to the very best of my fallible knowledge) the _only_ SCM in history to permit rewriting of history. Certainly SVN, CVS, and their predecessors did not get it all wrong by not enabling editing of history?
Admittedly, rebase/squashing/etc. is _necessary_ for a Linux-kernel-scale project, but 99.99+% of software projects are, in terms of the number of contributors/contributions, so far removed from that scale as to not even register on that scale.
There are a lot of reasons I don't use SVN and CVS, but correct, their branch model is one of them. I do think that Git's restructuring of how commits and branches work and the flexibility around them is one of the reasons its better than older VC systems.
I'm not sure how strict those older VCs actually were, I'm less familiar with them than I am with Git/Fossil, but... yeah I have no problem saying that if they were doing fully immutable history they were wrong to do so (or maybe "wrong" isn't the best term to use, more that it would be an attribute that I think would make them less useful to a lot of developers).
> 99.99+% of software projects are, in terms of the number of contributors/contributions, so far removed from that scale as to not even register on that scale.
I would disagree with this, I think rebasing/squashing is just a really useful tool, even for smaller projects. It's sort of a difficult debate to have because it's mostly going to come down to opinion. What does necessary mean in a smaller project, VC itself is not strictly necessary for many smaller projects.
SQLite gets by fine with Fossil, the developer prefers having an immutable history. But I'm not sure what to say other than that I use rebasing a lot. Different projects have different development styles.
Without history rewriting, the rewriting simply takes place before committing instead of after.
Ideally there'd be some kind of "virtual commit" capable of (visually) bundling up a range of commits, with its own message and tags; maybe these could be nested so that you could have a hierarchical view of the timeline: initially you see "release X, release Y" but then you can expand any of those to "implemented feature A, B" which can be further expanded into the actual commits.
Many git users agree, including the kernel from memory. By that I mean there is often some git tree (maybe called "production", "main" or "master") were "fast roll forward" is the only style of commit accepted. Ie, on that tree, you can't change history. But when you're using git to built a commit to that tree, you are allowed (and in the kernel's case expected), to clean the history up, removing all your mistakes and experiments, so the people following the main branch don't have to wade through all that crap.
So the difference is git allows it to be a policy setting, whereas I take it Fossil forces it to be turtles all the way down.
If Fossil ever becomes as popular as git, people will create software that allows history rewriting in Fossil.
Another user in this thread linked to jj [0], an alternative git client that does some pretty weird things. For example, it replaces the working tree with a working commit and commits quite often. I like git and that seems weird to me, but I'm not offended, people can do what they want on their own computer and I have the tools to ensure repos under my control are not affected. That's all I can hope for, and I'm happy that jj makes git more usable for some people.
I might betray my ignorance here, but what tools are those?
If I host a git repo, then I can obviously ensure that any branches on the origin are never rewritten. But how can I ensure that people who submit pull requests have not rewritten their history?
That is all I meant. As you say, people can still rewrite their own history on their own computer before submitting it.
We could get philosophical about what "history" is. If I press backspace am I rewriting history? What granularity are we talking here? If I make change X by frequently committing and then squash, have I rewritten history? If I make the exact same change X with one big commit at the end (no squashing), have I not rewritten history? Whether or not I rewrote history the pull request at the end is the same. Or what if I'm using jj which amends a "working commit" hundreds of times, have I rewritten history?
Ultimately the division of changes into commits is a matter of authorship, a creative endeavor. I'd prefer to do this creative work with whatever tools I choose, but if you force me to never squash, I can still achieve the same creative output using other tools or by altering how I work. At no point were commits ever an actual history, they were always a presentation of the history the author chose to present.
(I've rambled on here, most of this isn't meant as a direct reply to you.)
On my team we use pre-commit[0] a lot. I guess I would define the history to be something like "has this commit ever been run through our pre-commit hooks?". If you rewrite history, you'll (usually) produce commits that have not been through pre-commit (and they've therefore dodged a lot of static checks that might catch code that wasn't working, at that point in time). That gives some manner of objectivity to the "history", although it does depend on each user having their pre-commit hooks activated in their local workspace.
Git's history can correspond to actual history in reality and that can be a useful way to add accountability to a project (although of course as you say, you have no control over history coming from someone else's computer). But Git's "history" doesn't have to correspond to actual history in reality, and very often that's not how I'm using it. So I don't think when I rebase I'm lying because I don't believe I'm making any claim at all about the physical reality of how the code was written. I'm organizing feature commits on a timeline.
To me it's a little odd to look at that and to say "you're trying to change history." No, I'm not, I'm not saying anything at all about history when I do a rebase. I am grouping code together into logical units and putting them on a timeline so that they make sense when read sequentially. That's all I'm doing. If I came to you and said "this rebase perfectly represents the development history", sure that would be a lie. But I'm not saying that, and I don't think it's inherently the job of a VC system to claim that. I think the most important job of a version control system is to... well... control versions, and immutably showcasing a record of how the project was built is a secondary concern.
:shrug: At least the way I use VCs, I guess other people's millage may vary.
It's legitimately one of the largest divergences between simplicity of concepts and complexity of UX/interface of any serious tool I've ever worked with in my career.
Again, it's huge service and absolutely a benefit - but also the amount of collective dev hours wasted on understanding git minutiae is way too high.
When I encountered git back in 2006, I was kinda surprised at the choices of git's commands & arguments, it didn't seem nearly as nice as SVN's command-line interface. But git did win out for being usable locally & the sheer speed.
I kinda hoped the command-line interface would get revamped w/ better command names & better argument structure, but that never happened I guess.
But he did throw the baby out with the bath water. They got the data structures wrong, the overall concept skew whiff (a commit is the code at a point in time; how you got there is just meta data), but the higher level interface wasn't bad. He could have done worse than to base the porcelain command names on svn.
git doesn't suck. It's the best possible version control system in the context where it was produced, i.e. the Linux Kernel, i.e. an ultra large bazaar style project with hundreds of developers gifted at getting the low level details right.
It was not however designed for the kind of projects I work on, more Cathedral style, a few people who know and trust each other, where learnability, usability, and just not getting in the way are important factors.
The SQLite people have a concurrent to git called fossil. I found their description of why they started and maintain the project incredibly interesting
To summarize, his (Richard Hipp's) definition of freedom is "being able to take care of yourself." That includes reducing third-party software dependencies to the absolute minimum (e.g. libssl is not something he wants to reimplement... though we have (very) idly tossed the idea around ;)).
I feel strongly that VCS's could have much better UX and reliability. I'm trying to design one myself instead of implementing it in a weekend. (Though I do understand the constraints Linus was under when he made Git.)
I'd love to hear more about what people hate about Git.
It's not implemented as a single portable library. This makes embedding or driving git from other programs—a thing I've wanted or needed to do several times in my career, so I'm pretty sure it's really common—suck a lot more than it needs to.
And
2) It’s not the official implementation, so using it is committing to debug and work around divergence between it and actual git, probably after production or otherwise in-use data have been messed up.
- Bazaar
- Mercurial (Hg)
Both had superior user experience compared to git, including command line and GUIs. They were not as fast, but no slow either if you came from Subversion world. They were not as flexible, but still very very flexible.
What caused Git to win was not rants of Linus Tolvards, but Github. Github gave Git a semi-understandable web user interface. Early days, Github itself had a lot of competition. Bitbucket (now Atlassian) was the same but for Mercurial. However, Github, as a good American startup, won over the world, popularising Git along the way.
(Also Stackoverflow helped a lot. There isn’t a day I won’t Google how to do basic things in Git.)
Thankfully, SourceHut does support Mercurial (and, IIRC, it also supports Fossil).
Highly subjective.
Both Mercurial and Bazaar were plagued a long time by muddled branching and collaboration story. In hg there were the anonymous branches, multiple repos, bookmarks, all worked in different ways and their interactions were confusing. Bazaar I didn't use much but remember not understanding at all its branching model then, and didn't bother finding out.
Git won because it got many things right from the start, and was better than the competition.
Unfortunately it's been long enough that I don't remember any details about why I found mercurial confusing.
Back in 2011 or 2012 i once had one of the libgit developers sitting at my workstation for a full hour trying un-hose my local checkout after i'd made the mistake of following git instructions from SO.
SO git advice: 0 of 5 stars. Cannot recommend.
Later on stuff like git-flow came along which also helped people have a process to migrate to (even if it's poorly suited for the development patterns software projects were already migrating to at the time).
- SourceForge had become questionable with its inclusion of its own malware in installers https://arstechnica.com/information-technology/2016/06/under...
- Google Code was untrusted, because they have a tendency to rug pull their products now and then
Github served a market need.
For others
- Bazaar was too Ubuntu specific (was in-house Ubuntu project originally)
- Bitbucket kind of survived as Atlassian
Google code was svn and git. Source forge was the same, but also had CVS.
I also tried Darcs, Bazaar & Mercurial back then. Those options were slooowww. Git largely won because it was blazing fast, and easy to understand. Probably having the cachet of Linus helped. I personally found transitioning from svn to git was a breeze.
I do have some quibbles about the structure of commands & arguments from an UX perspective with git, but ultimately it wasn't a dealbreaker.
My tool has full branches, and your master branch is considered a different branch than the default master of the origin remote.
And to handle them across branches, each branch will have its own weave file, rooted at a parent. (There will be some optimizations.)
In a very large project you can have a monorepo, and then everything is slow and you can't easily use and work on a subset of the code.
Or you can use submodules and then testing, refactoring and making commits all become a nightmare.
Binary files is another crap area of Git. LFS is useless. Lots of people have Stockholm syndrome and think that Git doesn't support large/binary files well because it's immoral rather than just because it's not something Linus ever needed.
I'm still a bit sad that most of the attempts at replacing Git focus on the poor conflict resolution story (which is poor but tolerable) rather than these more fundamental issues.
As a lone developer, I admit that this is what surprises me the most about the experience of other people.
But I'm going to solve it. Partial checkouts, fully-transactional cross-submodule commits, the works.
Really, these problems are easy with a good design. It's unfortunate that Linus didn't have time for design.
> Binary files is another crap area of Git. LFS is useless. Lots of people have Stockholm syndrome and think that Git doesn't support large/binary files well because it's immoral rather than just because it's not something Linus ever needed.
Yeah, I don't get this either.
I am implementing a general plugin system for creating format-aware operations. This will include source code and binary files.
> I'm still a bit sad that most of the attempts at replacing Git focus on the poor conflict resolution story (which is poor but tolerable) rather than these more fundamental issues.
I fully agree. I'm going to the doing UX studies, and that's my first priority.
I am going to handle conflict resolution better, though.
If this rejects actions and limits possibilities that Git provides, so be it.
However, I was going to make a browser UI from the start. I could implement a branch and file explorer in that UI, which would allow you to do the same thing.
Would that be good enough or not? I'd love to know because I want to build this tool for humans first.
I do think that Git is very well established, and it would probably take a major player, maybe Azure or AWS with a cloud-based IDE to change paradigms.
I just realized something: maybe I can make it so regular file explorers work.
I had intended to use something like Fossil's checkouts. I could formalize it; each branch the user wants could be a separate directory in the repo directory.
While I hate that, people seem to like it. I think I will do it.
Thank you for pointing me in the right direction.
I mean, it's called .mailmap, and it's a map of commit email to cannonical email instead of uuid to canonical email, but this basically exists: https://git-scm.com/docs/gitmailmap
> submodules? they're a file in the repo with a special type inside the trees, git knows when checking out that the file is special, and could run other commands. it then does not run those commands and the person using submodules begins crying.
For a while, at my company, we used a git submodule (err, I unfortunately used a git submodule... this was my fault) and it was tradition for every new engineer to have a bad deploy because git silently ignores the submodule not existing on disk. So they would deploy, the submodule would be missing, and boom.
It just was annoying that you can use a submodule but git will happily ignore it not existing. It just made the whole thing super janky.
If you have to bisect across commits that added or removed a submodule you might as well give up now.
It's now 6000 lines of bash.
(Ok, I'm a little proud of it. I'll open source it as soon as I rewrite it in Python.)
However, they overstepped and gave me a hard time when they learned I was managing my own local repo how I wanted. I'm relatively good with git and would clean up my pull requests to meet the standards before submitting them to the main repo, but they still hassled me over the naming of my local branches and doing local rebases, etc.
Realistically speaking, will that happen? Why not throw up the bash code as a separate repository from the python one anyways? As an example. Could throw it into archived mode right after or something perhaps.
https://github.com/enfabrica/enkit/blob/master/scripts/gee
One of the big issues you'll find is that some off the defaults are very specific to my company. I'll fix that in the rewrite.
There are friction points between how Git works and how GitHub wants to do them.
Rebase is a nice compromise between merge which makes reading history and hard and squash which loses intermediate commits (sometimes breaking rename detection). But of course you cannot include a reference to the PR anymore outside the GitHub UI or manually rewriting commits.
Similarly having the type of merge be treated as a last second choice instead of part of the reviewable flow increases "wrong button" incidents a lot.
Like, fine, you are just so much smarter than me. I have spent many hours going through tutorials and the documents, and I still run into problems from time to time on doing things that feel like they should be routine.
I can have a surface level understanding of most other tools without fear of breaking the world.
Could someone show what this command looks like or link to docs? Searching for it produces a lot of rebase Vs merge results.
Yep, it’s a learning curve, and as deeper understanding comes, in more ways you start bending this great tool (git).
There is an endless ocean of toolings, helpers etc of all kinds, for all levels.
I’m not saying git is the best. There is no the best tooling in general. Fossil is great, git is great, and some other VCS. Pros and cons are everywhere.
git is a battle tested software. Who argues?
I mean that's just not true.
https://docs.github.com/en/pull-requests/committing-changes-...
Sha1 is a hashing function. As a hashing function, it's fine. Why does your identifier need to be cryptographically secure?
I agree with the name and email issues, but laughed at the ideal that a URL is somehow more robust.
Who claims that git is a database?
I agree with the broad strokes, especially having as many conversations as I've had with frustrated people about why their repo is in an unhappy state.
There are many use cases where people are using the hash to guarantee no actor has inserted different code than they expect in a dependency, so the dependency is pinned to a hash. Not being secure, would be catastrophic for some use cases that people are currently using if widespread.
We could make a claim this is a misuse, but this is what people are doing.
The only other one I know of that can be used for large files is https://www.plasticscm.com/ .
[0]: https://www.fossil-scm.org/home/doc/trunk/www/index.wiki
It can be used with regular Git repos.
So far, I just deal with it, even though it chips away at my soul each time it comes up.
https://git-scm.com/docs/gitmailmap
>If the file .mailmap exists at the toplevel of the repository, or at the location pointed to by the mailmap.file or mailmap.blob configuration options (see git-config[1]), it is used to map author and committer names and email addresses to canonical real names and email addresses.
I think it was supposed to be where were we
This pretty much summarises my experience with git.
Rebase, merge, and submodules being good examples. Show what you are trying to do and it becomes a whole lot easier to understand. Who uses rebase often anyways ?
Poorly written also imo.
That said, I agree with most points. The main problem with Git is that it's not bad, it's good enough. Mercurial and Fossil are superior, but Git is good enough, so people won't switch.
But no reflogs and no rebase makes it harder to use branching locally, and branching in general in mercurial isn't as flexible as it is in git (ok, i get it, it is footgun, but an airsoft footgun imho).