This, in a nutshell, sums up my feelings about git.
This, in a nutshell, sums up my feelings about git.
> git gets easier once you get the basic idea that branches are homeomorphic endofunctors mapping submanifolds of a Hilbert space.
Note: I use git frequently every day, not by choice, but simply because it is the defacto version tracking system. I have grown to like it, but I miss the more straightforward every day use of Mercurial (which is rarely supported by any services anymore).
Edit: ... and as a native English speaker, I can't help but feel bad for others who are expected to become familiar with these functions without familiarity with these colloquialisms.
But the command line user interface is one of the worst I've ever seen. The names are bad, discoverability is poor and which command line tool does what doesn't always make sense.
There are certainly cases where Git is the right tool, but it's vastly overapplied, used because it's popular, not because it's the best tool for every job. For smaller projects without a lot of randos offering PRs from the outside, Git's probably costing you more in its complexity than it's saving you by having that complexity at hand.
One of Fossil's selling points is that it's missing several important bits (i.e. all the tools for rewriting history)
The issue is that everyone is using the most complex tool, from solo developer, to 10 developer teams, to 1000 developer projects. You should use the simplest tool that gets the job done for your project[0]. That isn't git, but it's so easy to just pick the thing that "scales".
[0]: https://blog.codinghorror.com/the-principle-of-least-power/
It's sort of how a lot of shops decide they need to incorporate 'AI' into everything, or they need to use microservices and Kubernetes to solve their problem. Some of it is just resume driven development but a lot of it is just observing and following trends.
> Some of it is just resume driven development but a lot of it is just observing and following trends.
Couldn't agree more. That's exactly what I think happened with git.
The requirements of Linus and the kernel developers are completely different from the requirements of the vast majority of users of Git, who are using it in small teams in a centralized way.
I would argue that the only benefit that this decentralization gives is a local cache, which makes things nice and fast. Most users don't need to be able to create branches easily (code review tools already let you do that, effectively) and it's just given people enough rope to hang themselves (e.g. GitFlow).
IMO the worst aspect of this needless complexity is having to explain to people "you've got 1) the branch central repo, 2) your local copy of that branch, and 3) your local branch". It gets even more complicated when personal forks come into the picture, as there are just so many copies of things to manage or trip over.
Try explaining to a junior developer why "git fetch" takes two arguments ("origin" and "master") while "git rebase" takes just one: "origin/master".
The command line is shit, one example: `git checkout` can both switch to a new branch or restore a file.
EDIT: cherry picking is actually making a copy of the leaf and gluing it elsewhere. And fast forwarding isn’t really moving the leaf, it’s taking the leaf you call BRANCHNAME and now calling a leaf further up the branch BRANCHNAME.
Cherry pick on the other hand has a non-technical definition that closely approximates what it does in git: https://www.merriam-webster.com/dictionary/cherry-pick
I know/use clone, diff, add, commit, and pull/push.
That is all I ever do with Git, and it's pretty straightforward. I have found no need for the rest of it, and it confused me when I tried to look into it.
CVS and Visual Source Safe way back in the day.
I use it nowadays, but I think it's too limited to provide value like Perforce changelists does.
I'd like to have one changelist for random local dev changes, like setting debug flags or turning off optimizations. Stuff I have no plan on checking in.
Then I'd like to group my edits into maybe one to three possible future commits.
The staging area doesn't allow this, I need to keep doing "git add -p" and carefully sidestep all the debugging stuff, plus that I can only work on one commit at a time.
So could have been useful, but not so useful in it's current state IMO.
# At the point I realize I have two commits
git add -p
git commit -m 'first'
git commit -am 'second'
# Do some more editing
git add -p; git commit -m 'debug' # commit the debug stuff so that I don't have to keep skipping it
git add -p; git commit -m 'first'
git add -p; git commit -m 'second'
# After repeating the above a few times
git rebase -i origin/master
# Remove the debug commits, move the first/second/etc. commits together, squash the runs of first/second/etc. into one commit each, and then go back and write commit messages for each of themThis is that part of git that bugs me the most! It's totally hostile to the way I prefer to work: one screen session containing all the editors and shells per change that I am concurrently working on. Git simply cannot do it, unless I clone the entire repo for every change, which is not practical for large projects.
Note that you can have multiple working copies from one clone for a few years now. git worktree add <path> <branch>
I found darcs to be the most ergonomic, except for the fact that it was orders of magnitude too slow.
SVN was good in that it fixed most of the pain-points that CVS had.
git and hg are both great. I tried them both out at about the same time and found hg to be more intuitive, but it didn't take me long using git to be comfortable with it.
The UI of git is honestly quite terrible. Commands are often confusingly named and have seemingly disparate uses. However the underlying model of git is straightforward enough for me to reason about what operations should be possible.
Pretty much all VCSs require some such knowledge and reasoning; e.g.:
- The lack of atomic commits in CVS stems from the underlying RCS stack it is based on.
- SVNs brain-dead branching stems from the fact that there are no branches in SVN, just O(1) copies from one path to another.
> Git’s internal model is trivially simple: everything is stored as objects addressed by content. These objects can point to each other. Additionally names can be associated with objects and which object a name points to can be updated.
I'll do you one better: it's just some byte arrays on disk.
I think the OP has a section that gets at some of the complexity of git's model:
> The complexity of Git distracts attention from the software under development. A user of Git needs to keep all of the following in mind:
> a. The working directory
> b. The "index" or staging area
> c. The local head
> d. The local copy of the remote head
> e. The actual remote head
> Git has commands (and/or options on commands) for moving and comparing content between all of these locations.
Maybe they fixed that in the 20 years since i used it.. but that was a disaster.
Git set out to solve a different problem: adapt VCS to an agile, CI/CD world. It does this much better than those previous VCS generations, but its mental model does seem needlessly complex.
Which were "send patches to the maintainer", and a little bit of "work offline".
Linus fixed those as needed, and people who haven't those problems are using his solution a bit like painful fashionable shoes - they hurt but dagnabbit, that's what the fashion is ...
Main point being that comparing the complexity of Git and, say, SVN isn't apples to apples, as the former is suited to use cases that are inherently more complex.
In order to achieve that, I think you end up with some additional complexity like local vs remote and a complicated graph structure to accommodate people coming "on" and "off" line
Yeah, I guess I kind of consider that an agile tenet: in general, that people can work quickly and iteratively with limited interdependencies.
Said another way, it would be difficult for teams to work in an agile fashion--where the work itself is frequently distributed and happening in parallel--using most older VCS models.
That said, Mercurial and Fossil came out within a year of GIT so GIT at least outcompeted them early on.
Git, Mercurial, and Bazaar all came out within three weeks of each other (late March/early April 2005).
Once users figured out what they want to do with the graphs, they then need to figure out how to achieve that with git's cli. And I feel that is where many of the complaints about git's complexities comes from.
IMHO the best way to use git is through a GUI so that one only needs to figure out what they want to do with the commit graphs, leaving the second part of the puzzle to the GUI.
For example, why can't I do something like
git view filename -3 # shows file before last 3 changes _made_to_the_file_ (irrespective of how many commits)
git view filename $date # shows state of file at date
git revert filename $date | number # roll back a specific file to what it looked like at $date or file version
I have the feeling that the developers of git even understand this, but they needed to get git out the door and assumed the community would build the layer atop git to make it more user-friendly. Sadly, attempts to make git user-friendly have so far boiled down to GUIs rather than introducing new concepts. Certainly the current collection of shell scripts that exist as the ui for git definately have a hackish feel to them.Mercurial names are much more natural but it lost the war already.
I use git every day and don't complain when using it. But when a junior is learning git, you start seeing the oddities.
https://www.git-scm.com/book/en/v2/Git-Tools-Rerere
> Plus that it's quite hard to rewrite dates, names, or split commits into several.
Read the documentation for 'rebase' and 'cherry-pick' and 'add'.
> https://www.git-scm.com/book/en/v2/Git-Tools-Rerere
Thank you for this, looks like exactly what I need at the moment maintaining a dev branch alongside a bugfix deployed main branch and having to do lots of rebasing.
… of what, though? On GitHub, and on every other project I've worked on that used git, the natural unit is a set of changes (e.g. a GitHub PR, a patch). If you run `git show $SHA`, git will show you a set of changes. But that's a lie; that's not what git stores.
If you run `git log`, it'll give you a list of commits. If you run `git show` for each, it'll show you a bunch of changes. Many users expect (quite reasonably, before they've been bitten) that if you start from scratch and apply those changes in order, what you end up with will be the same as your current tree. Nope.
What "natural" does even mean? That's a vague philosophical argument. And even then, all versioning systems deal with versions, not changes. Changes are relative to different versions. This is true even for SVN. Changes are always relative, it doesn't make sense to track them as the based unit conceptually or even for performance. Different versions implies change, not the other way around.
> If you run `git show $SHA`, git will show you a set of changes. But that's a lie; that's not what git stores.
Each new version will bring a change. This is not a lie. Sure it could show the entire corresponding tree by flooding your console, or it could be more practical and merely show the diff from the previous parent(s). This is the kind of thing that people who do not bother to take the time (about one hour) are stuck with. Don't worry, it's not that hard.
> Many users expect (quite reasonably, before they've been bitten) that if you start from scratch and apply those changes in order, what you end up with will be the same as your current tree. Nope.
The author, the date and other data about the commit do matter. If you rebase your commits, which is effectively applying those changes in order, then very very likely you will not have the same snapshots of the filesystem. And even if the filesystem remain the same, the data about the commit will be changed. It seems that your expectations of what a CVS "truly stores" is naive and based on a lack of experience.
No, Darcs and Pijul (for which I have high hopes, though it's not ready for prime time) deal with changes.
> It seems that your expectations of what a CVS "truly stores" is naive and based on a lack of experience.
Thanks, but attempted insults notwithstanding, I know what CVS truly stores, and what SVN, RCS, SCCS, git, Mercurial, darcs, and pijul truly store. (I admit I don't know what Perforce or ClearCase truly store, or others I may have used too little to recall.) And before SCCS I knew what a stack of labelled backup tapes truly stored, though I wasn't _quite_ as proud as git of my fancy labels.
I didn't know about them. From what I read, Darcks is slow and Pijul doesn't really bring anything new to git and seems to "solve" the problem not being based on patches while not really doing better at what git already solved. At the end of the day, both can compare what was applied and what wasn't but the algorithms used around it are just more complicated no good reason, this means less tools and less community support.
Then, Darcs has never been slow for me, I've been using it for about 15 years, I can remember of one minor performance issue. It doesn't scale well to very large projects, but there are extremely few of them. Since concrete arguments are important when discussing with others, the main event which started Darcs' decline was its inability to handle conflicts in GHC (the Haskell compiler), which was at the time the open source project with the largest history (as measured in number of patches).
As for Pijul, I'm curious where you got your information from. I know Pijul's authors well, at least enough to know that they are well aware of the algorithms used in Git. Pijul does solve a number of problems:
- I know at least one very large-scale project where collaborators are well aware that 3-way merge can mess with their code in really bad ways, and complain about wasting tons of time with that. Unfortunately, I can't embarrass the project's authors by sharing their name, but I can say that it is a widely used piece of software with a really long history.
- Knowing that the code you review is the code you merge is the only thing you should care about if you care about your code at all. This is not what 3-way merge gives you, as the Pijul manual clearly explains (see "lack of associativity").
- Patch commutation is what Git tries to do all the time (rebase, merge, rerere…), except with bad hacks which fail in the more complex situations, which is where we need them the most.
Then, I don't think you actually understand what we mean by patches: for anyone who has looked into the topic, patches are obviously not equivalent to commits except in the most basic cases (where all tools "work", in your own terms).
A datastructure is defined only with respect to the operations you define on it, I'm sure you use other commands than checkout. For example, people who review snapshots rather than patches before a merge (or even a commit!) either have really small projects, or way too many man-hours to spend.
> if you take one or two hours to learn the documentation is actually intuitive
Git isn't "intuitive" at all for anything but the most basic operations (I agree it is easy for those, if you are willing to work with snapshots). For example, the existence of `git rerere` clearly shows that Git doesn't model conflicts at all. Then, merges are not unique, Git chooses one at random when there are more than one. Rebase is a horrible hack, "replaying" commits doesn't even always work.
Moreover, saying Git is easy isn't a very effective way to show off on HN: if you feel you have to defend Git so strongly, even though it wasn't actually attacked, and to the point of refusing to reply directly to any rational argument, it clearly shows you invested enough time in Git to feel you would lose something if you had to move to a better solution. So, sorry, but I don't think it was just "one or two hours" for you.