Sunday, 9 December 2018

GIT isn't perfect. (And other blasphemies.)

I was embarrassingly late in the game coming to GIT as a version control system. Time has since passed and I'm now happily using it. The days when we had to lock files before we worked on them are thankfully a distant memory.

My road was a little bumpy...

Orphan git.

It's a new dawn, it's a new day, it's new version control system and I'm ready to download a project from a GIT server.

The first step was to perform a clone of a project. "Clone? That's a strange word for it. Maybe this is just it's own way of saying Download." Whatever you call it, my "clone" was ready and I can get to work.

Later, I've done my work, tested it my dev-environment and I'm ready to check it in. Before I do that I need to check on any changes the others have done. Looking for a "Get Latest" option, I find "Pull", which seems to do the right thing. Those changes don't conflict with mine so I can continue.

How do I get my changes back to the server? There's a "push" option which sounds like it would be the opposite to pull, but that doesn't do anything. Finally, I find "Commit" and it shows me all my changes with space to write my comments. Success!

I've committed my changes to the master branch! Sounds final. The red icons next to the modified files have now turned green. There's no indication there's more to do, or at least none that's obvious to this beginner. My job is done so I can now switch my workstation off and disappear on vacation for a week.

Not quite. The thing called the "master" branch isn't the master branch. When I had the "clone" operation and thought the name was a bit odd, it turned out I had just made a complete copy of the code repository and it was now separate from the original. To finish the job, I needed to also perform a push, but after having done the commit.

And this is what annoys me about GIT - we profoundly disagree about what's important. As far as I'm concerned, my local hard disk is just a necessary staging point to the way to the central repository where release builds happen. You perform a commit and that has all the ceremony and pizzazz, but a push deals with the big picture.

Ask most GIT clients what's important an it will answer that its own local repository is the focus of operations. The remote server is basically an after-thought. "Huzzah! We've done a commit! Oh, you want to push too. Okay then. Don't forget to do the push again next time because I won't remind you if you forget!"

(I have, many times, ran completely pointless builds having committed but forgotten to push. The build server builds without my changes and I end up wondering why nothing I did made any difference.)

There is no shared server only ZUUL!

Before I proceed, I should probably clear a few things up. Discussing GIT architecture can be a bit tricky because if you talk about a shared server or clients-and-servers as separate things, someone will step in and insist those don't exist.

Okay. As my mathematics teacher once told me, "You can use what ever fruity language you like, as long as you define your terms."

A GIT server never produces its own content (except maybe for house-keeping), but instead receives commits pushed from one or more clients.
A GIT client produces commits (by the user) and pushes them to the server.


"I was very happy with SVN thank-you-very-much."

Enough negativity. What would my ideal client would look like? Maybe it already exists. In a nutshell, there would be no local repository. All operations would take place on the shared server with the client channelling my actions to that server.

  • When I commit, I'm committing to a branch on the server.
        (No more forgetting to push after commit.)
  • When I create a branch, I'm creating the branch on the server.
        (No more forgetting to pull before starting.)
  • When I switch branches, I'm switching to the latest current state of that branch on the server.
  • When I browse the history, I'm browsing the history on the server.
  • If there is anything stored locally, there's maybe a cache to save time but that's it.

As far as the server and the rest of the team are concerned, I'm still using traditional GIT. I work, I commit changes, I push them to a branch on the server. Just like everyone else. No-one has to change the way they work to accommodate what I'm doing.

How would it work?

Some clients already have a combined commit-and-push option. My ideal client would take that further into an atomic commit-and-push. The client would create the commit data internally and then attempt to push it to the server. If the push fails, (perhaps someone else has made a change or the server is down) then the error is reported to the user but the commit is rolled back. Once the user has resolved the problem, they may try to commit again.

Other actions would work in a similar way. Actions that would normally happen as actions upon the local branch, are instead applied to the remote branch using pushes and pulls where necessary. If there is a local "cloned" repository behind the scenes, it's just there as a convenient cache.

What if you are offline?

One of the selling points of GIT is that you can work offline, perhaps while travelling on an airplane. Sometimes the server itself is down and it just keeps on working.

If you do find yourself offline and you can't push your work, my ideal client would have a way to store an "offline commit". This would effectively be like how commits work in traditional clients. The difference is that the UI wouldn't hide that the commits are only offline. The changed files would have a different color and there would be a bright indicator somewhere, warning you that you've not really committed your work yet.

What if you send pull-requests or patches instead of pushing?

All of this would only work if you have push rights to the server. Some people don't work that way and instead can only clone-and-pull, but need other means to get their work into the shared repository. For those people, fair enough, the traditional client is probably best. The best of all would be one that could work in either way, depending on if the user has push rights or not.

I wouldn't be able to push updates to you directly.

When GIT people say that there's no such thing as a shared GIT server, they mean it. When you do a "push" action, you don't have to push to the origin server, you could push to one of your colleague's workstations instead.

People do that? That sounds like a project management nightmare!

SVN is still available if you prefer that way of working.

I'd still rather be working with GIT than the previous generation such as SVN. Merging changes was a nightmare and I'm happy those days are behind me. Distributed teams couldn't work well with SVN without a lot of administration.

All in all, I'm only really looking to replace one isolated part of the GIT system. If I switched to my ideal alternative client, the rest of the team wouldn't have to and could continue using traditional GIT happily.

Picture Credit:
100_2223 by "paolo". (CC)
Sir Walter Raleigh, by William Segar, 1598. (PD)
(Why yes, I am very clever. Thank you for noticing. I'm sure no-one else has thought of this exact joke.)

1 comment:

  1. Asking questions are in fact good thing if you are not understanding anything totally, but this article presents good understanding yet.

    ReplyDelete