Git and GitHub
Git is a distributed version control system used for most software projects worldwide. Here at CUSF, we plan to use Git for CAD as well through Charon
GitHub is one of many providers of Git remotes, i.e. a centralized place to store Git repositories. It is used by CUSF, you can find our organisation on GitHub here
Installation
Linux
If you’re using Linux you probably know what you’re doing. If not, just… use your package manager…?
MacOS
Adapted from docs written by Weixuan Zhang
Typically on macOS the package manager to use is Homebrew, which you can install from a terminal with
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Then you can install packages via:
brew install git
If you encounter a permission error, be cautious when you copy and
paste solutions from StackOverflow. Make sure you don’t mistakenly give root
privileges to all files in /usr/local/
.
Windows
You may also be interested in downloading the Windows Terminal from the Microsoft Store for a slightly nicer experience.
via Git Bash
The simplest solution is to use Git Bash, which you can get from the official download page. The default options are fine. The main drawback is that Git bash does not give you access to the Git man pages (manuals).
via MSYS2
A more extensible solution is to use MSYS2, which gives you access to a native UNIX-like environment. You can then install Git (and the man pages, which is highly recommended) from an MSYS2 terminal via:
pacman -S git man-db man-pages-posix
via Windows Subsystem for Linux
This is not recommended right now, as it is not yet compatible with Charon
Usage
This is not comprehensive, only a quick reference for basic usage. Your first port of call if you want to know more should be the man pages (manuals), which are accessible via:
git clone https://github.com/username/project
If in doubt, type git status
into the terminal. It will give you
some informative output of what is currently going on.
UNIX-like terminals
BEWARE: files deleted on a terminal will not usually go to the recycle bin
Refer to these docs from the SRCF for a good intro to UNIX-like terminals (i.e. the kind of terminal you should be using Git from, see Installation. Some understanding of these terminals is required to use Git. There are graphical clients for Git, but usually they should be avoided, as they obscure what's going on (and won't work with Charon).
Repositories
Repositories are usually self contained projects. They correspond to a folder on your computer, and are usually synced to a remote (e.g. GitHub).
To 'clone' an existing repository, i.e. copy the latest version from GitHub:
git clone https://github.com/username/project
This will create a local directory project
containing the
repository.
If you want to create a repository to use with GitHub, it's probably easiest to click the plus button on the GitHub website in the top right and let it tell you what to do.
If you are creating a repository just locally, the following command will turn the current directory into a repository:
git init
Commits
To 'commit' is to make a record of your changes. Except in some special circumstances, commits will always exist in the history of the repository, so that changes in the project can be tracked and rolled back if necessary.
In order to make a commit, you first need to 'add' changes to Git, which means making Git aware of the changes. Having to do this can be useful if you only want to commit some of the changes that you have made.
Note that you can use git status
to see what changes have been
added
To add just the file file
:
git add file
To add all files in the current directory:
git add .
To commit the changes that have been added:
git commit -m "Commit message"
"Commit message" should be a short description of what you have changed. (Include the quotes)
Pushing and Pulling
In order to sync your local changes with the remote (e.g. GitHub), you must push and pull: pushing uploads your changes to the remote, and pulling gets the changes from the remote.
To pull:
git pull
To push:
git push
The first time that you push, Git does not know which branch on the remote to push to, so you instead need to use
git push --set-upstream origin master
you can substitute master
with any other branch
that you want to push to.
Branches
N.B: Would be nice to add a `git branch --oneline --graph` from something complex.
Branches are chains of commits. In a repository, any two branches will have a common ancestor, which makes them akin to the branches of a tree.
There is one branch which is the canonical state of the project, usually called 'master', although alternatives are often used. (In this page, 'master' is the name used)
Typically different people will add changes to different branches, and then they will be merged together. See Pull Requests
To create a new branch based on the current branch:
git checkout -b branch-name
To switch between branches:
Try to keep the working tree clean when doing this or it will get complicated. (i.e. don't have changes which aren't yet part of a commit)
git checkout branch-name
To push a branch:
git push origin branch-name
git checkout
can also be used to navigate between any commits in
the repository. There are many ways to specify a commit, but here are some
useful ones:
HEAD
|
the commit commit that is currently checked out |
foo~
|
the commit before foo, for example HEAD~ is the commit before the current one |
foo~N
|
the commit N commits before foo, for example other-branch~N is N commits behind
the latest commit on the "other-branch" branch |
Confusion regarding checkout, switch, and restore
A source of confusion is that the old git checkout
command has
been somewhat replaced in recent versions of Git (with backwards-compatibility)
by git switch
and git restore
. This page uses the
older git checkout
, but note that the newer commands are used in
some places too. If in doubt, have a look at the man pages for each command.
Pull Requests
Pull Requests are a request to include the changes that you have made to your branch in the master branch. They are specific to GitHub, alternatives have their own way of doing things (which is often very similar).
The easiest way to create a pull request is to go to github.com, navigate to the page for your repository, open the branch you want to merge, and click the icon to open a pull request.
Submodules
Submodules are Git repositories inside Git repositories. They can be useful for a few reasons:
- Reusing a project in multiple places
- Using someone else's project as a dependency
- Segmenting projects into subprojects.
When a submodule exists within a project, it's just a link to another repository. Cloning a repository which has submodules will not (by default) clone the project's submodules.
To initialise submodules (after cloning the repo):
git submodule update --init
To add a submodule (location
is optional, it will go to
repo-name
by default).
git submodule add https://github.com/IDP-L211/repo-name <location>
To update all submodules to the latest commit in their repository
git submodule update --remote
To completely remove a submodule (yes it is this annoying)
git submodule deinit repo-name
# now delete the relevant lines in .gitmodules
rm -rf .git/modules/repo-name
Help and Troubleshooting
As the old adage goes… RTFM. man git
should be your best friend.
Run it on any terminal where you use Git. It’s much better than any online
tutorial you will ever find (including this one). There are also man pages
for each individual Git commands, try man git-add
, man
git-commit
, and so on.
For common problems, you can also refer to Oh Shit, Git?!, but do make sure you understand what you are doing (using the man pages), or you'll have a bad time.
If you're still stuck, do ask someone for help, but make sure you give it a good go on your own first.
Exiting vim
Occasionally Git commands will open vim. Tim's advice is to learn vim, it's worth the effort. If you really want to just exit, the following will work every time. (there are simpler ways when you know what you’re doing).
Type <ESC>:qa!<Enter>, where <ESC> and <Enter> are the escape and enter keys respectively. (You'd be surprised how much clarification this usually needs)