Whether you plan on developing websites, games, or business applications, Git is an essential tool for many teams. This guide is a step-by-step introduction to using Git and GitHub. By the end of this guide, you will know how to clone existing repositories, update (push) files, retrieve (pull) files, and initialize new repositories for your projects with Git commands.
What’s Git?
Git is an open source version control system. Developers use it to manage their source code. It’s especially useful to teams working on large projects, as it allows us to track changes, make comments, and see who did what when.
All source code and related development files are stored in Git repositories (repos), which serve as the central hub of our projects. For example, if you’re creating a 2D mobile game with two other developers, you might store all your source code and game graphics within the repository.
Here’s a quick illustration of a basic Git workflow with a local repo and a remote repo. Team workflows are a bit more complex than this, but we’ll expand on this later.
Note that while you’ll probably be working with remote repos to backup your files and collaborate with team members, it is entirely possible to make Git repos locally on your own computer, without ever pushing them elsewhere.
What’s GitHub?
GitHub is a service owned by Microsoft, used for hosting Git repositories. They offer other developer services as well, but hosting Git repos is their primary purpose. You can think of GitHub like an iCloud or Google Drive catered to software developers on steroids. Other services exist, such as GitLab, and GitBucket, but GitHub is the most popular platform. You could host your own Git server if you wanted.
Many open source projects host their code on GitHub since they grant free resources to support Microsoft’s public commitment to open source. WordPress, Joomla, OpenAI, ElastiSearch, and many more projects have homes on GitHub.
Key Terms
Now, review the following terms. We will show them in more detail later.
- A repository is a central collection of information. With regard to Git, it’s where we save and retrieve files, track changes, and resolve conflicts for our projects.
- A commit is a snapshot of a file or files at a certain point in time. You create a commit each time you want to save a version of your files. You can view and revert to any saved commit as needed.
- A branch is a pointer to a commit in a certain context. It’s where the code branches out. For example, you might create a specific branch to design and test a new feature of your program before merging it back with the main branch once it’s working properly.
- A merge is the opposite of a branch. It’s when the new features, improvements, or bug fixes are brought over from one branch back into another.
- A clone is a copy of a repository that remains linked to the original repository. For example, if you join an existing project as a new team member, you would probably want to start by cloning the repository to your local PC. You might clone a remote repo to your local computer for development, or from one repo to another server for production.
- A fork is another way of copying a repository. Forking is usually done for experimental purposes or when an entirely new project is being built off the source of an older one. They are not linked. You might fork an open source project if you don’t have collaborator status but still want to modify the code separately. Forked changes may be merged in with the original public repo if the admins review and approve.
- The HEAD is a pointer to the latest commit in your history. Effectively, it points to the active branch you’re working on.
- Vim is a console based source code editor. It’s Git’s default editor for commit messages and such, though not the one you would probably want to use.
- A collaborator is a user with permission to make changes to a repository. You might invite trusted team members to collaborate on a shared repository. Collaborators can push changes and create branches on their own.
- A contributor is any user who contributes code to a repo. They may not have collaborator status.
Create a GitHub Repo
I’d like to begin with a simple first goal. We will create a GitHub account, create our first repo, and upload sample project files to it.
Visit GitHub.com and create an account if you do not already have one. A free account will suffice. If you are a student with a .edu email, you may be eligible for a free pro account with some extra benefits.
Once you’ve activated your account and logged in, you’ll be taken to the dashboard. Click “Create repository” to begin.
The repository creation page asks you for some more details. You need to name your repository. If your project already has a name, this should match it or be similar. Use lower case characters and no spaces, or use dashes – in place of spaces. Try to pick something that’s not too long. The name you pick will ultimately become part of the link used to access the repo and upload files. You can change it later, but ideally you want to use a good name from the start.
I made my repository private, meaning only me or the people I specifically share it with can access the files. If I set it to public, anyone will be able to see the files and download them. Unless you’re creating an open source project, you should probably use private.
The readme file is technically optional, but it’s a convention to add one. The readme file acts like an index page for your repository. It is shown on the front page of your repository and should briefly describe the purpose of your project or repo. It can be formatted with basic HTML entities using the markdown format. Many open source projects post screenshots of their software, links to more documentation, basic setup instructions, etc. in the readme file.
We will get into .gitignore later. This is a special file which lists project files/folders that git will ignore, or not track.
I chose an MIT license, but you don’t really need to worry about the license unless you’re making the code available publicly.
When you are satisfied, click “Create repository”.
This will take you to what’s effectively the home page for the main branch in your repository. This serves as the root folder for your project’s files. Foremost, you’ll see the readme file and a license file if you picked one. The auto-generated readme is displayed beneath the file listing.
Now that our repo is up and ready to go, let’s learn how to clone the repo to our local computer, add files to it, and upload the new files back to GitHub.
Installing Git
There are several ways to work with Git repos on your local computer. The traditional way is to install Git and use console/terminal commands to tell Git what to do. If you’re afraid of working with terminals, GUI based tools exist. Finally, many IDEs have built in visual Git tools to help. My favorite code editor is VS Code, and it has extensions that make working with Git a breeze.
While I love the simplicity of VS Code’s source control extension, it’s important to learn the terminal commands. I promise, it’s easy, so if you’re afraid of working with commands, don’t be! As a developer, becoming familiar with using terminals in any context is important. There will be situations where you need to deploy applications remotely without the use of GUI based applications. Many developer applications are solely terminal based. So, for your own good, let’s learn some terminal commands!
Begin by going to git-scm.com and following the instructions for your respective operating system. Download and install one of the official Git packages, not one of the GUI clients. If you’re using Windows, you’ll probably want the 64-bit Git for Windows Setup option.
Run the Windows installer or follow the terminal commands shown on the Downloads page if you’re using macOS or Linux. You should be okay using all the default settings, though you may want to change the default editor from VIM to VS Code if you’re using the Windows installer.
With the Windows installer, one of the pages will prompt you to install the Git credential manager. It should be selected by default. Make sure you install this.
To check if Git is installed properly, open your terminal/console and type the command “git -v”
C:\Users\Kevin>git -v git version 2.39.1.windows.1
This will show you the version of Git installed on your operating system. So if you see a version number, Git should be working.
The Git Credential Manager makes it easy for us to login to things like GitHub, so it’s an important addon. If you used the Windows installer, it should have been automatically installed. If you’re on Mac or Linux, or you missed it with the Windows install, you need to install it manually. Visit git-credential-manager on GitHub and follow the installation instructions. Read the instructions carefully to ensure you have it installed and configured properly (we’ll know in a minute).
git clone
The clone command is used to clone a repo to a destination, like our computer. Many times, this is the first thing you’ll do when you join a new team or project. Someone else will have already created a repo, and you’ll want to clone it to your PC.
In this case, I want to clone the test repo I created earlier to a folder in my documents.
Begin by opening a terminal, command prompt, or windows PowerShell window.
Next, change to the directory you want to clone the repo into. This can be done in most terminals using the “cd” (change directory) command.
For example, suppose I want to clone the project into my documents folder. On my Windows setup, my documents is located at “C:\Users\Kevin\OneDrive\Documents”. So I use the command:
cd C:\Users\Kevin\OneDrive\Documents
On my Linux machine, it’s at “/home/kevin/Documents” so I would use…
cd /home/kevin/Documents
Here are screenshots of changing directory in Terminal, PowerShell, and Command Prompt (pick your respective favorite).
Once you’re in whatever folder you want to clone the repo into, use the “git clone <repourl>” command where repourl is the link to your repo. You can find this link on the first page of your repository in GitHub.
In my example, the command I will use is:
git clone https://github.com/kevinsguides/helloworld.git
Of course, use your own repo’s URL instead. If you use mine, you won’t be able to get it, since it’s a private repo I haven’t shared with you.
This is where we get to see if the git credential manager I touched on earlier was setup properly. If it’s installed correctly, a separate pop-up window should appear asking you to login to GitHub. If instead you see text messages in your terminal asking you to login with your username and password, your credential manager is not setup properly. Logging in through the terminal will probably not work. You should login through the credential manager pop up with the “Sign in with your browser” option.
After you sign in, you should see a message saying Authentication Succeeded. Then in the terminal Git should report back that it’s received objects. If your terminal looks similar to the following screenshot, you’ve succeeded.
Now, when I open the folder in my file browser, I can see the same two files shown online in the repo are now locally saved on my computer. Note that by default, Git clones the repo into a new folder with the repository’s name under whatever directory you “cd”ed into earlier. So when I used “cd /home/kevin/Documents” and used git clone, it put the repo’s files under /home/kevin/Documents/helloworld.
Uploading New Files
Now suppose I want to edit or change the files in my repo from my local machine. I’m going to start by updating the README.md file in VS Code.
Add some more text to README.md with VS Code or your favorite code editor and save it.
There are several steps involved before we can upload or “push” the file to the GitHub repo.
Git Config
First, we must set the global user email and name for our Git account.
I will use my GitHub username as my user.name for Git.
git config --global user.name kevinsguides
And for my email…
git config --global user.email [email protected]
If you don’t see an error after typing each of those commands and hitting enter, it was a success.
git status
Now that git knows who I am, I’m ready to prepare my file for upload.
First, cd into the helloworld directory (or whatever folder contains the repo files).
cd helloworld
Now, type git status to see the status of your local repo.
git status
As you can see, Git has determined that I’ve modified README.md. However, I haven’t added the change. Unlike Google Drive or iCloud which automatically sync files bidireectionally, Git requires us to provide a few more details – to explicitly tell it what we want to change. This helps prevent accidental conflicts and is especially useful if multiple people are working on the same project. While these extra steps may seem annoying, they are essential and may save you a lot of headache down the road.
Git is giving us two options, we can use “git add” or “git commit -a”
Let’s look at git add first.
git add
The “git add” command allows us to stage our files. It’s an intermediary step between making the changes and pushing the files to the remote GitHub repo.
When you include a file with the add command, Git stages the changes in a temporary staging area. Here, you can select exactly what changes you want to commit. For example, you could stage everything that was changed, some of what was changed, or even single parts of changed files, while ignoring other changes. Then, before you actually complete the commit, you can review what you did.
If you’re a sole developer working on a smaller project, or you really didn’t make any major changes, you might be able to get away with bypassing this step with the alternative “git commit -a” command, which adds all the changes and commits them in a single step.
However, if you’re working on a more complicated project, it’s a good idea to include this step, since it allows us to review our files one last time in the staging area, before we create the commit and push it to GitHub.
You can either type…
git add .
to add all the files in the folder to the staging area, or type the individual file name
git add README.md
For now, we’ll only add all the changes in entire files. We will discuss selecting and adding individual parts or sections of changed files in a future guide.
After you add the file, check the status again with git status.
Now, the message has changed. The file has turned from red to green in my example (if your terminal does not support colors it might look no different). The file has been successfully staged.
git commit
Once we’re satisfied that everything looks right, we can commit the changes. When we commit changes, we’re creating a save point or snapshot with a message explaining briefly what changes were made. Remember, we can always revert to old commits and view them as needed. So make commits often, whenever you feel you’ve added something of significance to the project. This could be a small function, part of a larger function, a few paragraphs of documentation, or anything else you feel is important.
Remember, Git repositories and commits track the changes to your files. Every time you add, change, or delete a line of code and make a new commit, Git saves and remembers these changes. Git does not copy or save unchanged files when you make commits – it only records the changes or the state of the files. This way, if you have a project with 1000 files, and you only update 5 of them, Git doesn’t have to waste time and resources copying the 995 files you didn’t change.
It’s important to add messages to your commits, so you can look back and see what, where, and when changes to code happen. Don’t make it too long, but don’t use entirely undescriptive messages either.
git commit -m "added more project details to readme"
Now it says a file was changed and an insertion is happening. An insertion means I’ve added a line of code to the file. Depending on how you changed your file, this may be a bit different. But it still should say the message along with the fact that you’ve changed a file.
With the commit done, I’m finally ready to push the changes up to the server.
Alternatively, I could have skipped the “add” part earlier and just committed the changes using the -a flag. “git commit -a” That would have added and committed the files in one step.
git push
The “git push” command will push the changes up to GitHub.
Since I logged in when I first cloned the repo, and my repo only has one branch (we’ll get into this later), I can just run “git push” without any extra arguments.
git push
Assuming you didn’t make any other odd changes to your file on GitHub, and you haven’t given other people control over your private repository in the last 10 minutes, the push should be successful.
Now, when I return to the repository in my browser, I can see the updates I made!
git pull
The next command you should become familiar with is git pull
which is essentially the opposite of git push. Git pull automatically combines the actions of two more specific commands, fetch and merge. So git pull fetches changed files from the remote GitHub repo and puts them into your local repo. Then it merges the fetched files with your local project files.
Let’s begin by creating a new text file in our GitHub repo, through the browser. It doesn’t really matter what you call it.
Click “Add file” near the top of the repo page and create a new file.
Name your file and write a brief message. Then click commit changes.
Enter a brief message and finish the commit.
Now, you’ll see the new file in your repository.
Return to your terminal. You should still be in the same folder (documents/helloworld – or wherever your local repo is).
Type git pull
git pull
The message indicates that test.txt has been added successfully. When I browse to the folder with my file explorer, I can see the new third file is in the folder.
Hooray! You now should know how to clone, stage, commit, push, and pull files between your local repository and GitHub.
git init
Suppose your workflow began a little different. Instead of creating a repo on GitHub and then cloning it to your computer to start, you created the project files on your local machine first, and now want to add them into a new repo on GitHub.
To demo, I created a new folder under documents called “hellomoon” and added a “hi.txt” file to it. I have not yet touched GitHub.
Now I want to set up a new local repo. I open up my terminal and change directory (cd) into documents/hellomoon
cd ~/Documents/hellomoon
Next, I need to initialize the git repo using the “git init” command
git init -b main
This initializes a new git repository in this folder on my local machine using the main branch. It tells git to start tracking this folder.
A “branch” is a point where the codebase diverges. For example, you might have a “development” branch and a “main” branch for the same repo. The development branch would be used to work on the brand new features. The main or public branch might be just for stable releases. The -b flag told Git to use the name “main” as our first branch.
After initializing the repo, a .git folder is added to my project’s files. The .git folder contains all the information Git needs to track our files – including the object database, which stores a compressed version of each file changed and committed. You should leave this folder alone. This folder existed in the previous helloworld example as well.
If you don’t see the .git folder, it’s probably because your file browser/explorer isn’t set to display hidden folders/files (items starting with a period).
Now I want to add, commit, and push these files to GitHub. But before I can do that, I must first create the repository on GitHub.
I did the same thing as I did before with hello world. I called this repo hellomoon and set it to private.
Clicking Create repository should redirect you to a page with the link to the repo. Copy the link.
Now we need to issue a few commands. These are the same commands it says on the link page, but I’ll explain them a bit.
First, add the file (or files) in your project to the staging area
git add hi.txt
Next, commit the changes and enter a message.
git commit -m "initial commit"
Now we need to make sure we’re on the main branch. The -M flag means move to this branch (main).
git branch -M main
Since we want to push to a remote repository, we need to tell Git where that repository is.
The following command is telling git to remember a remote repository’s URL. “git remote add” means add this URL, the word “origin” is the name of the remote repository. Conventionally, the name is origin, but you could name it something else if you wanted. Finally, copy/paste the URL.
git remote add origin https://github.com/yourusername/yourrepo.git
Finally, we’re ready to push to the remote repo.
git push -u origin main
The -u flag creates a relationship between our local repo and the remote repo. The “origin” is the remote repo we are pushing to, which was added with the name “origin” in the previous step.
The final argument, “main” is just the name of the branch we’re pushing to.
Since we issued the command with the -u flag, moving foreward, you can just use the commands “git push” and “get pull” without the extra arguments, and it should know to use the repo we’ve already specified.
When I go return to GitHub, I can see the file now exists in the new repo.
Command Summary
Review this diagram: it visually represents the essential commands you learned in this guide.
init
- Creates (initializes) a new repository in the current folder. The repo itself is in the hidden .git folder.
add <filename>
- Adds file(s) to the temporary staging area.
status
- Check the status of your repo, modified files, etc.
commit
- Move from staging area and into the actual repository
git remote add <originname> <url>
- creates a link to the remote repo
- origin name is usually just “origin”
- url is the full url, eg. https://github.com/username/repo.git
push
- Update remote repo with changes from local repo
push -u origin main
- set upstream (-u) repo to the main branch of the remote repo, which has a default name of “origin”
- creates a link between your local repo and the upstream repo
branch
- shows your branch status
branch -M main
- -M flag means move branches, so move to the main branch
pull
- Update local repo and your working directory with files from the remote repo
.gitignore
The .gitignore file is a text file placed in the root of your repo, which specifies the files and folders Git will ignore.
This is especially useful in situations where you’re using a package manager or some type of complicated framework. For example, if you’re building a project with React/NodeJS, the files needed to make your project work are usually stored in a node_modules folder in the root of your project directory. Your app depends on this folder to work, but none of the code within that folder is actually part of the project – you’re not trying to modify the React framework, just the files your project needs to function.
Whenever your project has dependencies like this, you add the respective folder to the .gitignore file. In this case, my .gitignore file might look like this:
# dependencies
/node_modules
Code language: plaintext (plaintext)
That would ignore the node_modules folder whenever I interact with Git. It won’t try to push, pull, or track changes in the node_modules folder. This is important, as we don’t need to upload/download 1000s of files from our dependencies each time a dependency is added/updated, or someone needs to clone the repo. Instead, we include a dependency manifest file (package.json, or similar). Then, when someone needs to clone a repo to their development or production environment, they only grab the project files from the Git repo and use a package manager to install the dependencies separately.
Tracking Changes
Now that you can push changes to your GitHub repository, it’s time to familiarize yourself with some of the powerful developer tools available through GitHub.
Begin by making another edit to a file of your choosing in your local repo. I’ve just added some more text to my “hi.txt” file.
Add the file, and commit the changes.
Remember, you can add a file and commit at the same time using the command:
git commit -a -m "added a line of text"
Optionally, check the status with “git status” and then push to GitHub using “git push”.
Now let’s see what happens when we look at the repo’s page in GitHub.
I’d like to point a few more things out. First, the top left dropdown shows what branch we’re on. This will be important in the future.
The little time symbol with a number next to it shows the total number of commits, and the time of the latest commit, in any file.
Next to the filename itself we can see the message of the last commit, and the time that file was last pushed to the repo.
Click on the little time symbol in the upper right where it shows the total number of commits.
This brings us to the commit history of the entire main branch of the repository.
It shows I made two commits yesterday, when I first started writing this guide, and today, when I added the new line of text.
This is helpful as a solo developer to see what changes you made yourself, and it will be especially helpful later when you’re working with a team of people.
Click on your latest commit.
When you open an individual commit, you can see details about the commit itself.
You will be able to see what files were changed, and how they were changed.
In this example, notice that I added a line of text to the file. Because I did this, the line is highlighted in green and a little plus icon is next to it, showing that it’s a new line.
There’s also a place at the bottom of the commit to leave a comment, so developers working on the same project can give each other feedback.
Now look what happens when I delete the new line in my file, save the changes, and push another commit.
The line of text is still visible in the commit, but it’s highlighted in red, with a minus sign next to it. Showing that this was the line that was removed.
I replaced the removed line with an empty line, so it’s showing an addition of a new blank line in green at the bottom.
This is the unified view, which shows your deletions and additions together in one file. What do you think the split view does?
If you guessed it shows the old and new versions next to each other, you would be correct. This allows you to see the old file, in its entirety, next to the updated file, in its entirety.
How you view it is up to your preference. I find I use both depending on how complicated the changes of the commit are.
Git and GitHub have far more tools than this. We can use commit histories to help us resolve conflicts between different developers, identify errors or possible performance issues, and see who did what at a glance. If something is royally messed up, we can even revert the entire repository back to an earlier state. You will learn more about using these features in the future.
Final Notes
- Now that you know the basics, I would encourage you to explore the other areas of Git and GitHub.
- Please read the guide on workflows, branches, and merge commands. That’s the next thing you need to know.
- Look at Visual Studio Code’s version control extension, which works flawlessly with Git.
- Remember, if you update a file locally, you’ll need to use git add, git commit, and git push to send the changes up to GitHub
- If you’re unsure where you’re at, you can run git status at any time
- If you’re done with your test repos, you can delete them at the bottom of the “Settings” page under each repo (not your GitHub profile settings, the individual repo settings).