I learn git from this interactive tutorial. I take note along the way while I was doing it.

Learn git visual

Commit to repo

We was on C1 commit

git commit



new branch

git branch <name>

branch new

change branch

git checkout <name>

create a new branch and check it out

It can be shorthand:

git checkout -b <name>


Now we are working on main branch

We are going to merge the branch bugFix into main

git merge bugFix



Note that the branch we are on, will ‘change the base’ to another branch.

Request: Move work directly from bugFix onto main branch

We are on bugFix branch

git rebase main

Before rebase

git rebase main

After rebase


Now we know bugFix is ahead of main branch so we have to merge main branch with bugFix branch as well

git rebase bugFix

git rebase bugFix

Since main was an ancestor of bugFix, git simply moved the main reference forward in history.

rebase <branch1> <branch2>

We are on main branch.

git rebase main bugFix

rebase interactive -i

Open up a text editor, show which commits are about to be copied below the target rebase. It also shows their commit hashes and message.

git rebase -i HEAD~4


git log

What is HEAD? HEAD is the work in action. Simply put: what you’re doing now is the HEAD. Once you commit, the HEAD becomes the branch commit you work on.

Let’s see where the HEAD is hiding:

git checkout C2

git checkout C2

relative refs

  • Moving upwards one commit ^
  • Moving upwards a number of times ~<num>
git checkout main^

git checkout main

Move 2 times

git checkout HEAD~2

branch forcing

You can directly reassign a branch to a commit with -f flag

On bugFix branch, main was on C4 commit.

git branch -f main HEAD~3


git branch f

Reassign a branch main to a hash commit, e.g. C6 commit

git branch -f main C6


Works for local machine

git reset reverses changes by moving a branch reference backwards in time to an older commit, i.e. rewriteing history

git reset HEAD~1

git reset


In order to reverse changes and share those reversed changes with others, use git revert

git revert HEAD

A new commit plopped down below the commit we wanted to reverse. This new commit introduces changes - reverse the commit

git revert

git cherry-pick <Commit1> <Commit2> <…>

Copy a series of commits below your current location HEAD. As long as that commit isn’t an ancestor of HEAD.

Suppose we are on main, and we want C2, and C4 commits.

git cherry-pick C2 C4

This will plop down the main branch twice


cherry before


cherry after

git tag <tagname> <Commit>

Tag is used to permanently mark a historical points in the history. It works as an anchor.

git tag v1 C1

git tag

git describe <ref>

output: <tag>_<numCommits>_g<hash>, the hash is where the branch on

git describe main

git clone

origin/main is called remote branch. When you check them out, you’re put into detached HEAD mode. Git does this on purpose because you can’t work on these branches directly.

To be clear: Remote branches are on your local repository, not on the remote repository.

git fetch

Fetch data from the remote repository

For example, when working on your local codebase, the remote repository has updated and committed few times. In order to download these commits, you can use git fetch to update your origin/main.

This update our local remote branch into synchronization with what the actual remote repository looks like now. It doesn’t change anything about your local state. You have to use git merge origin/main to merge the code.

git fetch

Don’t need to put any other arguments to it.

git fetch <source>:<destination>

Works like git push origin main while it’s on opposite direction

git pull

Often, when you git fetch, you’d like to merge it with your local origin/main:

Use one of the following:

  • git merge origin/main
  • git rebase origin/main
  • git cherry-pick origin/main
git fetch
git merge origin/main

And git provides a shorthand for it git pull

git pull

git pull

git push

git push is responsible for uploading your changes to a specified remote and updating that remote to incorporate your new commits. You can think of git push as a command to “publish” your work.

git push

git push <remote> <place>

The is what branch locally we like to commit to remote. For example, git push origin main, we simply tell git that we want the local main branch to push to remote origin main.

git push origin main

Note that we don’t have to use origin/main, simply origin

git push origin <source>:<destination>

<source> is where you specify your commit, e.g. C1, C2, etc.

<destination> is the remote branch name

Before git push

git place

git push origin foo^:main


git place

Real word example of git push

git push1

The image above, you cannot git push because your local repository is on C3 while the remote repository is on C2.

It’s common for team project. You work on your allocated part and others work on theirs.

Now, how do we push our work to remote repository?

Use rebase

  1. git fetch
  2. git rebase origin/main
  3. git push

The result:

git push 2

Use merge

git fetch
git merge origin/main
git push

git push 3

Use git pull shorthand

Tired of typing so many commands? Use git pull !

git pull is shorthand for a fetch and merge. Optionally, you can use git pull --rebase for a fetch and a rebase

git pull --rebase
git push

git push 4

Alternatively, use merge

git pull
git push

git push 5

remote tracking

Name a different branch to push to remote main

git checkout -b totallyNotMain origin/main

Another way to set remote tracking on a branch is to simply use git branch -u

git branch -u o/main totallyNotMain

If totallyNotMain is checked out, it can be shorter:

git branch -u origin/main