-
Notifications
You must be signed in to change notification settings - Fork 2
Git and GitHub
Git is the most popular version control system (VCS) - a tool for tracking and managing changes to source code. Originally developed for managing the source code of the Linux kernel, it has since become the de facto standard for source code management. Git is a type of decentralized VCS, meaning it that each copy of the code is treated as its own repository than can be managed independently, as opposed to centralized VCS where a central server is the only full repository to which users push changes.
GitHub is the most popular web interface for git. It provides a free public repository for your code to which you and other contributors can sync your code. However, it provides much more than this. Among its most important features are a system for easy management of pull requests, wikis for repositories (such as the one you are reading right now) and GitHub Actions, a continuous integration system that can automate many actions triggered by pull requests or manual user dispatches.
Git and VCS in general has a very specific terminology used to describe the concepts underlying its usage and features. These are some of the key concepts that are most important to understanding git:
- Repository - a repository refers to a copy of the source that also includes the metadata git uses to track changes. This data is stored in the
.gitfolder that you will always see in the root of a repository. - Branch - a branch represents a "version" of the code with a specific set of commits that diverges from a parent branch (usually the default branch). The default branch in
gitismaster, although many projects now to choose to use the namemaininstead, due to the the association of the word master with slavery. - Fork - a new copy of an existing repository, usually from the default branch.
- Commit - a commit represents a set of changes to the code that has been recorded by
git. One commit can record changes for multiple files, and a single file can be changed by many different commits. - Remote - a remote is another copy of the same repository accessed over the Internet. For most uses this will be GitHub or another Git web service (such as GitLab or BitBucket).
- Push and pull - users can push a set of commits to a remote branch from a local branch, or pull commits from a remote branch to a local branch.
- Merge - a branch is merged into another branch (usually its parent) when its commits are added to that other branch. If some of the commits in the branches to be merged conflict, the user must resolve this before a merge will succeed.
- Rebase - a rebase changes the base commit from which a branch diverges from its parent branch. This is often used to incorporate changes to a branch that were merged into the parent branch after diverging from it.
If you wish to contribute to an existing git repository, you will need to "clone" it to a local copy:
git clone REPOSITORY_URL
This will only clone the default branch in the remote repository. Although you can check out other branches from the remote later, you can specify a branch to checkout when cloning:
git clone -b BRANCH REPOSITORY_URL
Special note: If you are cloning a remote repository from GitHub and wish to make pushes to the remote, you should clone it with an SSH remote instead of an HTTP remote. The HTTP remote for this repository would be cloned as:
git clone https://github.com/danielnachun/dotfiles
The SSH remote would be cloned as:
git clone git@github.com:danielnachun/dotfiles
To initialize a new repository, you will need to tell git where to create the repository:
git init DIRECTORY
If you are already in the directory you want to initialize as your repository root, you can use the . placeholder for the current directory:
git init .
Git must be explicitly told which files/directory to track for a repository. This achieved by adding files/directory to the repository:
git add FILE
git add DIRECTORY
Think carefully about what files should actually be added to your repository. Generally you should only track files that are not generated automatically such as source code or user customized configuration files. Things you should not track include:
- Build artifacts or temporary files - you can use GitHub Actions to generate build artifacts automatically
- Large data or media files - these should be stored in dedicated file storage providers
- Any file that contains passwords or other confidential information
When you want to start making changes to your code, you will often want to make a new branch. This allows you to "switch back" to other versions of the code while making your changes. This is especially important if you are working on several independent modifications of your code, or if you are making changes you expect might break something and need to have a working version available as well. To make a new branch use:
git checkout -b NEW_BRANCH
If you do not specify a parent branch to checkout from, git will use the default branch for your repository. You can specify a different branch:
git checkout -b NEW_BRANCH PARENT_BRANCH
The parent branch can be a remote branch. Often it is a good practice to checkout new branches from the default branch of the remote repository, in case your local default branch is out of sync with the one in the remote repository. If your remote is origin and your default branch is main, you can use:
git checkout -b NEW_BRANCH origin/main
To check out an existing branch, use:
git checkout BRANCH
You can also check out a branch in a remote repository:
git checkout REMOTE/BRANCH
If your remote was called origin and the branch was called branch1, this would be:
git checkout origin/branch1
Git records changes you have made as commits. You must provide a path to the files git should check for changes, and message describing the changes:
git commit -m "MESSAGE" PATH
If you specify a path where no files have changed, you will receive a message indicating there are no changes to commit. If you have actually made changes, double check that you have specified the correct path and are in the correct directory, especially if you are using a relative path.
Once you have committed changes to a branch, you may wish to push it to a remote repository located on GitHub. If you have set up continuous integration with GitHub Actions, you can automatically perform tests or other actions whenever you pushes changes to GitHub. To push changes use:
git push -f REMOTE BRANCH
If your remote was called origin and the branch was called branch1, this would be:
git push -f origin branch1
If you have commit changes to your remote repository and want to sync those commits back to your local repository, you will need to pull the changes from the remote
git pull --rebase origin
In this example --rebase is used as this can better handle situations in which your local branch has conflicts with the remote branch. It is also possible to use --fast-forward:
git pull --fast-forward origin
but this may fail if there are conflicts.
As described above, rebasing is a way of changing the commit at which your branch diverges from its parent. You can even change the parent branch to a different branch if needed. This is usually needed if you have merged other changes and want to incorporate these into a branch you have not merged yet. To rebase interactively use:
git rebase --interactive PARENT_BRANCH
FINISH THIS