Chapter 5½ - Git. #
Git is a distributed version control system that tracks changes in any set of computer files, usually used for coordinating work among programmers collaboratively developing source code during software development.
So it’s a way of versioning my files? Why not just click save-as
and give it a new name?
You could. It’s just that git can do a lot more!
Namely, it’s really good at:
- Letting multiple people work together where real-time (Google Docs style) colaboration doesn’t work well.
- Allowing for changes to be reverted later
- Allowing for branches
If it helps, think of it like saving in a video game. You can save - or go back to a previous save -and have two different branches where you make a different decision in each. The only big point where this analogy breaks down is that you can merge two branches, resolving conflicts between them and that two different people can work on two different branches for them to be merged together.
Technically, Git isn’t the only version control system out there. There’s also Subversion, Mercurial, CVS, & Fossil to name a few. It’s just that git has a supermajority of the market share because it’s really damn good.
1. Letting multiple people work together #
Say you have a file with the single sentence Bob has a dog
in it. You want to change Bob’s name to Dave
and your friend wants to change the dog to a cat
So, you both make the changes to your versions of the file, each on your own computers.
You have Dave has a dog
, your friend has Bob has a cat
.
Now, you both go submit your changes. Naturally, one of you has to go first. Let’s assume you make it first, the file now says Dave has a dog
. Then, your friend goes to do their changes. Keep in mind, their version they were based on doesn’t have the name changed to Dave yet. Now, git is smart enough to realize that you only changed Dave’s name and your friend only changed the dog to a cat, so, it merges the two for you and you get Dave has a cat
Sometimes, the changes can’t be resolved so easily and you will have what’s called a merge conflict. These are fine, but does require some human intervention. In the above, if both of you had changed the persons name, the latter person would have to select which name to keep. Usually, each change is reviewed by multiple people working on the project, and if there’s a conflict the preson the conflict is with would help get it resolved - in this case, picking which name to actually use.
2. Allowing changes to be reverted later #
Say you’re working alone on the project and are working with two files
FILE A: The Rockwell Engineering Retroencabultor is neat.
FILE B: Usuage Guide: Don't.
and you make some changes
FILE A: The Aperture Science Retroencabultor is neat.
FILE B: Usuage Guide: Lick it.
and some more,
FILE A: The Aperture Science Retroencabultor is dangerous.
FILE B: Instructions: Lick it.
But you realize you realize the middle edit was in error. Git will let you revert one or both files, plucking just the changes you made in that single “commit” (basically a project snapshot). If we wanted to revert the changes just to File B in the second change, we could:
FILE A: The Aperture Science Retroencabultor is dangerous.
FILE B: Instructions: Don't.
Again, sometimes this will fail. If you’ve made changes where reverting like this is nonsensical or there’s just to many changes for it to understand what has actually changed, it won’t work. But, generally, it’ll do a decent job.
Even if it doesn’t work, it’ll let you pluck it out manually and ask you to fix all the changes after it to make sense based on removing that change - a bit tedious, but better than any alternative in complex situations.
3. Allowing for branches #
Motivating this outside of Git’s intended purpose (code) is a bit awkward, but branches generally serve two uses:
- Letting multiple people make a series of changes without constantly breaking eachother’s work
- Keeping a large project organized
1. should sort of make sense intuitively. If multiple people on a team are working on a series of complex changes, a change to one thing while someone works might temporarily break something else. It’s easier if you can take a snapshot, work off of that branch, and then submit those changes when they’re ready, not constantly keeping up with everyone else’s changes.
Sure, sometimes someone else’s changes will conflict with yours, but espically if you’re mostly adding entirely new files, it usually just works - no conflicts.
2. is roughly the same idea. Say you’re working on a program and you want to add a feature to do X. All of the changes to make X work should be self contained. When the feature is fully ready, then you merge the branch in as one big “add this feature” to the project merge. This is done because otherwise half-finished ideals will have code just hanging around.
With that context, I really recommend you go watch & read:
./missing-semester - Version ControlDone with that page? Cool, welcome back.
There are a few extra things I want to mention:
A lot of people conflate Git and GitHub
GIT is the protocol. GITHUB is a provider of git services. You can use git using GitHub’s platform, but you could also use Gitlab, Gitea, or about 10000 other hosting provides - or host your own git server.
Still, you may want to use GitHub. It’s nice to use and is often the only way a lot of people use git. It does add a fair amount of extra features on top of git too. So, for better or worse, you’ll probably want to know how to use it and those extra features too.
Setting up a GitHub account #
If you haven’t already, go though the usual steps to make an account on https://github.com.
One of the first things you should have to do when using GitHub is set up a secure method to send your changes to GitHub’s servers. For security reasons, you can’t just use a password (This is a good thing) and instead need to set up key based authentication.
I’m going to save the nitty-gritty about how public-private key based authentication works for the Security chapter, but for now what you need to know is having a key pair will let you securely access git (and ssh, when we get to that) services on various servers, so we need to get keys setup.
Assuming you’re running a somewhat recent release of Windows 10 or Windows 11, ssh
should be installed by default. SSH is something we’ll use later for it’s intended purpose, but right now we need to use something included along with it, called ssh-keygen
. If you open up a command prompt window, you should be able to run, well, exactly that- just type ssh-keygen
and press enter. It should prompt you for where to save it - leave it the default by pressing enter. Then, it’ll ask if you want to put a password on it, that’s up to you, it’s not strictly necessary. When done, that will make some new files for you in a folder at C:/Users/{YourUserName}/.ssh
(note, this isn’t in your documents, it’s literally in your user folder, one below documents) the two files you just made are id_rsa
and id_rsa.pub
, these are your private and public keys respectively.
It’ll also probably generate a pretty picture, something sorta like this:
As the names imply, you should keep your private key private, while you need to share your public key - in this case that means sharing it with GitHub. To do so, you can open id_rsa.pub
in a text editor (if you have office installed, it might try to open it with “Publisher” - don’t. Notepad or VSCode will work though)
You should see text that looks something like this:
+---[RSA 3072]----+ | ..oo| | o ++| | . + o .=| | + . E= ..*| | = S... +.| | o =o=o= . | | o ooX.=. | | + =.B +.o | | . +...= | +----[SHA256]-----+
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCXdDCxYNL58FFxfeDRuokZGfvmo1S7cTr7tXOjQ1oAFAF4cWNjcNsFWUVO5oHkY59yVcLM0OSe029rCIP8ecGsXQdDP9wi3sRgpWBfaEf0vTKQ8oAJN1ipw+J2e57gV+UOMIapoTPHSSp3pCyUVS9GnZHct5vorLOCdr6V6JCTMj0KzvrlF67FV8pX9/6kiRjAQuFdFkYzeXwebW2l2GSe7nF/WfkZWMK6KAYPltnWjN9sXXbv5SXyeU6UmrnmKFJAygUj24AK8eXT8wqxIJBsIMUtO1pplLM/XJUCYC8XGcAmjo+E4heWmj3PAHO3A7GltmZoBNzsYdAvYbqVWNpn [YourUserName]@[YourComputersName]
We need to copy that and upload it to GitHub. Just head on over to https://github.com/settings/keys and click New SSH Key and paste that text in, name it whatever you like.
When done, you should see something like this:
Now, you need to actually go install git to Windows. There are plenty of ways to do this, but since you’re in the command prompt anyway. You can use winget
, Microsoft’s package manager to grab it - just run winget install -e --id Git.Git
. If you’re on an older system without winget or just don’t want to use it, you can grab git for windows here.
By the way, winget
is pretty awesome and has a lot of packages. Everything from Chrome to VLC is available, and it’s a nice way to quickly set up a new computer.
Now we can set up your user in a .gitconfig
file, fortunately, you can do this directly from the same command prompt you’re at. Just run git config --global user.email "YourEmail@InQuotesHere"
followed by git config --global user.name "Your Username In Quotes Here"
. For simplicity, you might want to make sure the email and username both match the ones you use on GitHub, though (I think?) the username can be different without issue.
Mac OS X ssh
should be installed by default, as should almost any Linux distro, if it’s not, it’ll usually be in the openssh
package, so just install that with your package manager. SSH is something we’ll use later for it’s intended purpose, but right now we need to use something included along with it, called ssh-keygen
. If you open up a terminal, you should be able to run, well, exactly that- just type ssh-keygen
and press enter. It should prompt you for where to save it - leave it the default by pressing enter. Then, it’ll ask if you want to put a password on it, that’s up to you, it’s not strictly necessary. When done, that will make some new files for you in a folder at ~/.ssh
the two files you just made are id_rsa
and id_rsa.pub
, these are your private and public keys respectively.
It’ll also probably generate a pretty picture, something sorta like this:
As the names imply, you should keep your private key private, while you need to share your public key - in this case that means sharing it with GitHub. To do so, you can open id_rsa.pub
in a text editor, such as TextEdit on Mac or VSCode/Nano/Sublime/Whatever on Linux.
You should see text that looks something like this:
+---[RSA 3072]----+ | ..oo| | o ++| | . + o .=| | + . E= ..*| | = S... +.| | o =o=o= . | | o ooX.=. | | + =.B +.o | | . +...= | +----[SHA256]-----+
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCXdDCxYNL58FFxfeDRuokZGfvmo1S7cTr7tXOjQ1oAFAF4cWNjcNsFWUVO5oHkY59yVcLM0OSe029rCIP8ecGsXQdDP9wi3sRgpWBfaEf0vTKQ8oAJN1ipw+J2e57gV+UOMIapoTPHSSp3pCyUVS9GnZHct5vorLOCdr6V6JCTMj0KzvrlF67FV8pX9/6kiRjAQuFdFkYzeXwebW2l2GSe7nF/WfkZWMK6KAYPltnWjN9sXXbv5SXyeU6UmrnmKFJAygUj24AK8eXT8wqxIJBsIMUtO1pplLM/XJUCYC8XGcAmjo+E4heWmj3PAHO3A7GltmZoBNzsYdAvYbqVWNpn [YourUserName]@[YourComputersName]
We need to copy that and upload it to GitHub. Just head on over to https://github.com/settings/keys and click New SSH Key and paste that text in, name it whatever you like.
When done, you should see something like this:
Now we need Git. On Mac, git
is kinda installed by default. If you go to run it, you’ll get prompted to install “Command Line Developer Tools”. Do that.
On Linux, you probably already have git, but if not, it’s probably in your distro’s repositories as git
, so just install it as you normally would.
Now we can set up your user in a .gitconfig
file, fortunately, you can do this directly from the same command prompt you’re at. Just run git config --global user.email "YourEmail@InQuotesHere"
followed by git config --global user.name "Your Username In Quotes Here"
. For simplicity, you might want to make sure the email and username both match the ones you use on GitHub, though (I think?) the username can be different without issue.
You have successfully set up keys for your account!
Even more security… #
GitHub has a second layer of authentication that’s worth setting up too, which adds a sort of virtual signature to each change you push to GitHub as a confirmation to people that what they see was really written by you.
But I already had repos on GitHub, how do I make them use these keys?
There’s a good chance that when you made the repo and pulled it down to your computer you used the URL of the repo on GitHub, such as running git clone https://github.com/VegaDeftwing/OpGuidesHugoSrc
, while this does work, it sets GitHub to use the HTTP protocol for authentication, which isn’t what we want, instead we need to use the git protocol.
Like this, where the link is instead [email protected]:VegaDeftwing/OpGuidesHugoSrc.git
(so the command you need to run might be git clone [email protected]:VegaDeftwing/OpGuidesHugoSrc.git
) but the problem is you already cloned your repo, so what now? You don’t need to delete everything and restart, you just need to change the remote.
- Start by running
git remote -v
to see what the current URL is - Copy the
git
based URL from GitHub (or wherever you host your repo) - Run
git remote set-url origin [email protected]:UserName/repo.git
, using the URL you copied - run
git remote -v
again to confirm it changed over.
For example:
|
|
Note though, you probably don’t want to clone everything as git, especially if it’s someone eles’ repo you’re grabbing to build yourself, as sometimes it will try to authenticate with git and fail because you don’t have permissions to access the repo. This is an annoying edge case and usually doesn’t matter, but it can.
[TODO] adding GPG key to account for GitHub verified thing
[TODO] GitHub PR to OpGuides
Making A PR on GitHub #
-
Go to OpGuide’s GitHub Repo
-
Click “ Fork " in the top right
-
Clone your copy of the repo,
git clone [email protected]:YouUserName/OpGuidesHugoSrc.git
-
Go to this file (content→Engineering→Linux→git.md)
-
Add your name to the list below using a text editor.
-
Run
git add .
to stage your changes. (The.
character means all files) -
Then
git commit -m "added [yourname] to Cool People"
To put those staged files into a commit. -
Run
git push
to push your changes to your copy of the repo on GitHub -
Go back to the OpGuide’s GitHub Repo
-
You’ll see a banner at the top of the page that looks something like this:
[TODO]
Click [TODO]
-
You’ll be prompted with the checklist that’s in the pull_request_template.md file. Since you’re just adding your name, please check the first box “Everything I’m contributing…” and the first box on the Public Domain option.
-
Click [TODO]. Now the Pull Request has been summited but should be marked as “Open”. This means that I now need to either approve it or not. If it gets approved you’ll see “Merged” otherwise you’ll see “Closed”. This may take a few days. Once I’ve merged the change, it may not go live right away, as I still have to push it to the live version of the website.
-
Optionally, once the PR is done, you may want to delete your copy of the repo from your repositories.
Cool People that Have Submitted A PR To Edit This Page #
- [Your Name Here]
Actually learning to use Git correctly: #
learngitbranching.js.orgGit User Interfaces #
Graphical #
There are graphical user interfaces that can be used to make working with git dramatically easier. If you’re using GitHub, GitHub Desktop is a decent option.
You may want to dig through these if that doesn’t work well for you:
- https://extrawurst.itch.io/gitui
- https://aurees.com
- https://gitfiend.com
- http://cong.tools (Windows only)
- https://github.com/FredrikNoren/ungit
- https://gitextensions.github.io (Windows only)
- https://tortoisegit.org/download/ (Windows only)
Command Line Interface #
Some tools also exist to make the command line interface to git better.
Again, GitHub has their own tool, https://cli.github.com
But you may also want to check out Bit, an alternative git CLI (GitHub) and gut
The basic git
command really isn’t bad though. This Cheatsheet may help you if you want to learn it better.
A Note on GitHub and competition #
Many people will use a fleshed out, consistent timeline of git-commits as a high point in their resume. While having this is good, it’s also really easy to abuse and shouldn’t be used as some golden metric. See Stop using number of git commits as any metric (u/Sajjon on Reddit)
Still, I do understand taking pride in your work and have this auto-generating trophy thing on my profile:
So, while it’s okay to brag a bit, don’t think that someone not doing so - or using Git in a way that looks less flashy or consistent - means they’re a bad programmer. Some people have workflows that result in them intentionally pushing as few commits as possible. It’s quality, not sheer quantity, that matters.
Plus, you can totally cheat the graph. It’s really a BAD METRIC.
https://github.com/gelstudios/gitfiti
TODO: #
SSH keys article on the (Arch Wiki)
[TODO] .gitignores
[TODO] show git log --all --graph --decorate --oneline
and adding it to the gitconfig
[TODO] git diff
https://github.com/dandavison/delta
[TODO] Git on not-GitHub, DIY hosting
https://dhwthompson.com/2019/my-favourite-git-commit
[TODO] Files Git works with
https://blog.martinfenner.org/2014/08/25/using-microsoft-word-with-git/
[TODO] Not committing private info to Git
What will happen when you commit secrets to a public Git repo?
https://onlywei.github.io/explain-git-with-d3/
Weird Git #
Further Reading #
./missing-semester - Metaprogramming