Edward Thomson

Advent Day 4: 2FA and Git Credential Manager

December 4, 2018  •  1:04 PM

This is day 4 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.

You're using two-factor authentication (2FA), right? Right!? This simple change can increase your security - and the security of your source code - with very little effort. When you enable it, instead of logging in with just your username and password, you'll now also need to enter a 6 digit key from an app on your phone.

This means that if somebody gets your password - whether that's through a website breach, a sophisticated phishing attack, or a much less sophisticated look over your shoulder as you type - then 2FA can help protect you. Now if somebody gets your password, they still need to get your phone, too, to enter that 6 digit key.

Authenticator

2FA is so important that it's actually a requirement at most employers - at Microsoft, not only do I have to enable 2FA on my Microsoft account, but I even have to enable 2FA on third-party accounts like GitHub (before we bought them).

The problem, though, is that while 2FA works great in a website, tools like Git on the command-line don't have support for it. And the workaround is to create a "personal access token", a long, random string that you can use instead of your username and password (without needing 2FA). But being long and random means that it's hard to remember.

Thankfully, there's a tool called the Git Credential Manager. The Git Credential Manager plugs in as a git credential helper, and it will take care of all of the creation of personal access token for you. When you run git clone on the command line, git will launch the Git Credential Manager, which will open a dialog for you to authenticate, and provide your 2FA information, and then create that personal access token for you. That token will be stored in a secure vault in your operating system (like the Windows Credential Manager) so that the next time you run git to fetch or push, GCM can just use the PAT.

Git Credential Manager

Git Credential Manager supports GitHub, Bitbucket and Azure Repos, and there are varieties for both Windows and Mac and Linux systems. Even better, it comes included with Git for Windows so that it's simple to get started.

Git for Windows and Git Credential Manager

It's easy to get started with 2FA thanks to Git Credential Manager, so I'd encourage you enable it on your Git repository hosting provider - and, really, all your other websites while you're at it.

Advent Day 3: Oh Shit, Git!

December 3, 2018  •  1:04 PM

This is day 3 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.

Git is… weird. If you grew up with centralized version control systems, then moving to a distributed version control system is weird enough. But Git levels that up with concepts like the "detached HEAD state", commands like "merge-subtree" and error messages like "did you run git update-server-info on the server?"

So I'm very sympathetic to new users being frustrated by Git.

One of the things that I've always pointed new Git users to is "Oh Shit, Git!". Katie Sylor-Miller put together a great web page that describes how to get out of some of the problems that you have with Git. (Those "oh shit!" moments.) And she does it in plain English, in a way that's easy to follow.

Oh Shit, Git!

But recently, "Oh Shit, Git!" got even better: Julia Evans has gotten involved. You might know Julia from some of her clever zines that dive deep into some tech like networking or Linux debugging tools in - you guessed it - plain English.

So, obviously, this was a good match, and together, Katie and Julia have created the Oh Shit, Git! zine. It takes the content from the original "Oh Shit, Git!" site about how to get out of trouble when using Git and adds in some extra goodness about how Git works including hashing and object creation, the graph and branches.

I highly recommend it for people getting started with Git.

Advent Day 2: Fixup Commits and autosquash

December 2, 2018  •  1:04 PM

This is day 2 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.

When working on a development team, it's important to try to create a pull request that's easy for your peers to review. Some people like to look at the aggregate changes - the pull request itself. But some people like to look at each individual commit as a small piece of work to get a better understanding of the code.

That's how we work on the libgit2 project: one contributor in particular likes to review each commit to understand the motivation for each individual change. So I try to craft a series of commits that stand on their own and are each reviewable. To help me get there, I use a rebase-focused workflow: when I have a series of commits that make up a pull request, git rebase will help me reorder them - or even modify them or squash them together - into something that I think best communicates my intent.

There are two useful git commands in particular that help me.

First, when I'm working on a pull request and realize that one of my previous commits could have been improved, I can make a "fixup commit".

