Skip to content

Instantly share code, notes, and snippets.

@hansrajdas
Last active October 3, 2021 08:58
Show Gist options
  • Save hansrajdas/20767bbc1ac3350580090e218b37b756 to your computer and use it in GitHub Desktop.
Save hansrajdas/20767bbc1ac3350580090e218b37b756 to your computer and use it in GitHub Desktop.
git versioning

Version control systems(VCS)

  • Local VCS: Files stored on local machines
  • Centralised VCS: A centralised system where the main repository is stored. Eg: CVS, SVN, Perforce
  • Distributed VCS: Each client doesn't just check out the latest snapshot of the files; rather, they fully mirror the repository, including its full history. Eg: Git, Mercurial, Bazzar.

Other VCS like CVS, SVN, Bazzar stores delta changes after every commit(in each version of project), instead git stores snapshots of projects in every version(some file may have reference to previous, if that file was not updated)

Everything is local

  • Git is fast as everything is local in git. While working other repository systems like SVN and CVS we need to be connected to the server to commit anything but with git we can commit locally also and when connected to the server we can push the changes.
  • Also we can see the history of the project as it stores everything on local drive

Uses SHA-1(40 character string 0-9 and a-f) for integrity

3 stages of files in git

  • Modified: Locally modified
  • Staged: Will be committed in next commit, using git add
  • Committed: When file is committed using git commit command

Set globals

Git global variables, will be used in each commit

git config --global user.name "Hansraj Das"
git config --global user.email "hansrajdas@gmail.com"
git config --global core.editor vim
git config --list

Getting git repository

Two methods to get a git repository on our local machine

Initialise any directory to git using init command
git init
Clone existing repository
git clone <url> <optional destination path>

Git file status

  • Tracked: Known to git, was present in last snapshot
  • Untracked: Unknown to git, need to add this file in git
git status -s    # Show short status
git status       # Show detailed status

git add

This command serves 2 purpose

  • Adds any untracked file to git workspace
  • Also adds already tracked and modified file to staging area so that it will be committed in next commit
git add <file(s)>

git diff

This command is used to see difference in repository

git diff             # Diff of working(local) directory and staging area
git diff --staged    # Diff of staged changes and last commit
Diff between 2 commits for all or for specific files
git diff <commit-hash-1> <commit-hash-2> <file(s)>
Diff between working copy(local changes included) and given commit
git diff <commit-hash> <file(s)>
Diff between last commit(local changes not included) and given commit
git diff <commit-hash> HEAD <file(s)>

git commit

Commit modified files, below command opens an editor to accept commit message
git commit -a
Commit all modified files
git commit -am "<commit-message>"
Commit files which are in staging area
git commit -m "<commit-message>" <file(s)>

git log

Can be used to view to see logs/commit messages of a repository

git log              # View detailed all log of project
git log <file/dir>   # Logs specific file/dir
git log -n           # Last n logs
git log -p           # View all logs with diff (-p or --patch)
git log -p -n        # View last n commits diffs with log
git log -p -n <file> # View last n commits diffs with log for specific file(s)
git log --stat       # Log with number of lines inserted/deleted in files
git log <branch>     # Show log for a specific branch(if not on that branch)
git log --graph      # Show ASCII graph of branch and merge history

Other log formats

Short/full option
git log --pretty=<oneline|short|full|fuller>
Print logs and information as per requirement
git log --pretty=format:"%h by %an, %ar: %s"

# %h: Short commit hash
# %an: User name
# %ar: How much time ago
# %s: Commit message
# Other options can be used...
Filters on basis of commit msg
git log --grep="<search in commit msg>"
Logs which updated a specific code like version number, function name
git log -S "<code diff>"  # Searches diff
All commits by hansraj in the month of october

Any complex query is possible

git log --author=hansraj --since="2008-10-01” --before=”2008-11-01"

# --since and --until: Time limit logs
# --no-merges: Without merge commits
Decorate

In git HEAD is pointer to the local branch(like master, etc...) we are currently on

git log --oneline --decorate                # See where HEAD is pointing to and other details
git log --oneline --decorate --graph --all  # Show logs with diversion history(where branches diverged)

Branching

Branch is a new pointer to a commit

List branches

git branch              # List branch names
git branch -v           # List last commits in each branch
git branch --merged     # List branches merged to current branch
git branch --no-merged  # List branches not merged to current branch

Create new branch

From head of current branch
git checkout -b <new-branch>  # Create and switches to new branch from head of current branch
git branch <new-branch>       # Create a new branch, don't switch to that branch
git checkout <branch-name>    # Switch to other branch
From older commit hash

Creates and switches to new branch from current branch not from HEAD(latest) but from some specific previous commit on current branch. This is useful for undoing things

git checkout -b <new-branch> <commit-hash>
From remote branch

Start a new local branch serverfix from origin/serverfix, we can have different local branch name than on remote

git checkout -b serverfix origin/serverfix
Same local branch name

Create local branch with the same branch name as on remote

git checkout --track origin/serverfix

Delete branches

Gracefully
git branch -d <branch-name>

Note: Branch that is not yet merged to current will give an error while deleting with -d flag. We can delete those branches forcefully

Forcefully
git branch -D <branch-name>

Undoing things

Re-commit(amend)

This will not create a new commit log but update the last commit with this one, we modify files and commit messages in this re-commit. We end up with a single commit - the second commit replaces the results of the first

git commit --amend
git commit --amend -m "Updated commit msg"

git checkout

