When I started using Git back in 2012, I wasn’t new to source control systems. I used a database-backed source control system back in the 80’s and, at Microsoft, I used Visual Source Safe (VSS) and Team Foundation Server (TFS). I was a whiz at checking files in and out, examining and comparing versions, and restoring versions.
Still, when I started to use Git for the Azure “help drawer” docs, I was totally unprepared for the effect of changing branches on Git-managed files on disk.
Git Checkout — An Example
Here’s an example. I’m working in my fork (my online copy) of the PSScriptAnalyzer repository. I’ve created a clone, that is, a working directory or copy on disk, of the files in my fork.
To switch from my ‘development’ branch to my ‘AddHelpTest’ branch, I use the git checkout command. Despite the name, the git checkout command doesn’t check out any files — not in the traditional sense — but it checks out or switches branches.
git checkout AddHelpTest
When I do a ‘dir’ to list the subdirectories and files in the PSScriptAnalyzer directory, I can see the Pester test file that I added, Module.Help.Tests.ps1.
After some work on the files, I switch back to my development branch:
git checkout development
Now, when I do a ‘dir’, the Module.Help.Tests.ps1 file is gone. It’s not hidden or anything. It is just not there.
No fear! When you switch back to the AddHelpTest branch:
git checkout AddHelpTest
… the Module.Help.Tests.ps1 file is back.
Git Checkout replaces files on disk
When I first started using Git, I expected that creating a branch in a repository (or in a fork of a repository) would create a separate subdirectory in my files on disk.
Something like this:
C:\GitHub\CoolRepo C:\GitHub\CoolRepo\BranchA ... Branch A files ... C:\GitHub\CoolRepo\BranchB ... Branch B files ...
But, that’s not how it works.
Your files on disk represent only the files in the current or active branch — the branch that you have checked out. So, if you have different files in Branch A and Branch B, when you use ‘git checkout’ to switch from Branch A to Branch B, Git effectively deletes the Branch A files on disk and replaces them with Branch B files.
git checkout BranchA: C:\GitHub\CoolRepo ... Branch A files ... git checkout BranchB: C:\GitHub\CoolRepo ... Branch B files ...
When I first saw this behavior, I thought I had lost my work in BranchA, but it’s still out there in the big Git repo in the cloud.
And, when you check out the files in BranchA, Git removes the files on disk from Branch B and replaces them with the files from BranchA. Nothing is lost.
git checkout BranchA: C:\GitHub\CoolRepo ... Branch A files ...
In fact, changing branches is a local operation. All of the branches and their history are stored in files in the .git directory. You don’t need an internet connection to switch branches and see the effect in your local directory.
As explained in the excellent, professionally written Git tutorials by Atlassian (I highly recommend them!):
“Checking out a branch updates the files in the working directory to match the version stored in that branch, and it tells Git to record all new commits on that branch.”
That’s not what I expected, but it’s predictable, and I’ve never seen it fail.
By the way, to list branches, use the git branch command. To combine branches, use the git merge command. I’ll tackle that one in another post.