An objective analysis of Git and why developing with it sucks.
- Git Sucks
Git Sucks when used with Eclipse and SVN is still King
Eclipse and SVN were an amazingly great combination. Git came along and screwed the whole beautiful romance up.
This is a rant I have been storing up for at least 10 years now. My friends are tired of hearing it so I have decided to
bug the world with it. I was always thinking my opinion of Git would get better as I had more experience with it but
it just seems that Git Sucks more every time I use it.
A little bit about me. I have been developing software continuously as a professional since 1996, so for 24 years. As an experienced developer I have used Shared drives, then CVS, then SVN, and then Git. I have a masters and bachelor's degree in engineering, so I don't think I'm too dim witted but that is up to you to decide.
CVS was pretty darn great when it came out. A huge improvement over trying to keep old copies of your code all over the place, and it was intuitive from the start. When you got deeper into it you had some really fine grained control that no versioning software has matched since. For example, with CVS you could pick two points along a branch and merge all of the changes in that range to another branch. CVS was all about diffs and file level versioning. However, when your project got huge CVS got slow. Your server could be grinding for quite some time when you created a new branch or tagged a bunch of files, so this was its weakness. However, CVS never sucked like Git.
Along came SVN. SVN was faster than CVS and required less space because it managed differences between files instead of keeping an entire copy of every file whenever it changed. Creating a new branch in SVN was instant because a new branch has no differences. It is basically a new label that says "I have not made any changes to this branch yet" but here I am. SVN also did something else very advanced, it took time into account and kept track of where differences came from in a special file called a merge-info file (it showed up as a little green triangle in eclipse). This tracking meant that if you merged a difference from your trunk to an already existing branch, than SVN knew that the difference came from the trunk and wouldn't bug you with it when you merged that entire branch back to the trunk. This is actually a very important functionality and very frequently useful. SVN was like CVS because it was about file versions. SVN did not suck like Git, and a developer wondered if this is as good as things could become, with the exception of AI that does merges for you.
Eclipse's integration with CVS and SVN was just short of amazing. I could work with 5 teams and 10 people on each team, 50 people in the same code base, and merge multiple files every day with possibly hundreds of conflicts and the UI was so great that I could still breeze through it. Color coded targeted comparisons were presented to the user doing the merging sequentially and you could merge all non-conflicting changes very easily. Conflicts were clearly displayed and the user could decide to choose one version of the code or the other or copy and paste a combination of the code into the merge target, without leaving the merge view. Complex merges were made as logically simple as possible. Once again it couldn't get better.
Then out of nowhere came Git. Git was created for the development of the Linux operating system, which was being crowd sourced all over the world. There are two important differences between Git and SVN. The first difference is that the developer downloads an entire copy of the branch they are working on locally on to their machine, but that isn't the copy they will be editing. The developer then creates a workspace out of the copy and has to relay any changes from their workspace copy, to the local copy, then to the central copy. SVN just used a developer's local copy and a central copy. The second difference is that Git tracks versions at the commit level instead of the file level, so the entire branch is effectively tagged each time a developer commits something and the file versions are more or less inseparable because of this. The short story is that these two differences are very unnecessary complications that cause a lot of issues. The long story is below.
Git's middle man repository copy is the Twilight Zone
Every developer I know that uses Git with an IDE tries to use it like SVN. Nobody wants to leave
a version halfway between their workspace and the central repository. Evidence of this fact is
apparent by all of the IDE's having buttons that allow the developer to commit (to the local)
and push (to the central) at the same time. This might have been useful when college students
were working on something for months and wanted to see their local code history during that
time before pushing it up to Norway for good old Nils to see, but it is exactly the opposite of
how development is done in every business I have worked in. When I am on a sprint team of
5 developers working on a two week sprint, we check our code in multiple times a day because
We are anxiously awaiting our co-workers changes.
The really bad thing is that this middle layer isn't just weird but the damn files disappear and get stuck there too, and its mostly because of the combination of this weird middle layer with the unwritten law that files can't be moved back and forth one at a time. In order not to get literally hung pushing or pulling stuff back and forth you have to always pull down everything from the central repository before sending your newer code back up. Oops, did you try to check something in before pulling down the latest first. Well, Git now hates you and will hold your files with a Kung Fu grip in the middle layer. The only way to get out of this hell is usually to copy your changes to somewhere else on your drive and hammer your local copy with the latest from the repository, then carefully copy your changes back in and check in. You better pray little piggy that someone else didn't check something in while you were doing this. It's a completely unnatural way to check code in, and checking in or pulling down your files piecemeal is actually very frequently desirable. I will go so far as to say that piecemeal updates are actually desirable the majority of the time.
Git merges suck
Gone is the wonderful merge-info file, and you will be lucky if you don't have to merge by cleaning up the wonderful "<<<<" mess that text merges make when they mash up your files. If you are using the web based pull requests and there are conflicts it will refuse to merge and will give you a bunch of command line instructions to rebase your files. The people that think merging in Git isn't that bad are people that don't work on big multi team projects like I have. They live in little academic happy path worlds where file conflicts rarely happen, and their Mommy still wipes their little chins.
Git's Development branch is not for Development
Just in case having this middle man repository wasn't bad enough, someone came up with Git Flow,
a prescription for branching projects in Git. Git flow advocates having a Development branch which
is simply a pseudo Master branch (Git's name for Trunk/Main) that all code has to be merged through
on its way to the Master. The idea is that developers create their feature branches off of Development
then merge back to Development and then to a release branch which is merged to Master after deployment.
So, nobody develops on development.
Why this extra layer?! As far as I can tell, layers are great according to Git fanatics so let's just add another. The only time I have seen this layer even remotely make sense is when a static analysis tool is pointed at it, because it makes it easier for someone maintaining Sonarqube and Jenkins so they don't have to point the tool at different places.
The Development branch actually has a big drawback besides just being an annoying extra step. Since developers are merging all their features there before a release, they now have to go in there and undo merges and pull code apart if the business decides they don't want some features combined in the next release, which is actually very common.
The true ideal branching pattern is called "candidate release", and it goes as follows, no diagram necessary. The Master looks like what is in production. New feature branches are created from the Master. When the developers are planning a release they create a candidate release branch from the Master and merge the features to that branch. Some extra QA is done on this branch and maybe some bug fixes and then it is released. After release it is merged to the Master and the cycle continues. If business decides during this process that they want fewer features in the next release you simply abandon the current candidate release branch and create a new one from Master and merge fewer features into it. Notice that there is no Development branch! Why do you need it? Point your static analysis at your feature branches during development, or your release branch, or your Master. The master static analysis will give you a history of analysis. Don't let the Devops people be so lazy!
Git CLI sucks
Did the Git people do a good job on their CLI commands? For me it doesn't even matter. CLI belongs in the 1970s,
and there is no way I have time for typing things out when I can just push a button in a well designed UI instead.
The last refuge of the Git fanatic is to start stating how I would enjoy using Git if I took time to learn the command
line interface. My response. "You will pry my GUI out of my cold dead hands you commie bastard (Charlton Heston Style)".
And there ends my rant.
On a brighter note. Github does support an SVN client to all of their repositories if you so desire. God Bless you People, finally some rational thinking!