A tutorial for those looking to get started using git and github. Originally used on campus at BYU.
Git might not get you a job, but it will certainly be an everday tool. It's how world-class dev orgs ship applications. Let's get started!
PS - I'll be focusing on GitHub here, but all of the same concepts apply to BitBucket, GitLab, or any other git-based storage site. The UI might look different, but they're all based on the same underlying tech (git).
PPS - Don't worry, I won't let the git puns git in our way.
The README of this repo is the tutorial, but you'll use the rest of the files to practice forking, commiting, open a PR, etc. This won't teach you everything, but I hope it gives you enough of a base if you get stuck in any sticky situations.
- You have git installed on your machine
- You have setup your git config with your email and git username. See the section
Your Identity
in the First Time Git Setup documentation if you haven't done this step. You can make sure that you've done this step by runninggit config user.name
andgit config user.email
.
In this tutorial, you will be doing the following steps:
- Fork This Repository
- Clone Your Newly-Created Fork
- Create a feature branch on your local repo
- Add a python script to the
favorite-animals/
folders - Commit your changes
- Push your local feature branch to your remote repo (your fork)
- Open a Pull Request to the Starting Repository (jasonstewartpariveda/learn-git)
For bonus steps, you can do the following: 7. Pull in the latest changes from this repo (not your fork) into your local repo 8. Resolve Merge Conflict
Instead of adding your changes directly to someone else's repo, you can create a copy of their repository to work with. When you create this copy, we call it "forking the repository."
Conceptually, think about hitting a fork in the road -- the road splits into two. This is the same with forking in git. Forking simply creates a snapshot of the base repository (jasonstewartpariveda/learn-git
) that you can make changes to. Once you make changes, you can open a pull request (PR) from a feature branch on your fork to the base repo's master. More on this later.
After you fork your repo, your newly-created repo will be referred to as a "fork." This might sound weird, but just go with it. I promise it will stick eventually.
- Make sure you're on the base page of the
learn-git
repository: https://github.com/jasonstewartpariveda/learn-git. - In the top right-hand corner, you'll see a button that says "Fork". Click it.
You'll see a screen that shows "Forking repository". You'll now find yourself on a new repo page. If you look in the top left, you'll see that this repo is based on your
<your-github-username/learn-git>
.
Congrats! You've created a fork! This is simply a copy of the base repository jasonstewartpariveda/learn-git
You'll need to clone your fork repository to you local environment. "Clone" might just sound like a fancy way to say "download", but cloning keeps the connection between the remote repository (in GitHub) so you can add our changes (commits) back to the remote. By the end of this step, your will have cloned the repository into a folder on your computer.
- Go to your fork and hit the green "Code" button. Select HTTPS.
There are several ways to clone the repository, including SSH and GitHubs own command-line interface. We're going to keep it simple and go with HTTPS.
- Copy the link in the box. This link is the url to the repository. It should look something like https://github.com/your-username-here/learn-git.git
- If you're on a Mac, open your terminal. If you're on windows, use Git BASH. I'm not a PC user, but I'm fairly certain you can download Git BASH on gitforwindows.org
- Navigate to the parent directory you'd like to download it to.
- Type the following command:
git clone <insert-the-https-url-here>
And Voila! You've officially cloned the repository onto your local machine. Navigate to your repository by running a quick cd learn-git
One of the trickiest parts of Git is updating your local branch with the changes in the remote repository (jasonstewartpariveda/learn-git
in our case). In order to do this, we'll need to add a "remote" reference to our local git branch.
- Run
git remote -v
to see all of your current remotes. You should see one:origin
and that should reference your forked remote repo. Don't worry about the difference between(fetch)
and(push)
for now. - Next, add a remote called
upstream
with the URL of the original repository by runninggit remote add upstream https://github.com/jasonstewartpariveda/learn-git.git
. - Run
git remote -v
to see that new remote added
Congrats! You added your new remote! Now, when updates are added to that repository, we'll be able to pull those changes to your local repository. We'll practice this after we open our pull request in the Bonus section of this tutorial.
Now that you're on your local repository, you can focus on making our changes. Your assignment is to add a script to the favorite-animals/
directory. Yes, very complicated. It's basic, but the goal is to learn git. You'll name your script your_firstname_and_lastname.py
, commit it to your local repo, push your changes to your fork, and open a repo. Phew, that's a lot! Don't worry, you'll focus on creating the feature branch in this step.
-
Make sure you're in the root of your local repo. Use
cd
to get there. To make sure you're on the master branch, rungit status
. The output will show you your current branch. If you're not on your default branch, run the command in step three to switch back. We'll come back togit status
in a minute. -
Run
git branch my-animal
. This creates a snapshot (a branch) of your current branch (master
in this case) namedmy-animal
. You could have named this branch whatever you'd like (ex:git branch covid-sucks
). In this case, you'll be adding our simple script to this branch. -
Now that you have our new branch created, you need to switch our current branch to the new branch. You refer to this process of branch switching as "checking out a branch." Run
git checkout my-animal
. Now, rungit status
to confirm that the current branch asmy-animal
. -
BONUS - in the future, when you create branches, you can use
git checkout -b <insert-branch-name>
as a shortcut togit branch
andgit checkout
. This is the same thing as runninggit branch my-animal && git checkout my-anmial
. Personally, I always usegit checkout -b
.
And voila! You've created your feature branch. You're all set to make these changes.
In this step, you're going to add a script. The important part is that you're going to make changes locally, commit those changes to our feature branch, and ultimately you'll be pushing these changes to our fork.
- Open the
learn-git
folder in your code editor. - Add a new file to the
favorite-animals/
folder. - Name this file
<your-first_name_and_last_name>.py
. Example: stephen_godderidge.py - Add a print statement to the file. This could be anything you want. If you'd like to play along, add a statement that describes your favorite animal. My script does the following:
print("My favorite animals are sloths")
- Save your new file.
Now you're ready to move on and actually commit your changes!
Committing your changes adds your changes to the current branch. Before you commit your changes, you have to stage your changes. This step may seem trivial when you're working on a few files (especially in our case), but this step becomes more helpful as you work on more files at once.
Think of an assembly line that creates new cars. The cars are assembled, and they go to a separate location for a quality check before shipping out to the customer. This is what your staged changes are. You work on a bunch of changes locally, and then stage the changes (quality check) before they're finally committed (shipped to the customer). Once you've staged your changes, you can review your changes before finally committing them.
Think of committing your staged changes as saving your changes to your repository. Follow the steps below, and we'll come back to this question.
-
Make sure you saved your new script.
-
Run
git status
to see the files that have been changed. You should see aChanges not staged for commit:
section. Underneath, you should see the file path to your new script (example:favorite-animals/jason-stewart.py
). These are changes that you have saved to your files, but they aren't currently setup to be committed yet. Your changes aren't staged yet. In fact, you'll need add them to the staged files before you can commit them. -
Run
git add favorite-animals/<insert_your_script_name>.py
. This step adds the file to the files staged for the commit.Note -- if you'd like to stage all of the files you've made changes to locally, you can simply run the shortcut
git add .
instead of adding each file individually. -
Run
git status
again to confirm the changes have been added to the staged files. You should see aChanges to be committed:
section. Underneath, you should see the new file path. This means your files are ready to be committed. -
Run
git commit -m "add my new script"
. This commits the changes, and allows us to add a git commit message at the same time. Now, our branch has been updated to point to this new commit. -
Run
git status
to check that the files have been added. You should see a message that saysnothing to commit, working tree clean
And voila! You've committed your changes.
Now, back to the question โ How is saving your files on your computer different from committing your changes to your repository? Committing your changes bundles all of your changes into a single commit and adds that commit to your branch. Once your branch includes this new commit, you are able to push your changes up to your remote repository. From there, someone else could pull your changes, create a branch from your branch, and start adding new commits. By stringing these commits together, the repository has an accurate view of the current state of the branch.
Once you have several commits on a branch, you can choose to do a whole host of different actions - undo (wipe away the changes completely), unstage (un-commit the changes, and add them to the unstaged files on your local workspace), and more.
Now that you have your changes committed, you need to push those changes to your remote repository, which is a fork of the original learn-git
repository. At the end of this step, your remote repository will include your feature branch.
-
Check which branch you're on by running
git status
. If you're not on your feature branch, go ahead and checkout that branch. -
Run
git push
. Git should automatically display a message similar to:The current branch my-animal has no upstream branch. To push the current branch and set the remote as upstream, use git push --set-upstream origin my-animal
Don't worry, nothing is wrong. Git is simply helping us with your next step. Git is telling you that you need to set the upstream branch of your local branch to the remote copy (origin). Phew, that was a lot. Let's break it down.
So, what is
origin
? This is the term that git uses to refer to a remote repo. In our case, origin is our remote repository (our fork). The upstream branch is the branch tracked on the remote repository by your local branch. So, in our case, we're setting up our localmy-animal
branch to track any changes that happen in our origin's (our fork's)my-animal
branch. When would this be useful? Well, say we have multiple developers making changes to a feature branch. We need a way to pull down the latest commits -
Do as git suggests, and run
git push --set-upstream origin my-animal
. You'll see a bunch of update statements likeresolving deltas
andWriting objects:
. This means git is pushing your local branch to your remote repo. You'll also see a helpful line that should read:
remote: Create a pull request for 'my-animal' on GitHub by visiting:
remote: https://github.com/<insert-your-github-username>/learn-git/pull/new/my-animal
Copy this URL. You're going to need it in a minute!
- Bonus -- go to your fork in your browser. In the top left corner, you should see a button that says
Master
. Click it, and see that your branch is there. You can open you branch and navigate to your script. You should be able to see your changes. Pretty cool right?
Our next goal is to add our commits to the master branch of the real learn-git
repo so others can see our script and make changes if they'd like. In order to do this, you need to submit a request to pull those changes into the repo. In other words, you need to open a pull request.
This Pull Request needs to be approved by the owners of the repository before it can be merged into master. Different companies have different approval processes (example: multiple reviewers from different teams), but our use case is simple. You're simply focused on opening the pull request.
- Open a request by going to the link in the last step of Step 6. It should look like
https://github.com/<insert-your-github-username>/learn-git/pull/new/my-animal
. This should take you to a page with the title of Open a pull request. - Name your Pull Request whatever you want. Add some commetns if you'd like.
- Once you've added your PR name and comments, go ahead and click the
Create Pull Request
.
Congrats! You've opened your first pull request!! Go ahead and take a look around at the different tabs. See if you can find where you can view your changes (Hint: look for files). You can also view your commit(s).
Because you don't own the upstream repo (jasonstewartpariveda/learn-git
), you won't be able to approve your own PR. I'll keep an eye on this repo, and once I see your PR, I'll approve it and merge it into master.
Note that if I wanted to, I could add collaborators that contribute directly to this repository by by going to Settings -> Manage Access -> Invite a Collaborators. This would be particularly useful for group projects.
git clone <insert-the-https-url-here>
git remote -v
git remote add <insert-the-remote-name> <insert url to the original repository>
git status
git branch <insert-name-of-branch>
git checkout <insert-name-of-branch>
git checkout -b <insert-name-of-branch>
git add <insert-name-of-file>
git add .
git commit -m "<insert-a-message-to-describe-the-commit>"
git push
git push --set-upstream origin <insert-name-of-current-local-branch>
note: DON'T Simply run these commands in order. There is some overlap. This list is mainly meant to be a reference for later. Remembering all of the git commands can be tricky. I still regularly google Git commands, and I've used Git everyday for the last 3 years or so.
Need more practice? Take a look at some of these tutorials to expand your experience (Don't worry, they're free!):
- Kent C Dodd's Intro to GitHub -- an Awesome course that helped me fill in some gaps of my knowledge about GitHub way back when.
- Kent C Dodd's Intro to Contributing to Open Source -- the best way to learn is to do, and this is a great course for contributing to real projects on github.
- Another good step-by-step guide from opensource.com
- Here's an interactive git playground that you can practice branching
This tutorial doesn't cover these topics, but they're still useful to know after you've learned everything included above:
-
How to undo your last commit - See the second answer to this post on Stackoverflow.
-
How to view your current changes in VSCode - I definitely recommend using VSCode if you can. I run all of my git commands and logic through the command line, but I use the git tab on the far right toolbar to view the changes to my files. See `the VS Code documentation for more info.
-
How to Rebase Your Feature Branch Onto the latest version of Master - Let's say you're working on your feature branch for a few days, and the upstream master has been updated, and you need the new changes on your feature branch. The process to do this is called "rebasing". It's a good one to know. I'll work on adding a tutorial for it, but in the meantime, you can always Google "how to rebase my branch onto master" and a Stack Overflow link should pop up.
-
How to Resolve Merge Conflicts - Let's say you open a PR that changes files that someone else changed after you created your branch. Your branch doesn't have these changes, so Git isn't sure how it should treat the order of the commits. This is called a Merge Conflict. This is the trickiest part of working in git. This will most certainly cause you headaches in the future. It's worth an entire tutorial by itself. I'm working on adding a full-fledge tutorial, but here are the basic steps: (A) Pull the latest changes from the upstream master into the local master. (B) Checkout the feature branch that has the conflicts. (C) Rebase your feature branch onto master. (D) Use the interactive rebasing process to resolve any conflicts. (E) Force push your changes. Again, I'll add a full-fledge tutorial soon, but hopefully these steps give you a guide for things to Google.
Here are some of the terms we've used in the tutorial. This isn't meant to be a comprehensive git dictionary, but hopefully it helps fill in any gaps you might have after the tutorial.
-
repository - the git-enabled folder. Think of it as your project folder with a hidden .git folder inside. This repository can have branches, forks, and various commits. The main goal is that it tracks all of the versions of a project, both working and development. AKA "a repo."
-
branch - think of branches as pointers to a snapshot of your changes. The default branch in git is referred to as
master
ormain
. Branches are used for new feature development. The process to switch to a new branch is called "check out a branch." Each time you create a branch, you create a new snapshot of the branch you currently had checked out. -
commit -
- verb: to write your changes to whichever branch you're currently on.
- noun: refers to the new changes themselves. Once you've committed your changes, you can undo those changes by undoing the commit. Git uses hashes to refer to your various commits.
-
remote - opposite of local. Used to describe a repo that exists in GitHub (or a different git service). By default, your local repo will have one remote:
origin
. You can add other remotes as well. This is helpful when you want to pull the latest changes from the original repository that your fork is generated from (see Step 2.5 above in the tutorial). -
local - opposite of remote. Used to describe a repo that exists on your local machine.
-
fork - a copy of someone else's repository. This new copy is owned by your GitHub user, so you're able to make changes to it. This is a very common approach in the open-source contributing world. See Step 1.
-
pull request - a request to merge your changes into a branch (usually master). Think of it as a request to pull your feature branch's changes into the master branch. Note that these feature branches can be on a fork of the original/upstream/main repo.
-
push - Used to describe the process of adding your commit to another branch, usually from a local to a remote. Example: Push your changes (commit) to your remote repo.
-
pull - Used to desribe the process of adding the changes from one branch to another, usually from a remote to a local. Pull in the latest changes from the master branch.
*master - Used as the default branch for any repository. There is nothing special about this branch; it's simply the one that is designated as the main branch
> Because of today's society's realization of systemic racism, there are movements to rename "master" to "main." I think this is an important and necessary shift in our verbiage as developers. GitHub will soon make it the default for all repositories. However, in the meantime, for those learning git, it is still helpful to learn "master" as the default branch. New developers will most certainly come across repos with a `Master` branch and need to be aware of what that means. For this reason, I'm going to continue to use `master/main` to refer to the default branch.
Did I miss a term? Go ahead and open a PR to add any you think should be added!