Git Cheat sheet - quick command reference
Here are the list of commands we use quite often.
remote means remote repository uri,
for example, https://github.com/User/myrepo.git
- To clone a remote git repository with depth = 1 and specifying my project name:
$ git clone --depth=1 remote myproject
- To clone a remote git repository with specific branch (eg. master):
$ git clone -b master remote
- To see the branches after cloned all branches (cloned w/o specifying any):
$ git branch -a * dev * master remotes/origin/HEAD -> origin/master remotes/origin/dev remotes/origin/master
- Switching branches (checkout):
$ git checkout dev Switched to branch 'dev'
- Create a branch off master base (checkout -b <new branch> <base off branch>):
$ git checkout -b hotfix master Switched to a new branch 'hotfix'
- To setup local repo with a remote repositories.
First, we need to use git init and then use git remote add remote-name remote-url:$ git init
This will create .git directory into our current working directory. Now we want to add the remote repo:$ git remote add origin https://github.com/User/repo.git
Here the 4th one (origin), we can name it whatever we want to. But origin is a kind of convention. - To see what are the remote repositories:
$ git remote -v origin https://github.com/User/repo.git (fetch) origin https://github.com/User/repo.git (push)
If we want to use the same name, we can drop our project name which is the last argument. - To switch remote repositories from repo1 to repo2:
This is my current remote:$ git remote -v origin https://github.com/User/repo1.git (fetch) origin https://github.com/User/repo1.git (push)
Here it is:$ git remote set-url origin https://github.com/repo2.git
Note that we overwrote (replaced with a new remote) an existing one.
If we wanted to keep the old one, we could have used add instead of set-url:$ git remote add origin2 https://github.com/repo2.git
Then, we have two remote repos:$ git remote -v origin https://github.com/User/repo1.git (fetch) origin https://github.com/User/repo1.git (push) origin2 https://github.com/User/repo2.git (fetch) origin2 https://github.com/User/repo2.git (push)
- To delete a remoee "dev" branch:
$ git push origin --delete dev To https://github.com/Einsteinish/testing-git.git - [deleted] dev
There are couple of options when we do stage files.
- Staging only "modified (including deleted)":
$ git add -u
or$ git add --update
If we want to do commit at one shot:$ git commit -a
- Staging all (modified + new + deleted):
"git add -A" is equivalent to "git add --all"$ git add -A
or
$ git add --all
As we can see from the table below, as far as Git 2, there is not difference "git add -A" and "git add ."
To un-stage a file, we can use HEAD with a file name. For example, to unstage a README:
$ git status Changes to be committed: new file: 1.rb modified: README
Let's unstage the README:
$ git reset HEAD README Unstaged changes after reset: M README $ git status Changes to be committed: new file: 1.rb Changes not staged for commit: modified: README
Before:
After:
Picture credit: Learn Git 20: The Mixed Reset
Sometimes, we want to switch to other branch but we have uncommitted changes.
In that case, we can issue git stash
, which saves our working directory and index to "stash".
Basically, it restores our working directory and index to the most recent commit.
We can then work on other branches, make commits, etc. When we're ready to get back to where we were, we may want to type git stash pop
.
If we have lots of files to cleanup (undo any lines of code that are not working), we use git reset --hard
.
This will put the files back to the original state before staging:
$ git status Changes to be committed: (use "git reset HEAD..." to unstage) new file: 2.rb new file: 3.rb new file: 4.rb ... $ git reset --hard $ git status On branch master nothing to commit, working directory clean
With the git reset --hard
, if a file was newly created and added,
it will be gone (deleted) from our working directory while a file was modified, it'll have the content before any modification.
Before:
After:
Picture credit: Learn Git 21: The Hard Reset
This git reset --hard
can be used with id (SHA hash):
$ git log --graph --oneline * 35e529b README update * 94b269f ruby script * 5de1450 README added * 5dcafb2 C3 commit * 316f4dd C2 commit * 2b61646 initial commit $ git reset --hard 5dcafb2 HEAD is now at 5dcafb2 C3 commit $ git log --graph --oneline --all * 5dcafb2 C3 commit * 316f4dd C2 commit * 2b61646 initial commit
We created a new branch (hotfix) base off a master branch, and now we want to merge it back to "master" branch after worked on the new branch.
Before:
$ git branch dev * hotfix master
Since no changes have been made to the "master", when we merge our "hotfix" back to "master", internally git is doing so-called fast-forward merge: just moving forward the HEAD and Master pointers to a new commit:
$ git checkout master $ git merge hotfix Updating 5dcafb2..85d564c Fast-forward
After:
Picture credit: Version Control with Git - 05 - Branching
"The git rebase
command has a reputation for being magical Git voodoo that beginners should stay away from,
but it can actually make life much easier for a development team when used with care."
- from Merging vs. Rebasing.
Here are the steps I take when I use rebase:
- (main) create a feature branch off of a main branch -
git checkout -b feature
- (featute) commit my works to feature branch -
git commit -m ""
- (main) pull any changes made during my work on feature branch, syncing local main with remote main -
git pull origin main
- (feature) rebasing feature branch against the main,
reanchoring my feature against the latest update (at this point, local main branch has pulled all the updates from the remote main branch). This is when git let us know if there are any conflicts.
git rebase main
- (main) rebasing local main against the feature branch and with this my local main will have a nice linear history
git rebase feature
- (main) all we have to do is just push local to remote -
git push
We can see how it works from:
$ git rebase --help NAME git-rebase - Reapply commits on top of another base tip ...
Before:
$ git log --graph --all --oneline
Before rebase:
To rebase, issue the following command on a testing branch:
$ git branch * testing main $ git rebase master First, rewinding head to replay your work on top of it... Applying: C3 Applying: C5
$ git log --graph --all --oneline
Note that while git is doing rebase, it applies each commit one by one, and it may stop doing rebase if git finds any conflicts.
After rebase:
Picture credit: Version Control with Git - 07 - Rebase
From man page:
Assume the following history exists and the current branch is "topic":
A---B---C topic / D---E---F---G master
From this point, the result of either of the following commands:
$ git rebase master $ git rebase master topic
would be:
A'--B'--C' topic / D---E---F---G master
Note that there is another command that can be used with interactive mode of the rebase
command.
For example, if we want to the last three commits on feature branch into one large commit,
we can move ahead 3 commits with rebase -i HEAD~3
command.
Then, we may want to work on the popped editor to do it.
Just for demonstration purpose, I put my file (a.txt) in several stage with a text of that stage name:
- A file on working directory (working tree) - "My Working directory file"
- A file in staging area - "My Staged file"
- A file already committed - "My HEAD file"
- A file already pushed to remote - "My Remote file"
So, when we issue a diff command, we can see the diff more clearly.
- After we staged a file, and want to see the diff of the file from the one that's already in the HEAD (local repo):
$ git diff --staged a.txt -My HEAD file +My Staged file
- Worked on a file that's on our working directory (or working tree), and want to see the diff from the one already staged:
$ git diff a.txt -My Staged file +My Working directory file
- To see the diff of my file on working tree with the one already in the HEAD
$ git diff HEAD a.txt -My HEAD file +My Working directory file
- To see the diff of my file on working tree with the remote one.
To be more clear, we may want to know how the remote looks like:$ git remote -v origin https://github.com/User/repo.git (fetch) origin https://github.com/User/repo.git (push)
Now, let's do diff:
$ git diff origin/master:a.txt a.txt -My remote file +My Working directory file
We can switch the positions$ git diff HEAD:a.txt origin/master:a.txt -My HEAD file +My remote file
To see tree like git history:
$ git log --graph --oneline --all
To see the changes by commits, we can use:
git show
with HEAD for the most recent commit:- To go back further, we can use HEAD~, or one more backwards: HEAD~~:
$ git show
Or:
$ git show HEAD
$ git show HEAD~3
After merge our feature1 branch to master branch, we want to push feature1 branch to remote repository:
$ git checkout master $ git merge feature1 $ git push -u origin master
On a Github page, select "feature1" branch and click "New pull request". Then, the following page will be opened:
Hit "Create pull request".
Hit "Merge pull request".
Next, after a code review, one of our colleague will merge "feature1" branch to "master" branch by clicking "Confirm merge".
Now, our "master" branch has the new features (F1 & F2 commits):
The "git reset"s are confusing topic even for seasoned git users. We have 3 types of resets.
It's helpful if we picture it from the top level (indexed - committed), then staged, and then working directory, in that order.
Let's assume we have committed v1/v2/v3.
All the 3 types of resets will move back the HEAD to the previous commit (v2).
Let's starting from soft reset to mixed reset (default), and then hard reset.
The soft resets undo the indexed (committed), and put it back to the state before the commit. In other words, the status will be back to staging. So, v3 still in the staging level and it's ready to be committed again.
The mixed resets undo down to the staging. So, v3 is in the working directory:
The hard resets undo all down to working directory, wiping out all. So, v3 is not even in the working directory, gone:
Git/GitHub Tutorial
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization