Okay, so you have come here because you want to learn Git/Github. So instead of writing a 10 lines paragraph about it, let’s get to the point. I will keep updating this article in the future to make it as comprehensive but concise as possible.
Step one. Go to https://git-scm.com/downloads and download git according to your OS.
Now save the file and run the executable. From here, just follow the prompts to install Git. Unless you know what you are doing, just leave all the defaults as they are. You can also install from source.
Once it is installed, run
to check the installation was correct.
Creating a Github account
Alright, your next step is now to go to https://github.com/ and create and account if you don’t have one yet by clicking on the “Sign Up” button.
Congrats, you got git now. Let’s configure your username and email:
$ git config --global user.name "James Porter"
$ git config --global user.email "firstname.lastname@example.org"
This will be useful when fetching from your repositories. You can also configure your password by following this tutorial.
What’s a repository
Fancy name for a project folder, managed by git. That’s it.
Creating a repository
Okay, so there are two ways to do this. First one, is by Github. Once logged in, go to the “Repositories” section and click on New.
Then, follow the information
Making a repository Public means that everyone will have access to seeing it, whereas Private means that only you and the contributors of the repository can access it and make changes. You can add a
.gitignore file so that some files are not pushed automatically. This is a common scenario in many projects where you don’t want to include auto-generated IDE or heavy files, environments and so on.
Once created, the repository will look like this:
Now what we are going to do is, open a terminal console in Mac, or the Git Bash app that was installed before, and go to the location you would like your repository to be in.
In this case, I just went to a folder called
git_example on my Desktop. Next, we go back to our Github repository, and click on the Code button.
Now just copy paste the HTTPS address there, go back to the folder you opened on your Git Bash or terminal window, and execute
git clone like so:
$ git clone "https://github.com/JairParra/demo_repo.git"
Cloning into 'demo_repo'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), done.
If you check the directory, you should see the same contents as we saw before.
$ ls -la
drwxr-xr-x 1 jairp 197609 0 Mar 22 20:57 ./
drwxr-xr-x 1 jairp 197609 0 Mar 22 20:57 ../
drwxr-xr-x 1 jairp 197609 0 Mar 22 20:57 .git/
-rw-r--r-- 1 jairp 197609 1928 Mar 22 20:57 .gitignore
-rw-r--r-- 1 jairp 197609 36 Mar 22 20:57 README.md
Congrats! You now have your GitHub repository.
Okay, now let’s take a look into some of the commands. Let’s suppose we make a change in the local repository, say create a file:
You can then press
I , write something, and then
:wq to save and close. Now, if we run the command
git status , we will see that the file has changed but it’s not committed, and it appears in red:
In order to make , record and track these changes, use the command
git add .
which will add every change under the current directory for commit.
Now, a commit means that you have told git that you are about to apply these changes to your current branch, which by default, is the main. A branch is essentially a copy of your current project, but with possibly different changes and variations.
git add . , using
git status should give you something like this:
We see that the
example.txt file is now in green, which means it is recorded as a change. Note that you can also add individual files independently by specifying the filename instead of a dot, such as
git add example.txt
This will avoid adding every single file that has changed.
Now, in order to actually register the changes you have made, you need to use
git commit -m "Some message"
This will commit the file with the input message by using the
-m flag (duh). That is, this will register the change to be pushed to the remote repository, but it doesn’t immediately apply it. You can have multiple commits before pushing them (i.e. writing them in the remote repository). Always try to make your messages short and relevant!
When we commit, the files changed and some descriptions can be seen as output. If we use
git status we now see that our local branch has changes yet not merged with the remote one.
Okay, so we have some changes. The typical command to send them to the remote is
git push -u origin main
-u is a flag that sets up upstream for git pull/status; it links the local branch to the remote.
origin is a shorthand for the name of the original repository you cloned from.
main is the main branch or working copy of your repository. If the push has been successful, you should get something like this:
Now, let’s head to the remote branch on Github: you will see that the changes have been applied and the new file is there. Great!
Now, what happens if one or more files change on the remote repository? e.g. someone else working on the project makes a change. How can you copy these changes into your local? That’s when you would like to use
git pull on your local machine. Say, let’s modify the
README.md file on github. First click on it.
Then, click on the edit icon (which I circled in red). This will show you the following view:
Now, we are just going to add some text, say
## Example sub-title
These are some markdown descriptions:
If you scroll down, you will then see the Commit button along with a space to add a message. Just leave the default options and click on commit the changes.
You will see that the changes have indeed been applied, but if we take a look at the local repository, they are not there!
If you use
git status you will also see “nothing to commit”:
In order to download the remote changes, use
git pull or
git pull origin ; you will then obtain the following output:
Now if we check the file again, we see that the changes have been copied into the local!
Git auto-merge & git log
Okay, now, what happens if some change is made to the file remotely AND locally at the same time? Let’s try it out! Let’s first add the word “CHANGE1” to our local
example.txt file with
vim example.txt +
I .The resulting file should look like this:
git add and
git commit -m "change from local" to commit the changes.
Now let’s head to the remote, and add the word “CHANGE1” to the same file, but in addition, also add the word “change2”, just below.
Now, just commit the changes, and head back to your local repository. Next, try to
pull the changes from the remote by using
git pull origin ; what happens?
We see that there is a merging conflict, since changes were made to the same file from the local and remote repositories. In order to solve this, we need to go and edit the file, and opt for the desired changes. Note that you don’t need to edit everything via command line and bash; this is just for illustration purposes. If we open the file with
vim example.txt , we can see the following:
using whatever editor you like, you can simply go and delete the extra lines added automatically by git, leaving only the desired changes. Say, we can just leave it like so:
This is an example text.
you can save the file (
:wq in vim) , and press
git status :
and nothing has changed yet. That’s because we need to
commit the file first! Say, you can use:
git add .
git commit -m "fixed merging conflict"
which will produce the following output:
Now we get “your branch is ahead by 2 commits” message; you can check the history with
git log , which might look something like this:
We can see that every action that we have made has been registered. Now we can go ahead and push to remote with
git push -u origin main :
Git reset — aka, you screwed up
Okay, now supposed you made a mistake, say you accidentally deleted the first two lines in the
example.txt file, that is, before it was
This is an example text.
and now it is
Further, you didn’t really realize, and you committed the changes:
What do we do if we want to restore the way the file was, say to the previous commit? First, let’s check
git log , before we made the commit with the error:
say we would like to go back in time one commit, and rest everything to the way it was at that commit. We can do this by using
git reset --hard HEAD~1
--hard flag means that everything is rested to the state of that commit, including any additional changes you have made, so be careful! The output is
We can verify by opening the
example.txt file that everything is as it was before!
Amazing!! Note that if we use
git status , we will see that our branch is now behind by one commit:
That is because we went back in time. To save these changes, we have to
push into the remote:
Oops!! It looks like we have to
pull from the origin first. But what if when pulling, the changes we’ve made so far get corrupted? Now, if you pull from the remote, git will force you to fast-forward, hence having the same mistake. Whenever this sort of thing happens, it’s easier to have a backup copy beforehand, so that in the case something went wrong, instead of using git black magic to solve it like crazy, you can simply copy-paste on top of it. Be smart folks.
Git push — force
Here’s what you should never do:
git push --force
Now, this will work in this case and overwrite the contents in the remote, but here’s why you should never do it:
- You might actually not even have permissions (which should be the case at any work situation).
- If you do have permissions, you might break other contributor’s code or production — hence the “it’s interns season” memes. Seriously folks. Just. Don’t. Do it.
One safe way to go is to use
git stash . This will temporarily hide any changes we make. For instance, if we create a file called
touch ex.txt in bash, or with any editor, and then use
git add .
the change will be temporarily hidden:
You can see that the
ex.txt file we created is not there anymore:
Now this is the time you would like to
pull from the remote repository, and then apply your hidden changes. If there is a merge conflict (i.e., your changes are different from what was pulled), then you can go ahead and resolve it now, without being afraid of your files getting overwritten by the
Next step to restore the hidden changes is to use
git stash apply
. In this case, we will get back the
ex.txt file we had created before:
Cool! Now we can simply commit the file and push it to the remote:
Amazing!! Checking the remote, you will see the changes have been applied correctly :)
Git reset — soft
Okay, so if there is a
--hard flag, there should be a
--soft one, right? What’s the difference? Suppose that you made a change, and committed it by mistake. Now, you no longer want to commit that change, but you also don’t want to lose it (perhaps you want to add more things before). In such cases, you would use the command
git reset --soft HEAD~n
This will go back n commits in time, but preserve the changes. That’s it, although they disappear from the log, the changes are actually still there. For example, let’s modify the file
example.txt , adding a new line:
Now, suppose we add and commit this change — but not push it yet to the remote:
Now, if we check
git log , we see that the commit is indeed there:
In order to undo the commit, but keep the changes, we simply run
git reset --soft HEAD~1
so we go back by one commit — while keeping the changes. When checking
git log , the commit is no longer there!
However, if we inspect the file, we see that our changes are preserved.
Okay. This is how it works: by default, you have a main branch (previously “master”). This is the core of your project. Now, supposes that you accidentally erase important files, or make an important bug without realizing, which screws the whole project. Oopssie. Could this have been avoided? Yes. A branch is essentially a clone of the repository at a certain commit in time. It’s common to work with branches so that different people can work on different aspects on the same files at the same time, also to avoid accidentally committing errors to the main project. When a branch feature (i.e. some addition) fix or similar has been completed, then two branches can be merged. To create new branch, you can use
git checkout -b branch_name
So here, we have created a new branch called “my_branch”. All the changes that we commit here will be applied to this “copy” and won’t affect the
main branch. The
checkout command is to switch into an existing branch, but when using the
-b flag, we are also creating a new branch.
Once again, let’s go ahead and create another file into this new branch , call it
file.txt . We can commit this file to the current branch as we would do in the main branch currently. We will do the following:
git add file.txt
git commit -m "added file.txt"
git push -u origin my_branch
Note how we specified
my_branch when we did the push. Now, if we go to the main branch with
git checkout main , we will see that the
file.txt file does not exist there.
How can we update the main branch with the changes? Being in the
main branch, we can do so with
git merge my_branch
Similar to what we had before, we have now integrated the changes in
my_branch into the
As now we see that the
file.txt exists in the main. In the case of a conflict, you would have to solve it similar to before.
Git commit — amend & git commit -a
For the sake of completion, let’s consider one more case you might encounter often: suppose that you have made a commit: you would like to alter it / add stuff without making a new commit. That’s where
git commit --amend comes save the day: it overwrites the last commit with whatever new changes you have made. For instance, let’s suppose we modify the file
ex.txt by putting some text into it:
Now, let’s commit and push the changes to the remote:
Now, we would like to correct the random gibberish at the end of the file, and perhaps creating another one. Instead of creating a new commit, we can simply make the changes,
add them, and then amending the commit like so:
git commit --amend
This will open the commit file, so that we can change the message if we wish. Else, we can simply leave it as it.
If you are in vim, press
I to edit the file, and then
qw to save the changes.
pull from the remote first, solve the
merge conflict, and now we are ready to push again!
Here we solve the conflict:
We can then use
git commit -a
To complete the merge (the
-a flag is to commit all changes)
Another example, but this time before pushing into remote: here, you will see there’s only one commit :
The commands employed above are as follows:
git add .
git commit -m "added file"
git add .
git commit --amend
I + :wq
git push -u origin main
You are a git expert now. Hmm. Not quite, but now you have all the basis you need to get started. Next steps? Use it, and if you don’t know how to do/solve something, Google and StackOverflow are your best friends (yes, stackoverflow has a main page, wink wink ;) ). And always remember to currently keep an aside copy anyways :)