Things I hate about Git (2012)
stevebennett.me
stevebennett.me
And some points about the article. Git is a framework actually, you need some workflow to use it in a team. So git requires a lot of discipline from all team members. You can't just "commit" as in subversion, you must understand what are you doing. So you can't directly compare git with something like subversion. And git ≠ github.
Some points are valid: bad and unclear documentation, no "included" workflows, bad command line UI. Author also didn't mention authorship issues, it's a real pain.
That said, the command line UI really is infuriating - checkout means 3 different things depending on what the argument is, it's never clear to me whether I should be using "origin master" or "origin/master," etc. I'm also not entirely sold on the usefulness of the index, but perhaps that's cause I'm still new to using git.
Further I'd argue the subversion "just commit" model is potentially toxic to the quality of the codebase and SCM logs. It makes the act of sharing code with others overly casual. Users therefore often don't become proficient in the proper use of SCMs in general. They write poor commit messages, or may not have a clear understanding of changes introduced by their commit (this goes double for IDE-integrated SCM plugins that I've generally found to have poor UI and lack good affordances for grokking what's happening at any point).
The stage -> commit -> push (often to feature branch) provides multiple checkpoints to find issues in your code before it makes it into master/trunk. While staging (especially if you're using a GUI) you have a chance to view the changes being staged. After committing and before pushing, if you find something else that you missed, you can quickly amend your commit without much harm done. The pull request mechanism added by Github provides an additional code review step for a final sanity check and also allows you to run tests on branches before allowing merges (contrasted with the common practice of allowing everyone trunk privileges in SVN, often with a post-commit code review). Rebasing is a an act of final resort for cleaning up your work before everyone else is burdened with the job of grokking and maintaining it for the remaining lifetime of the system.
EDIT: Some of these practices are possible to replicate in SVN (eg. do an svn diff and really review the changes before committing) but there's no chance of amending commits, private or features branches are less frequently adopted and rebasing is equivalent to FTL travel and immortality from an SVN viewpoint.
https://git-man-page-generator.lokaltog.net/
It describes advanced features like `git-govern-origin` and `git-organize-head` [0].
[0]. https://git-man-page-generator.lokaltog.net/#26463b871524ca4...
I mostly write ML code as a single author and there's a lot of experimenting going on, so often I sit at the end of the day and write a commit message along the lines of "dicking around" or "updated some files" and feel like I might as well just sync my stuff with Dropbox and not have to worry about all the GIT commands.
They're naturally recommending the GitLab Flow, but a good approach is to read through it and choose what might work for you. The important thing is to keep in mind that there are countless variables that will likely be different for each team -- team size, release schedule, build process, testing etc -- which mean that each team's flow will be somewhat specific.
And as for commit messages, I have developed a system which helps me write more meaningful messages with just a little bit of discipline: instead of summarising what I did, I try to figure how would I give instructions to someone to do the same. So I have things like "refactor MyBigFunction to individual methods" or "change SomeSetting to use float instead of int" or "implement NewClass".
There are so many ways in which Git has simply failed. It was basically an experimental piece of software designed for a hypothetical world which never really eventuated. Truly distributed version control (code shared between different servers) turned out to be a fringe use case, and the vast majority of all collaborative developed source code has a primary repository. So it has all these features built around the edge case, and a lack of features for the primary case (many users, with different levels of trust, contributing to one repo).
Gitless is pretty cool. http://gitless.com/
"I don't like it and here's a heap of examples which lead me to arrive at my preordained conclusion that it's completely broken": cool, you've found issues. If you can, fix them and share. If you can't or won't... well, there are other tools for doing version control and perhaps another might suit you better. If you have to work with people that use git, I'm sure there's some way you can generate patch sets and still get stuff done.
Fixing the implementation means changing code, improving APIs (e.g. local/remote branch delete).
Fixing the model means finding an everything different system. Yes, a graph-based VCS more complicated than a linear one. But it also matches realities of collaborative software development. And reality is complicated.
As you might guess, I'm sympathetic to criticisms of inconsistency or unnecessary effort, but I believe Git (and other DCVS) to have the completely correct idea about collaborative text versioning.
My problem is implementation.
Which DVCS implementation do you like the most?
And even then you don't want to create a joystick which pulls up when pushing forward.
git reset abc # unstage file `abc`
git reset xyz # switch to commit `xyz`
or: git checkout mybranch # switch to branch `mybranch`
git checkout myfile # remove any local changes to `myfile` since the last commit
---Maybe this would work great in a typed language where I might have `reset(File x)` and `reset(Commit x)` with different signatures... but for a CLI where everything is stringly-typed? Not so fun.
Also, god knows what happens here if there's a branch name with the same name as a file...
This article raises some valid points, though. One that resonates most with me is that git exposes its entire model. I really wish there was a git-lite that just had the few basic commands that junior developers can grok and not fuck up so I wouldn't have to waste my time explaining the same stuff for the umpteenth time.
Edit: Thanks to lyall for the links. He posted below. [1]: http://gitless.com/ [2]: https://people.csail.mit.edu/sperezde/oopsla16.pdf
I second this. Trying to go from SVN to git left me confused and frustrated, while I found it much easier to switch to hg. Once I had been using hg for a while, I found that I had absorbed enough of the difficult/confusing stuff that switching to git was relatively painless.
Blaming users for not understanding a bad interface is one of the classic mistakes.
It took me a while make the mental jump from svn style branches to git style and from no stage to having a stage but I'd never want to go back now that I understand them.
In my experience, once you get into more complicated commands like rebase, I had to read a lot of docs to get things to work in both systems, so I'd say hg is easier to get started with but they're on par overall in terms of complexity.
As a sidenote, I think the ability to `rebase -i` work branches and squash, edit, and drop changesets is a very useful feature, and it's made very easy in git. Mercurial can rebase branches, but it really doesn't like it...
Granted, I learned git first and had been using it for 6 years before using hg.
1. The UI is more consistent ie. the "update" command only does 1 thing updates your working directory to a specified state.
2. It doesn't have a pre-commit staging "index" like Git (or it at least doesn't expose it to the user. So workflow is a bit for straightforward ie. you don't need to constantly "add" files before you commit, it automatically does it for you.
Plus, while the UX of git is not intuitive, especially from SVN, if you want to bypass staging and just use it like SVN, you can "git commit -a". Like svn, if you have new, untracked files, you can "git add -A; git commit". This is also trivial to alias.
[1]: http://gitless.com/
To get a "fancy oneline log" output, add the following to your `~/.gitconfig`
[alias]
ll = log --graph --oneline --decorate --date=short --all --pretty=format:'%ad %h %Cgreen%an %Cred%d %Creset%s'
then run git ll
It's great when rebasing your way out of spaghetti-commitlog situations.I personally have this in my ~/.config/git/config:
[alias]
lg = log --graph --pretty=format:'%C(auto)%h%d %s %Cgreen(%ar) %C(bold blue)<%an>%Creset'I find Fossil way, way more friendly and useful for individual users and teams.
Why would you prefer SVN over git? I find git to be infinitely better than SVN. DVCS is a pretty good paradigm and the biggest (valid) complaint I have seen about git is that several of the commands such `git checkout` have multiple meanings which isn't a big enough deal to lose DVCS.
www.bitkeeper.org
This leads to the UX that was initially planned becoming unwieldy. I think most organizations default to no-merge, rebase-and-commit-only mode, with master acting as the central branch to push to.
Hence what git needs to improve it's UX to a newcomer is to help define a repository to be in a "no-merge", and then help translate user's following actions:
git init
<make changes>
git commitchanges
<this lists current changes, and tracked, untracked files, and asks which are to be commited, and makes the commit>
git push
<pushed changes to origin .. automatically rebases, and prompts the user for any conflicts>
git pull
<pulls changes, automatically rebases, and prompts for any conflicts>
I'm convinced the entire workflow related to merges, and non-centralized features are what cause UX confusion for a new user.
I could write a similar article about how FTP is so much easier to use than SVN and it would be equally silly.
That is not to say that Git isn't inconsistent and the docs are terrible, but there are good tutorials out there. If I were more helpful I'd have a link to one here but I'm on my phone.
The primary function of a version control system is to recover earlier versions of the software in rare error situations where it is hard to figure out what has gone wrong. Backup to something that worked and identify the change that caused the problem.
For most software developers, a version control system should appear very simple so they can focus on solving the end user or customer or their own problem.
check-in <file | folder> o if the file is new for the project, the VCS should ask do you want to add this to the project? o check-in <folder> checks everything in the folder (directory) all at once. If the folder is new: do you want to add this folder to the project?
checkout <file | folder | project> [ <version> ] o checkout <file> checks out the most recent version of the file <file>. o checkout <folder> checks out the most recent versions of the files in <folder> and its sub-folders o checkout <project> checks out the most recent version of the entire project. The project can just be the specification of the top level folder! o <version> is an easy, human readable/understandable specification of the earlier version, a file sequence number such as 1.43, a folder or module sequence number, or an overall project sequence number (all generated automatically by the VCS -- at least by default).
All sorts of pain and suffering is avoided by dividing the project into folders for different components and contributors and/or teams. These check-in/check-out their folder independently.
The VCS should be very simple and take care of everything, such as maintaining a sequential overall project number as well as file sequence numbers, automatically behind the scenes.For a single developer or a team in the same office or building or for that matter office park with a fast network, that is all you need. For remote collaboration -- such as China and USA -- then you might need one or two command to push/pull the code to remote repositories; this too should be simple!
KISS (Keep It Simple Stupid)
I mean, it already does everything under the sun, so there's a challenge for anyone up for it!
The fundamental promise of any version control system is this: “Once you put your precious source code in here, it’s safe. You can make any changes you like, and you can always get it back”. Git breaks this promise. Several ways a committer can irrevocably destroy the contents of a repository:
git add . / … / git push -f origin master
git push origin +master
git rebase -i <some commit that has already been
pushed and worked from> / git push
That should not be possible.Mandatory XKCD: [1]
Also, I suspect that many of the "hosted git" implementations out there prevent this from happening by default. I know that both of the ones I use in my day job (gitlab and bitbucket) do, but I'm not 100% certain it's a default as opposed to something our ops guys did. In any case, far from impossible. EDIT: see boaardwalk's post.
Also, svn won't protect you from `rm -rf /` on the server, while git will, which is pretty cool.
git config receive.denyNonFastForwards true
Should it be the default? Probably, but it's trivial to fix. Things I hate about Git (stevebennett.me)
31 points by rbanffy 2 hours ago
Could do with 2012 in the title: Posted by steveko on February 24, 2012It could use neural network for this for all I care. Anything but merging lines as if they contained completely meaningless string of characters.
Never felt the need or desire to try anything else.
It's not unlike a programmer who only knows GWBASIC saying they feel no need for recursion because they never wrote any code that relied on it, or named functions, because subroutines can do that. Or a C programmer who thinks class-based inheritance is superfluous syntactic sugar.
I don't mean it as an offense, mind you, but your lack of experience in DVCSs makes your opinion suspect. Spend a month actually working with Bzr or Mercurial and then, having been exposed to different solutions to the same problem, your opinions will be much richer.