I was inspired to write this by a Cloudflare guide on how to use Hugo with Cloudflare Pages. The guide is generally just fine, but it explicitly assumes a “fundamental understanding” of Git without it being very clear what that means. They go on to provide example git commands that have an error, trying to push before the first commit. For a beginner with “fundamental understanding”, that sort of thing is pretty confusing.

Git is a powerful beast with a lot of possibilities, so much so that it can be very difficult for a newcomer to figure out where to get started. I’m going to ignore that entirely and explain what you absolutely have to know to use Git for solo projects, possibly with a few extra bits. If you want to collaborate with others there is a bunch of other stuff to learn, but once you are comfortable with what a Git repository looks like and how you can examine it you have a foundation to build on.

I’ve written this guide for Windows because that is in some ways the most awkward OS to set up. Most stuff should translate nicely to whatever platform you are on.

What is Git?

Git is a version control system (VCS). It keeps track of the history of changes you make to some files, usually source code of some sort, so you can always look at and retrieve that history. It also has mechanisms for replicating the whole history to/from Git services such as GitHub so you can easily back it up and share it with others. There’s a lot more to Git, but that’s the fundamentals.

When you’re working with a Git repository, you are working on a particular “branch”. Branches are a mechanism to let multiple developers work on things at the same time without tripping over each other. We’re not going to explore branches at all in this TODO.

Prerequisites and beforethings

As an example place to keep a remote repo, I’ve used GitHub. You can of course use GitLab or any other Git hosting solution with a few modifications.

  • Create a GitHub account
    • Enable two-factor authentication. This is not in any way required, but two-factor authentication is awesome.

Add SSH access to GitHub. This allows you to clone, push and pull between local code and GitHub without having to enter a username and password every time.

  • Create an SSH key
    ssh-keygen -t ed25519
    
    • Accept the default path
    • Add a passphrase to be secure or leave it blank to have an easy life
      • TODO set up ssh-agent service and run ssh-add if you have a passphrase
  • Get your public key and copy it to the clipboard
    type .ssh\id_ed25519.pub
    
    Note NOT id_ed25519 - make sure you have the .pub on the end. The key should look like ssh-ed25519 AAAsome-long-key you@yourpc.
  • In GitHub, go to Settings -> SSH and GPG keys
  • Click “New SSH key”, add a title and paste your public key
  • Install Git
    winget install git.git
    
    • Start a new PowerShell to make Git available

Getting started with Git

To work with Git by yourself you need to be able to do a few things:

  • Create a repository
  • Add, change and delete files
  • Commit changes
  • Publish changes

We’re just gonna talk through each of those steps and then try them.

Note: you can take most of these actions with integrations in editors, for example Visual Studio Code. That’s cool and works just as well, but I’d recommend trying with the command line first so you can get a feel for what’s going on.

Configure Git

In order for Git to be able to show who made changes, it needs to know your name and email address. You can configure those globally as follows:

git config --global user.email James [email protected]
git config --global user.name "James McDonald"

These details are saved in Git’s global configuration so they’ll apply to changes you make in any repository you work with on your PC.

Creating a repository

A Git repository is a directory where you keep the files you want to track. You can turn any directory into a fresh Git repo by running git init. You can copy a git repo with all its history from another source, such as GitHub, with git clone. We’re going to use the latter method to keep things as simple as possible.

  • In GitHub, create a new repository
    • You can call it learning-git or give it an awesome name instead. I’ll refer to it as learning-git.
    • You can make it Public or Private. Public repositories are visible to everyone in the world, whereas Private default to only being available to you with the option to add more contributors.
    • Add a README file. This is not essential, but it has a couple of advantages. It’s generally a good idea to have a README in GitHub projects, as the contents of that file are shown in GitHub on the repository’s page so you can write down notes on what’s in there. It’s also nice to see a file appear when you clone so you know it worked properly.
  • Clone your repository on your PC
    • In PowerShell, go to wherever you want to keep your project and clone it:
