Edward Thomson

Advent Day 9: git lol

December 9, 2018  •  1:04 PM

This is day 9 of my Git Tips and Tricks Advent Calendar. If you want to see the whole list of tips as they're published, see the index.

There are two commands I run more than any other: first, git status which lets me know what I've been working on. Second, git log which lets me know what other people have been working on.

git log

But I don't actually use git log. Usually I run git lol. Now, if you've just said to yourself "what's git lol?" and gone and run it, apologies. There's actually no git lol command out of the box. I've made an alias for it. It stands for:

git log --one-line

Which is a handy flag that shows you the commit history, one on each line. It omits the extended commit description and just shows you the commit ID and title:

git log --oneline

(That git lol is sort of fun to type is also nice.)

And actually, I've extended the alias a bit over the years to also add the --graph flag, which will show me the graph on the left, helping me better understand the flow of commits into the project:

git log --oneline --graph

You can enable this by running:

git config --global alias.lol 'log --oneline --graph'

And of course you can add your own flags to customize the history behavior to what you want to see. Do you want to just see only the merge commits, so that you see the pull requests that got merged and not each individual commit inside of them? You can use the --first-parent flag to git log.

Ultimately, though, I'd encourage you to use aliases to make your git commands work best for you in your preferred workflow.

Advent Day 8: Git-LFS

December 8, 2018  •  1:04 PM

This is day 8 of my Git Tips and Tricks Advent Calendar. If you want to see the whole list of tips as they're published, see the index.

Distributed Version Control Systems like Git are revolutionary: instead of having to communicate with the server to rollback to a previous version, to view changes introduced in a particular version, or even make a commit, you can do it all locally. That's because when you clone a git repository, you get every version of every file that's ever been checked in. That's why it's called cloning a repository, you get a complete copy from the server.

This is a huge productivity gain for working with versions of source code and text files and … a terrible pain if you want to check in large files like images, movies or audio into your repository. That's because when you clone a repository, you'll get every copy of those large binaries.

Consider a PNG image that's seemingly not too big - maybe only 100 KB. That's not so big, until you have 100 revisions of that file: now you're pulling down an extra 10 MB on every clone to get that history.

Worse still, some hosting providers limit the storage space that your Git repository can use: GitHub, for example, doesn't let you check in files larger than 100 MB.

The solution to this is the Git Large File Storage extension.

When you use Git LFS, you can still have large files in your project, and you can still manage them with Git. But instead of adding large files directly to the repository, you'll add them to a separate Git LFS storage area. What's added to the Git repository is a "stub" file or a "pointer" file that describes where to find the actual binary in that Git LFS storage area.

version https://git-lfs.github.com/spec/v1
oid sha256:7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730
size 4

This is helpful because when you clone a repository, you'll get all the stub files and none of the binaries. When you check out a particular version with Git LFS, it will download the binaries from the server's Git LFS storage on-demand. So you'll only have to download the versions of the large files that you actually need, and not previous versions.

(Some of the old versions may be cached on your local disk so that you can move back and forth between branches without having to download the LFS files repeatedly.)

This is also good for the hosting providers: they can store your Git repository on a storage media that's optimized for high-I/O throughput, while putting your LFS data in blob storage that's optimized for large file reads.

Thankfully, this is all mostly transparent. Once you've installed Git LFS, you can work with files just like you normally do. And hosting providers like GitHub and Azure Repos will load your LFS data to show you your repository contents exactly as you'd expect.

The only caveat is that you need to set up Git LFS for large files before you add them to your repository. Since Git history is immutable, you'll still have the large files in history (unless you take the trouble to rewrite it). So make sure you set up Git LFS before you start adding lots of large files.

Git LFS isn't critical if you're just checking in one version of a large file that never changes (after all, you probably need that version to build or run your application), but if you're checking in multiple versions of images, videos or audio files, Git LFS is a lifesaver.

Advent Day 7: Git Merge

December 7, 2018  •  1:04 PM

This is day 7 of my Git Tips and Tricks Advent Calendar. If you want to see the whole list of tips as they're published, see the index.

The annual Git Merge conference is one of my favorites of the year. Git developers and users get together to hack, share tips, and plan the future. Over the past five Git Merge events, we've seen a few product announcements, several talks on how to scale Git, and many talks, about using Git.

Unfortunately, I can't make it this year, but you can. It's coming up January 31 and February 1 in Brussels and it's going to be great.

But you don't have to take my word for it, my friends at Praqma have written up trip reports from both Git Merge 2017 and Git Merge 2018.

And if you want to see what you've been missing over the past few years, check out the previous talks:

I hope you'll be able to make it in my place!

Advent Day 6: GitKraken

December 6, 2018  •  1:04 PM

This is day 6 of my Git Tips and Tricks Advent Calendar. If you want to see the whole list of tips as they're published, see the index.

The Git command line is a tricky thing. It's useful for all of the developers some of the time, and some of the developers all of the time. But for some people, it's not always the best thing to reach for.

Over the last few years, the Git GUI market has really grown. We've seen some of the first Git GUIs really mature, and we've also seen new GUI tools launch. There are a couple that I'm really fond of, and I'm excited about each of them.

One of my favorite Git GUI tools is GitKraken.

GitKraken

GitKraken is unique in that it's a truly cross-platform app; it's built in Electron so it runs on Windows, Mac and Linux, which is great for me, since I happen to build software that also runs on Windows, Mac and Linux. It also integrates nicely with GitHub and Azure Repos - and no surprise, I happen to also work in both of those places.

Needless to say, I'm a big fan.

You can get started for free, so unleash the Kraken!

Advent Day 5: Review Pull Requests Locally

December 5, 2018  •  1:04 PM

This is day 5 of my Git Tips and Tricks Advent Calendar. If you want to see the whole list of tips as they're published, see the index.

Reviewing pull requests is tough work: whether you're using GitHub or Azure Repos or another hosting provider, they all try their best to give you a powerful code review experience right in the browser. But no matter how good they are, for some changes you really need to get hands-on, to run the code, to step through it in a debugger to really grok it.

Thankfully, GitHub and Azure Repos both expose pull request branches so that you can just fetch them locally and work with them. Those branches are hidden from your git client by default, though, so you'll need to set up "fetch specs" in your configuration that include those branches on the remote.

There are a few ways you can do this: you could set up another fetch spec on your origin remote. In this case, you'll always download remote pull request branches locally whenever you run git fetch. But if you work on a busy project with a lot of contributors (and a lot of pull requests), this will get annoying fast, especially if you're on Windows where branch management is slow.

Instead, you can set up a new remote called "pr", so that you can fetch pull request branches only when you want. To create a new remote (with the same URL as your existing origin):

git remote add pr $(git config remote.origin.url)

Now you can change the fetch specs for this remote to include the pull request branches. The remote branch information differs slightly depending on your hosting provider.

GitHub:

git config remote.pr.fetch '+refs/pull/*/head:refs/remotes/pr/*'

Azure Repos:

git config remote.pr.fetch '+refs/pull/*/merge:refs/remotes/pr/*'

Now if you want to check out a pull request locally, you can fetch from the pr remote and check out a branch pr/nnnn (where nnnn is the pull request number.

For example, to check out pull request 1234:

git fetch pr
git checkout pr/1234

Bonus: if you do have a lot of pull request branches, you may not want to fetch them all. To fetch a single branch, you can use the remote's branch name. You can see that in the configuration we set earlier. Again, it differs depending on your hosting provider.

GitHub:

git fetch refs/pull/1234/head
git checkout pr/1234

Azure Repos:

git fetch refs/pull/1234/merge
git checkout pr/1234

Now you can build and debug the pull request locally and send feedback in the web portal.