I’m a GUI guy when it comes to using Git. I like to click over to a native app and immediately see useful things. Like a list of files that were changed in the repo I’m actively working on, on the branch I’m actively working on. This feels efficient and productive to me. I can quickly see lines of code (through those classic red/green visible difs) that have changed. Then stage a set of them and commit them in a few clicks. I’m not afraid of the command line, I just think a GUI does a better job of it.
I’ve just switched from using Tower for ages for this job, over to GitHub Desktop. This is a bit niche, I realize, but it’s been on my mind since I’m going through it, and I figure since Git is something pretty much all of us developers deal with, it might be of interest. These are far from the only two GUI git clients. There is Fork, GitKraken, Sourcetree, Sublime Merge, any many more, not to mention the Git features built into code editors themselves. But in this article, I’m just comparing Tower and GitHub Desktop because I’ve actually used both of them quite a bit so can speak from personal experience.
First the quick hits:
Tower | Github Desktop | |
---|---|---|
Platforms | Mac and Windows | Mac and Windows |
Price | $69+/year | Free |
Uhh — Does Git Stuff | ✅ | ✅ |
There isn’t that much head-to-head comparison stuff that is all that interesting. Since they basically do the same things, it’s more interesting to consider the experience of the tasks. And that price thing is obviously going to be a big deal to many.
The Things That Mattered to Me
This is absolutely not a major feature comparison. These are based on notes I took while getting used to switching between apps. They are things that are important specifically to me and my usage of the tool. I suspect the things you care about will be at least a little different.
Running Git Hooks
Have you used Git Hooks? They are a powerful concept that allow you to run code alongside git commands. A big use case is running things like formatters, linters, or tests before a commit is allowed to go in (a “pre-commit hook”). That way you stop developers from making simple obvious mistakes that other people might have to deal with.
My team used to use a tool called Husky to set these up, and now use one called Lefthook. You don’t need these, they are just helpful.
Tower can technically run these, but I find the experience very lacking. The output from failed hooks comes up in a tiny window that is a pain to scroll.
Worse, to have them run at all you have to manually edit the applications environment.plist
file, which doesn’t follow you from machine to machine and I have found quite flaky. To some degree it makes sense. As they say:
When you run Git from the command line, it runs in the environment as set up by your Shell. GUI OS X apps, however, have no knowledge about your shell – and the PATH environment can be changed in many different places. The actual environment they run in even varies depending on how the application has been started.
I just bought this reasoning for many years, until I had a particularly frustrating time where I couldn’t get my hooks to run and explored other Git clients.
Somehow, without any extra configuration or involvement at all, GitHub Desktop runs all my Git Hooks perfectly. So a big good job to GitHub Desktop here. I’d probably put up with a lot more stuff I didn’t like as long as this keeps working.
+1 GitHub Desktop
Although I do like the fact that Tower has a [ ] Skip Hooks checkbox you can use when committing — GitHub Desktop doesn’t have that.
Keeping Files Staged after Minor Changes
Speaking of Git Hooks and linting… one common situation for me is that a hook fails because of some linting problem. Like it’s linting a JavaScript file, and there is an unused import
statement at the top. Rather that ignore it, our linting throws an error and I can’t commit until I remove it. I like that, it keeps code clean.
In Tower, I have slightly awkward experience with this flow. I’ll leave to go fix the file, come back, and it will look like all my files are nicely staged as before. Then I’ll go to commit them, and after the commit I’ll see the now-changed file, meaning I need to make another commit to fix the mistake. Just a little annoyance. Or, I might come back to Tower and see that it has un-staged that file because of the changes. That sort of makes sense, but from an entirely UX perspective, I’m like I just changed one little minor thing, just leave the dang file staged.
Somehow on GitHub Desktop it just does what I want. If I pop out to make a super quick change to a file, when I come back, it has decided to leave the file staged. I imagine they have some kind of heuristic that makes the call there, as major changes seem to un-stage, but hey I like it.
+1 GitHub Desktop
Pull Request Perusual
Tower theoretically has a tab for Pull Requests (PRs) on repos, but straight up I’ve just never been able to get it to work. It always gives me this error, and it’s not unique to any one repo:
It hasn’t worked for me for so long I just had given up on the idea of looking at PRs there. In switching to GitHub Desktop, it has great PR integration. The UI for changing branches opens a dropdown where it shows you a list of branches as a tab and a list of PRs as another tab.
That’s wonderful to me. I don’t want to think about what the exact branch name is usually, I want to look at what the PR is called and just select it. Case in point: when someone opens a new PR and you get an email about it, that email doesn’t even contain the branch name. But you do get a big ol name of the PR right in the subject of the email — so my brain is primed to look for that.
I also get just enough metadata on the PRs that is useful: how old it is, who did it, whether the GitHub Actions are passing or not, and if it’s still a Draft or not.
+1 GitHub Desktop
GitHub Actions
We use GitHub actions for all sorts of stuff, notably testing and deployment. Similar to Git Hooks (except, ya know, in the cloud), some Actions prevent other actions. Like if a PR fails tests, it cannot be merged to the Main branch.
Tower has no idea about the status of GitHub Actions as far as I know, but it’s built into GitHub Desktop at least a little bit. I can see their status. And if a new PR has a failure during Actions, I’ll even get an alert, which is the kind of alert I like to get. It’s not amazing in that I can’t actually dig in and see the run or much detail at all, but at least it’s there.
+1 GitHub Desktop
Merging Branches
If I have a branch I’ve been working on a while, a common task is pulling from the main branch into it to make sure it stays up to date. I always thought the dance was a little awkward in Tower:
- Switch back to Main
- Pull
- Switch back to Branch
- Merge Main to Branch
- Push
You don’t have to switch to Main first, but if you don’t, when you go back to Main, it’s like you haven’t pulled it directly. Your branch has the latest changes from Main, but your local Main branch doesn’t yet. That would always trip me up.
I was hoping this would be better in GitHub Desktop, but I actually find it more cumbersome. Partially because the branch-changing UI is buried within a menu instead of a side-panel. You have to open the menu, switch back to Main, Pull, open the menu, switch to the other branch, go to the small button at the way bottom of the menu offering to choose a branch to merge, click that, use a new modal to find the Main branch, and then merge them and push.
I’m just surprised this action I’ve done ten billion times isn’t smoother.
Ultimately keeping the branches/PRs in a dropdown menu as GitHub Desktop has it vs. the side panel like Tower has it is worse. Plus, Tower has drag-and-drop merging in the side panel. You can pick up a branch and drag it onto another one to merge, which is satisfying, or drag a branch to the BRANCHES header to cut a new branch using the one you are dragging as a base.
+1 Tower
Undo
Tower has a feature where ⌘/Ctrl Z, the time-honored “undo” command, is honored in the app. Pretty much anything you do can be un-did with the command. It’s very smart and a great feature. GitHub Desktop cannot do that.
+1 Tower
Reset HEAD
There is this context menu option in Tower:
I find it tremendously useful. It’s when I do some commits and I then find out I was on the wrong branch, or I want to go back and commit them differently or move the changes to another new branch or something. GitHub Desktop doesn’t offer this and I miss it.
+1 Tower
What to do with changes?
You know when you switch branches but have un-committed files, Git need to know what to do. Should it stash them? Should it discard them? 95% of the time, what I want is for the files to “come with me” over to the new branch. GitHub Desktop annoys me in that the default is to “leave the changes”, which puts them in a stash. I find the stash a bit hard to find later, and it doesn’t name the stashes so it only has one and it’s easy to lose.
I wish there was a setting for defaulting to “bring my changes” as like I said that’s what I almost always want. Tower has a setting for “Always offer to stash changes” that is on by default and I find that behavior much nicer. I wish one of them would go even futher and just automatically do it without even asking me (stash them, change branches, and then automatically un-stash them, that is.)
+1 Tower
Conclusion
You’d think stuff like how they handle merge conflicts would be a big, but I find them both fine at this task. Not amazing, not horrible. Or things like integrations would tip the scale one way or another. True, GitHub Desktop does to GitHub integration the best, like built in buttons to hop over to the repo on GitHub.com, and in reverse, buttons to clone a repo in GitHub Desktop from GitHub.com, but it’s not that big of a deal. And GitHub Desktop doesn’t have to be only GitHub repos, it can do whatever.
There are lots of things that both apps just do really nicely. I love being able to click on individual lines and discard them before committing. Like if I leave in an extra console.log()
and just want to ditch that without having to go back to the editor to find it.
In the end, to me, mostly it’s just the UI and UX of how doing the major tasks I need to do. It’s a narrow edge toward GitHub Desktop for me right now. And the fact that it’s free, actively developed, and from the company that makes the Git hosting I use anyway… GitHub Desktop is my winner for now. But to be 100% honest, I’ll probably keep both of them installed as while I’m 90% switched to GitHub Desktop, I still have so much Tower muscle memory I still pop it open to do some tasks sometimes, and I’m kinda fine with that. I’ll be a harder decision when the time comes to pay for it again though, as Tower isn’t particularly cheap! It’s relatively indie software though and I do like supporting that.
I prefer CLI or VS Code default git management to save me flipping through apps which I don’t like.
I have the question about does any code management due for private local without up to cloud host?
Actually in my company team work the code and manage in secret private that do not publish update the code to the other person outside cloud.
I would love to know does tower about due for local ip to ip update team code just like github without cloud saving.