What is VCS?
- Version Control System stores changes in file(s) over time so we can check out any version anytime.
- Tracks who modified what in the code.
- Allows to revert back to a version.
- Each collaborator has the whole version history in his computer in
.git
folder.
Git vs other VCSs
Most of the VCSs think of the information they store as a set of files and the changes made to each file over time (delta based version control).
Git thinks of its data as a stream of snapshots. Each time we store data a snapshot is taken of all files at that time. For increasing efficiency, the files that aren’t changed are referenced from previous commit. This makes common operations faster.
Install Git
For Linux
$ add-apt-repository ppa:git-core/ppa
$ sudo apt update
$ sudo apt install git
For Windows
Initialise Git repo
$ cd ~/Desktop
$ mkdir git-tutorial
$ cd git-tutorial
$ git init
.git
folder
.git
folder in the root directory of the project is where Git stores all the information. Deleting this folder will result in deletion of all versions and further Git commands will show the error -
$ fatal: Not a git repository (or any of the parent directories): .git
Configure username and email
$ git config --global user.name 'RohanBh'
$ git config --global user.email 'brohan52@gmail.com’
Install Atom or Sublime Text Editor
Atom
$ sudo add-apt-repository ppa:webupd8team/atom
$ sudo apt update
$ sudo apt install atom
Sublime
$ sudo add-apt-repository ppa:webupd8team/sublime-text-3
$ sudo apt-get update
$ sudo apt-get install sublime-text-installer
Note — Run Atom using the command atom
and Sublime using the command subl
from terminal.
Use editor of your choice
$ git config --global core.editor "subl -n -w"
$ git config --global core.editor "atom --wait"
OR
$ export GIT_EDITOR=subl
This will be valid only for current session of terminal.
Use Vim Editor
- press i to start typing
- press esc to stop typing
- Type :wq (w-write q-quit)
- then press enter to exit
Common commands
git status
git add
Usage:
$ git add <file1> <file2> <file3>
$ git add *.txt
$ git add --all
$ git add .
- Untracked files
- Tracked files
git add
stages the changes made to files. Also git starts tracking the untracked files if they are added to staging area.
Three States of changes done
- Committed means that the data is safely stored in your local database.
- Modified means that you have changed the file but have not committed it to your database yet.
- Staged means that you have marked a modified file in its current version to go into your next commit snapshot.
Note -
Working Directory is also knows as Working Tree. Also, the Staging Area is referred to as Index. It acts as an interface between working tree and repository.
- Any time you see your project, its state can be understood as
Project = “.git Repository” + “changes in Index” + “changes in Working directory”
- Although commands like
git diff
shows us these changes, remember that these “changes” are actually “whole files” as mentioned in this section - Changes are “staged”, if they are in the “Index” and unstaged if they are in the “Working directory”.
git reset
It is used to undo add
Usage
$ git reset <file1> <file2> <file3> # Take the files out of the staging area
$ git reset --hard <commit-id>
$ git reset --soft <commit-id>
$ git reset --soft/hard HEAD~n # Use this to move the branch back by n commits
Note — git reset
by default runs with the flag --mixed
. To get an in depth knowledge of git reset
, read this SO post or this official post.
git commit
Commit is like a snapshot in time. We can return back to this commit anytime in future.
Usage
$ git commit -m "Commit message"
- Amend previous commit
$ git commit --amend -m "Change previous commit message"
$ git commit --amend --no-edit # Modify previous commit but keep the commit message same
If we have some changes that we would like to include in the last commit, we use --amend
flag with git commit
. This new commit contains all the newly staged changes as well as the changes that were committed in the last commit. The new commit is not same as the previous commit. Therefore, if origin/branch has the old commit and you push an “ammended commit” then your branch will diverge!
Commit all tracked files
$ git commit -a -m "Commit message"
- This command adds all the “tracked files” to the staging area and then commits the changes made in them.
git diff
git diff
prints nothing for Untracked files.
Usage
$ git diff # View all the unstaged changes made since last commit
$ git diff --cached # View all the staged changes made since the last commit
$ git diff --staged # Same as --cached
$ git diff <file1> <file2> <file3> # View the changes only for the mention files
$ git diff <commit-id> # View the changes you have in your Working tree relative to the named <commit>
$ git diff HEAD # if we use HEAD as <commit>, we will get both staged and unstaged diff since last commit.
$ git diff <commit-1> <commit-2> # same as <commit-1>..<commit-2>, explained below
git diff <commit-1> <commit-2>
is used to view the changes between two arbitrary commits. In other words, it prints out the difference between the working tree you’ll get after doing git checkout <commit-2>
and the working tree you’ll get after doing git checkout <commit-1>
. So, when using it for two commits in the same branch, to include the changes done in <commit-1>
, we run git checkout <commit-1>^ <commit-2>
, where <commot-1>^1
points to the parent commit of <commit-1>
.
git log
Usage
$ git log
$ git log -p # View diffs introduced with each commit
$ git log -n 5
$ git log --all # show all commits except for the ones that are "lost"
$ git log --oneline # this flag condenses each commit to a single line
$ git log --graph # this draws an ASCII graph representing the branch structure of the commit history
$ git log --oneline --graph --all # Used to print the whole network
Sample Output
commit 9c2f963d097df58040ee26673a15f50dc4c954dc
Author: RohanBh <brohan52@gmail.com>
Date: Fri Jan 19 11:23:57 2018 +0530
Complete the more section
commit 3b1c96765005b1806b31617987a9bfb374a943b7
Author: RohanBh <brohan52@gmail.com>
Date: Thu Jan 18 19:45:19 2018 +0530
Add GridView adapter
:
Git identifies commits by attaching a long hexadecimal number to every commit. These can be seen using git log
. The ID corresponding to the commit "Complete the more section" is 9c2f963d097df58040ee26673a15f50dc4c954dc. Usually first 4-5 characters of this ID are enough to identify the commit.
git checkout
Usage
$ git checkout <commit-id> # Visit the commit made earlier with id=<commit-d>
$ git checkout branch-name # Change to another branch
$ git checkout -b branch-name # Create a new branch and then checkout that branch
$ git checkout -- <file1> <file2> <file3> # discard unstaged changes(changes in the Working Directory)
$ git checkout <commit-id> <file1> # Update the index and working directory so that they match with the committed file1 at that commit.
$ git checkout HEAD file1 # discard all changes(staged or unstaged) made to file1
- **NOTE — The last command is not Working Directory safe. Your changes in Working Directory could be lost. This is why it can be used for discarding changes with HEAD in place of .**
HEAD
- HEAD is a reference to the last commit in the currently checked-out branch. Git automatically moves the HEAD pointer along when you create a new commit. You are automatically on the newest commit of the chosen branch.
Detached HEAD
- When we commit in a Detached HEAD state, the commits do not belong to any branch and are thus lost.
git branch
Usage
$ git branch --list # display all local branches
$ git branch # same as above
$ git branch -r # display all remote branches
$ git branch new-branch # create a new branch
$ git branch -d old-branch # Delete a branch if the local old-branch isn't ahead of origin/old-branch in commits. Shortcut for --delete.
$ git branch -D old-branch # force delete a branch anyways. Shortcut for --delete --force
git stash
Usage
$ git stash # stash away modified tracked files and staged changes so that you are free to switch branches
$ git stash apply # Apply the stashed changes. It doesn't removes the removes the changes from the stash list
$ git stash drop # Remove a single stash entry from the stash list
$ git stash pop # is equivalent to `git stash apply && git stash drop`
git merge
Usage
$ git merge branchname -m "Commit message"
$ git merge --no-ff -m "Commit message"
- A fast forward merge moves the branch pointer to the head of branch that is being merged instead of creating a merge commit.
- Let’s say branch B is to be merged in branch A. A fast forward merge happens by default if the branch A’s tip is the ancestor of branch B. To prevent it, we use
no-ff
flag.
git remote
Usage
$ git remote add origin https://github.com/<username>/learning.git
$ git remote -v #list existing remotes
$ git remote set-url origin url.git #change existing origin
- Note —
.git
can be omitted.
git push
Usage
$ git push origin branch-name # push local changes to remote branch
$ git push -f origin branch-name # force-push local changes
git fetch
Usage
$ git fetch # fetch the latest changes from the default remote upstream repository
$ git fetch remote # fetch changes from specific remote
$ git fetch --all # fetch changes from all remote repos
git pull
Usage
$ git pull origin branch-name # Fetch branch from a remote repository and merge it to local repository.
Using .gitignore
Add the files and directories you’d like git to ignore. These files and directories will not be tracked by git.
Related post : https://stackoverflow.com/a/1139797/7263373