Let's say in some previous commit abcd111, I added some variable to a new file:

int a = 42;

And after I've made a few other changes, and committed them, I realize that seems pretty magical. Why 42? I don't like magic in my code, so I want to add a comment to explain it, or maybe even make it a constant. So I can edit that code:

/* This is the answer to life, the universe and everything. */
#define MAGIC_NUMBER 42

int a = MAGIC_NUMBER;

There, that's better. Now I can git add that change to my staging area like normal, but when I'm ready to commit it, I can mark it as a "fixup commit", specifying the original commit that I'm "fixing up":

git commit --fixup abcd111

When I do, git will give it a special commit message. But why is this useful? Well, when I'm ready to push my changes up to the server, then I can use rebase --autosquash to tidy up my commits. The --autosquash flag will look for these fixup commits and set up my rebase steps to actually squash them right in with the commits they're fixing.

It will look something like this:

pick abcd111 Add some code that starts at 42
fixup 41a8ffe fixup: Add some code that starts at 42
pick 3bd40de Update documentation to reflect changes
pick 9a74a45 Add another test for the magic number validation

Even if I made that fixup commit later in my series of commits, rebase has reordered it and made it a fixup on top of that last commit. If I just close my editor and let rebase do its thing, then I'll end up with only three commits: the fixed up first commit, the documentation commit, and then the test commit.

Now I can push my changes up to a branch on the server and open a pull request for review, and my collaborators will see a nice, tidy, easy to understand history.

Advent Day 1: gitattributes for Text Files

December 1, 2018  •  1:04 PM

This is day 1 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.

A friend of mine asked to have a quick chat about a git problem that he was having and I knew before he even asked what it was going to be about: line endings.

It's always about line endings.

He'd gotten advice to set core.autocrlf; I've said it before, but it's so important that I want to reiterate: this is always the wrong advice.

The problem with the core.autocrlf configuration option is that it's set on your local repository. This setting isn't checked in anywhere, so you have to rely on everybody who works in your repository to set it, and set it to the same value. If somebody sets core.autocrlf=true and someone else sets core.autocrlf=false then you'll constantly be battling each other, flipping the line endings back and forth from Unix to Windows style each time one of you edits the file.

Instead, you should set the text option in the .gitattributes file at the base of your repository. Don't have one? Create it now. I recommend:

* text=auto

This will turn on automatic text translation for the files in your repository (at least the ones that aren't binaries); when files are checked in to the repository, they'll be normalized to Unix-stye line endings (\n). When files are checked out to the working directory on a Windows machine, they'll be converted to the native Windows-style line endings (\r\n).

If you want to force a particular type of line endings - perhaps you have Makefiles or sh scripts on Windows and these need to have Unix-style line endings to be used. In that case, you can force the files to have Unix style LF endings on all platforms:

Makefile text eol=lf
*.sh text eol=lf

If you're old school and have been using version control systems before git, you might remember that this concept of having your version control system be opinionated about line endings is rather new. And you may not like it. You may also think it's inefficient to perform this translation (it is). Or you may just like Windows-style line endings.

These are all perfectly reasonable opinions, but you still need to enforce these opinions with your .gitattributes so that everybody in your repository has the same opinions. If you want to not perform line ending translation, set up your .gitattributes with:

* -text

This will disable all text translations on your text files.

Although git is somewhat opinionated about keeping files in the repository itself with Unix-style line endings, you can configure how this is saved in your working directory, or even disable this behavior altogether. But whatever you choose to do, please do enforce that behavior with a .gitattributes.

Git Tips and Tricks Advent Calendar

November 30, 2018  •  5:04 PM

This December I'll be publishing an advent calendar of Git top tips; a new tip or trick every day. I'll make sure to keep it a good mix of basic topics that useful for beginners (or just a good reminder) and a bit more complex topics to make sure that it's approachable for everyone.

I'll keep this page updated as I go; I hope you enjoy!