cd Documents
git clone [email protected]:<yourusername>/learning-git.git

Note: As shown below, you should be asked whether you want to continue connecting and shown the key fingerprint for github.com itself. It’s a good idea to check that key’s fingerprint against GitHub’s documentation. If it matches, you can say yes and the key will be saved so you don’t have to answer this question again.

The authenticity of host 'github.com (140.82.121.4)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?

You should have a shiny new folder called learning-git (or whatever you called it) containing a fresh README.md.

Status

The command that is your best friend when working with Git is git status. It gives you a summary of the changes that Git sees. Let’s try it on the fresh repo:

cd learning-git
git status

You will get output something like:

PS C:\Users\James McDonald\Documents\learning-git> git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

So the branch we are on right now is called “main”. That’s the default branch in Git most of the time, and the only one we’ll be using. Branches are a nifty way of being able to track multiple streams of development at the same time that we aren’t going to talk about at all in this tutorial, because they’re much more complicated than we need to know about now. We are on “main”, and there we shall stay. (You may seem some repos with this branch called “master”, which was the previous default branch name).

The second line is telling you that there are no new changes in the “main” branch on GitHub. The name “origin” is automatically given to the place you git clone from, so that it’s easy to push and pull future changes to there. This is telling you that your local “main” branch is up-to-date with the GitHub version of that branch. We’ll see examples of this changing in a bit.

The last line tells you that you haven’t yet said you want to commit any changes, and that Git can’t see any files that have changed.

Making changes

For a simple workflow, there are three stages to adding your changes to git:

  • Tell git what you intend to add or remove
  • Actually commit those changes
  • Push the changes to GitHub

The first is accomplished with the commands git add and git rm. We’ll look at git add for now. This tells git to put the file in its “staging area” ready to be committed. You can git add a bunch of different files and include all those changes in the same commit.

Once you’re happy that all the changes are as you want them, you can use git commit to store them. Once changes are committed, they can be pushed to GitHub and they will appear in Git’s log.

To replicate your local changes back to GitHub, you use git push. Once that’s done, cloning the repository in the future will include those new commits and their changes.

Adding files

Let’s try actually changing something to get a feel for this. Create a file in the learning-git directory called hello.txt. You can create it with Notepad or whatever editor you fancy. I used the contents “Hello there, General Kenobi”, but you do you.

Try git status again:

PS C:\Users\James McDonald\Documents\learning-git> git status
On branch main
Your branch is up to date with 'origin/main'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        hello.txt

nothing added to commit but untracked files present (use "git add" to track)

Now it sees there is a file that’s not currently being tracked by Git, and even points you at git add if you want to track it. Let’s do that.

PS C:\Users\James McDonald\Documents\learning-git> git add hello.txt
PS C:\Users\James McDonald\Documents\learning-git> git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   hello.txt

Now we’ve updated git’s “staging area” with our new hello.txt. As that’s the only change we want to make right now, we can commit.

Committing changes

PS C:\Users\James McDonald\Documents\learning-git> git commit -m "Add hello.txt in case of Jedi"
[main dc4c57c] Add hello.txt in case of Jedi
 1 file changed, 1 insertion(+)
 create mode 100644 hello.txt

The -m option contains the commit message, which should generally be a description of what change this commit makes. There’s a great article about this at https://cbea.ms/git-commit/ that future you will thank you for reading.

Note: If you omit the -m, you will get dumped into Vim to write a commit message. This terrifies many people, but can be escaped by typing :q<Enter>. Committing with nice messages in Windows is usually much easier via tools like Visual Studio Code unless you have your PowerShell set up nicely to open an editor you prefer.

Now you can push the changes back to GitHub.

Pushing changes

PS C:\Users\James McDonald\Documents\learning-git> git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 321 bytes | 160.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:James McDonaldmcdonald/learning-git.git
   d39641c..6e26f46  main -> main

Deleting and changing

If later we decide we don’t want a file, removing it is similar to adding it in the first place.