Since the start of the year, I've been running weekly workshops with Paddy Morgan at work. These have been fun sessions to run. Some have been chats, some demos etc.
However, this week we ran a "Git 101" workshop. Weirdly, this was the most attended workshop we have run, with around 50 engineers joining throughout the hour session.
This post covers what we ran through.
Time allocation: 60 minutes
This workshop will be a high level overview of the basic git commands you will use daily. It's an entry level workshop, so if you're comfortable with git on the CLI, this probably isn't for you.
If we have time (intermediate)
- Configuration (Global and repo level)
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
There are different ways to achieve the same thing. Here are some cheat sheets:
Git is a distributed version control system, so doesn’t require a centralised server. You can clone from another machine on a network, GitHub, GitLab, or your own git server.
For this example, however, we will use GitHub.
git clone https://github.com/benmatselby/dotfiles.git
git clone gets the codebase from GitHub, in this instance, and keeps a copy on your machine. You have now “cloned” the repo.
How do you know where the original end point is?
git remote show
This will show you the
origin remote in the first instance.
git remote show origin
This gives you all the details of the
origin remote. What the URL is etc.
But, you can have many, many origins.
git remote add github https://github.com/benmatselby/dotfiles.git
git remote show
git remote show github
This adds another remote, called
github that points to the same endpoint, in this example (which is contrived).
Git is a distributed version control system. So you have the full repo locally, but changes are being made elsewhere. You need to
fetch those changes.
Benefits of this include being able to work "offline" and still commit code. You do not need an internet connection to commit code!
git fetch origin
This pulls the latest information from the
origin remote. This includes branches, tags etc.
git fetch github
Also fetches from the
So, we have cloned and fetched. Now we need to pull the code into your branch.
git pull origin main
This pulls the code from the
origin remote, and the
main branch. You can change both of these values to match your remote and your branch.
At this point, you are “up to date” with what is on the server, wherever that server is.
You have a clone, you have the code, now you want to change it.
git checkout -b workshop origin/main
git checkout is the command.
-b is the option to create a branch.
workshop is the name of the new branch.
origin/main is what I am branching from. It can be from any remote, or branch. You can even create a branch from a local branch:
git checkout -b workshop main
You're on your branch, you've made some changes, now you need to commit.
We have a few options here:
git add .
This can be risky, if you are not overly disciplined on file management, or working logically.
git add [file] [file]
This can be better as it allows you to pick the files to stage, ready for commit.
Both of these options have staged files ready to be committed.
How do you know what to commit?
git diffshows you what is not staged, that has changed.
git diff --cachedshows you what has been staged ready for commit.
git diffshows you the diff, without whitespace changes.
This shows you what is and is not staged, and what will be committed.
Again, a couple of options:
git commit -a
Again, this can be risky, if not overly disciplined as it will commit all changes you have made. This is the equivalent of
git add . mentioned above.
git commit -nVery naughty. The
-nmeans naughty, I promise. This essentially ignores any local hooks.
git commit -m "This is my commit message"
- Logically atomic commits
- Please be liberal in information in your commit history. It's the only thing that stays with us.
Committing code, does not make it available for everyone, since git is distributed. So, we need to push the changes
git push origin workshop
git push is the command.
origin is the location of the server we want to push to.
workshop is the branch we are pushing to.
So you now commit all day long, but at the end of the day, you want to make logically atomic commits. This means you need to learn rebasing.
I always think of rebasing as "replaying your work over the top of the latest code changes on the branch".
But you can also do much more with an "interactive rebase".
git rebase origin/main
git rebase -i origin/main
Interactive rebase provides you a menu of options, such as squashing, picking, editing, dropping.
git config --list will show you all your configuration items.
You can break that down
git config --list --local
git config --list --global
So to add config
git config --add user.email firstname.lastname@example.org
This sets configuration locally to the repo you are in, and overrides global configuration.
To unset configuration
git config --unset-all user.email
Or to add configuration globally
git config --global --add user.email email@example.com
You can also edit
~/.gitconfig for global configuration, and
.git/config for the local repo configuration.
Let's say you want to have version controlled git configuration, but you need different email addresses (e.g. one for work, one for home), you can set the following:
path = ~/.gitconfig.local
The contents of
name = Ben Selby
email = firstname.lastname@example.org
Logging is what it is, but here are some useful commands:
git log- Show the log.
git log --stat- Shows the log and the files changed.
git log --stat -p- Shows the log and the files changed, and the diff!
git log --graph- Shows the log and graphs how the commits came in.
git log --oneline --decorate- Shows the title of the commits, and curates tags/branches. This is why useful git commits are important.
git shortlog- Commits by engineer.
git shortlog -ns- Commit totals by engineer, in order.
Note that there are server and client side hooks. If you maintain your own git server, you can have both. If you use GitHub, you have "GitHub Actions" as the server hooks.
Normally, we deal with local hooks, which are stored in
masteris being moved away from. If you
git inita new repo now, git explains this. GitHub is also moving away from
masterin favour of
- This is a good thing.
git initcreates a new repo.
git show [commit]will show you the contents of the commit.
git ls-fileswill give you a list of files in git.
git reset --soft HEAD~1will undo the last commit from your local history.
git checkout origin/main -- README.mdwill checkout
README.mdby itself from the
git add -i [file]will allow you to selectively add changes within a given file, using a menu.