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 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.
$ add-apt-repository ppa:git-core/ppa
$ sudo apt update
$ sudo apt install git
Initialise Git repo
$ cd ~/Desktop
$ mkdir git-tutorial
$ cd git-tutorial
$ git init
.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 'email@example.com’
Install Atom or Sublime Text Editor
$ sudo add-apt-repository ppa:webupd8team/atom
$ sudo apt update
$ sudo apt install atom
$ 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"
$ 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
$ git add <file1> <file2> <file3>
$ git add *.txt
$ git add --all
$ git add .
- Untracked files
- Tracked files
git addstages 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.
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 diffshows 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”.
It is used to undo add
$ 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
Commit is like a snapshot in time. We can return back to this commit anytime in future.
$ 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 prints nothing for Untracked files.
$ 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
$ 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
Author: RohanBh <firstname.lastname@example.org>
Date: Fri Jan 19 11:23:57 2018 +0530
Complete the more section
Author: RohanBh <email@example.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 <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 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.
- When we commit in a Detached HEAD state, the commits do not belong to any branch and are thus lost.
$ 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 # 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 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
$ 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 —
.gitcan be omitted.
$ git push origin branch-name # push local changes to remote branch
$ git push -f origin branch-name # force-push local changes
$ 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 origin branch-name # Fetch branch from a remote repository and merge it to local repository.
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