Discard the local changes and get the last committed version of file(s)
git checkout -- .         # All changes
git checkout -- <file(s)> # For specific files
Checkout a specific version of file(s)
git checkout <commit-hash> -- <file(s)>
Checkout one version previous to specific version of file(s)
git checkout <commit-hash>~1 -- <file(s)>

git reset

Unstage file

If we don't want to commit changes done in a file but accidentally added this file to staging area, this command can be used to unstage this file

git reset HEAD <file/dir>
Soft reset

Moves head of file(s) to commit-hash and changes from commit-hash to old HEAD to staging head(shown as green in status)

git reset --soft <commit-hash> <file(s)>
Mixed reset

Moves head of file(s) to commit-hash and changes from commit-hash to old HEAD to un-staging head(shown as red in status)

git reset --mixed <commit-hash> <file(s)>
Hard reset

Totally removes all commits and moves head to given commit hash

git reset --hard <commit-hash> <file(s)>

Note: Git reset command also removes commit logs so not recommended

git revert

git revert HEAD    # Revert last commit
git revert HEAD~n  # Revert last nth commits

Revert all changes done from commit-hash-1 to commit-hash-2(excluding commit-hash-1)

git revert <commit-hash-1>..<commit-hash-2>

Note: revert creates new revert commits for each commit reverted

Working with remotes

On git clone <url>, apart from local master branch a remote branch is also created called origin/master where origin is default remote name

git remote

List remotes

Lists remotes configured with URL, git clone command adds origin remote implicitly

git remote -v
Remote mapping

Lists which tracking branch is setup on each local branch

git branch -vv
Add remote
git remote add <shortname> <url>  # Add remote explicitly
git branch -u origin/serverfix    # Set up upstream of the current branch to origin/serverfix
Show information about a particular remote
git remote show <remote>
Rename a remote name
git remote rename <existing remote> <new remote>
Remove a remote
git remote rm <remote-name>
Change remote URI
git remote set-url origin https://github.com/user/repo2.git  # Change the 'origin' remote's URL

git fetch

Fetches new changes from remote to local working dir and moves origin/master to its new position. fetch only fetches the changes and does not merges it to local branch

git fetch                # Fetch changes from default remote
git fetch <remote-name>  # Fetch changes from given remote-name

git pull

Automatically fetch and then merge(pull uses merge strategy not rebase) the remote branch into current local branch. Git clone automatically sets the local master branch to track the remote master branch

git pull

git push

git push                    # Push current branch changes to default upstream(like origin)
git push <remote> <branch>  # Push current branch changes to upstream, to specific branch on a specific remote
git push origin --delete serverfix  # Delete reference to `serverfix` on remote

git tagging

git tag               # List all tags
git tag -l "1.1.0.*"  # List all tags which has 1.1.0*

Tag types

Annotated tag

Permanent tag, stores a lot of information, use -a flag

git tag -a v1.0 -m "My first tag"  # Create annotated tag
git show v1.0                      # Show details of tag v1.0
Lightweight tag

Stores less info, don’t use any flag

git tag v1.0-lw   # Create a lightweight tag
git show v1.0-lw  # Show tag info

Tag previous commit

Create a tag on given commit hash

git tag -a v1.2 <commit-hash> -m "<Tag msg>"

Sharing tags

By default, tags are not shared to the server with git push, we have share tags explicitly

git push <remote> <tagname>  # Push a specific tag to server
git push <remote> --tags     # Share all tags created to server

Tag checkout

Checks out code from given tag

git checkout <tagname>

As we cannot commit on tag we will have to create a branch from tag to commit changes

git checkout -b <branch-name> <tagname>

Tag delete

git tag -d <tagname>

git aliases

Create an alias of git simple/complex commands

git config --global alias.br branch           # To create alias of `git branch` to `git br`
git config --global alias.last 'log -1 HEAD'  # Get last commit info with `git last`

git merge

Merges the changes from branch-name to current branch we are currently in

git merge <branch-name>
  • If both branches have common ancestors, merge is done in fast forward way as it simply changes the commit pointer of current branch to branch-name commit pointer
  • If both branches don't have common ancestor, three-way merge is done which creates a new commit to which current branch now points. This new commit is also called as merge commit and has 2 parents(one where the current branch was initially pointing and other where branch-name was pointing)

Merge conflict

  • We may get merge conflict when the same line is updated in current and branch from which we are merging, gives error Automatic merging failed. Files not merged can be seen using git status
  • In this case we have to open each file and resolve conflicts, when resolved run git add <file-name(s)> to marked as conflict has been resolved and can be committed
  • git mergetool Opens the diff(local and other branch file) in an editor to resolve conflict(s)

git rebase

git rebase master  # Rebases current branch with the changes done in master
  • Both rebase and merge command works to sync multiple branches. Rebasing is preferred on remote branches instead of merge to have cleaner log history
  • Rebasing replays(takes diff and applies) changes from one line of work onto another in the order they were introduced, whereas merging takes the endpoints and merges them together
  • Rebasing first moves pointer of current branch to new reference then creates new commits of the changes done in current branch so it is preferred in local branch and not on shared branches like master
  • Below command - Take the client branch, figure out the patches since it diverged from the server branch, and replay these patches in the client branch as if it was based directly off the master branch instead. Ultimately updates the client branch
git rebase --onto master server client

git cherry-pick

Used to merge specific commits only, not whole branch

git cherry-pick <commit-hash>  # Merge changes committed in `commit-hash` to current branch

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment