Advanced Git Tips and Tricks
Improve your daily workflow.
Supporting with GUI tools (know how to read the graphs). GUI tools are always limited.
Recommendation: Use the command line tool to learn use git and its advanced concepts.
Git Fundamentals
Mandatory to understand these concepts:
- Commits
- Snapshots
- References
Object Model: It is the foundation of Git that uses the three concepts before.
When I commit changes:
- Git creates a Commit Object (Object Model). It contains a Reference to its parent, the author and a timestamp.
- A snapshot is a representation of the state of the directories and files in the repository at the time the Commit was made.
- Internally the directory is represented by Git using an object called a Tree (which contains other Trees and Blobs).
- Internally every object in Git (commit, tree, blob) has a unique ID (SHA-1 hash of its object's contents)
- Reference is the user-friendly naming used by Git to easy its use.
- In Git there are three types of References: Tag, Branch, HEAD
- Tag is a fixed reference to a specific commit. Never changes. It is used as a Mark. to points a certain version in the repository.
- Branch is a reference to the latest commit in the line of history. With every commit, the branch reference is updated to point to it. Its history is recreated from latest commit to track backwards.
- HEAD is a special reference managed by Git to keep track of the branch or the commits.
Git - Command Line
In Windows
Git from PowerShell. Install a module called posh-git. Clone it from Github. Install it from a PowerShell command.
git clone https://github.com/dahlbyk/posh-git.git
cd posh-git
.\install.ps1
Import-Module posh-git
Import-Module from Windows PowerShell could throw an error.
Import-Module : No se puede cargar el archivo C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\PsGet\PsGet.psm1
porque la ejecución de scripts está deshabilitada en este sistema. Para obtener más información, vea el tema
about_Execution_Policies en http://go.microsoft.com/fwlink/?LinkID=135170.
This is fixed by executing:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
Now:
PS C:\ISBAN\workspaces\git-architecture\posh-git> Import-Module PsGet
PS C:\ISBAN\workspaces\git-architecture\posh-git> Import-Module posh-git
PS C:\ISBAN\workspaces\git-architecture\posh-git> .\install.ps1
C:\ISBAN\workspaces\git-architecture\posh-git [master ≡]>
Aliases (git config)
These are shortcut for Git commands useful for accelerate tool management.
Examples (one command):
git config alias.mialias status
# Means
git mialias
git config --global alias.miglobalalias status
# Means
git miglobalalias
Where they are located: cat .git/config | grep -A 1 "\[alias\]".
There are commands which applies to Repo, User or System level. Where the aliases are located using --global option is: ~/.gitconfig.
Examples (more than one command and options):
git config --global alias.qm '!git checkout $1; git merge @{-1}'
git config --global alias.qm
# A serie of commands
git co work
echo "Here" >> nuevo.txt
git cma "Mas cambios"
git qm master
Aliases are used spreadly because simplify command execution in few steps.
Formatted and Pretty logs
Using git log
command.
http://git-scm.com/docs/pretty-formats
Examples:
$ git log --pretty=oneline
$ git log --pretty='%h | %d %s (%cr) [%an]'
# Using colors
$ git log --pretty='%Cred%h%Creset | %C(yellow)%d%Creset %s %Cred(%cr)%Creset %C(cyan)[%an]%Creset'
# Using tree graph
$ git config --global alias.lg "log --pretty='%Cred%h%Creset | %C(yellow)%d%Creset %s %Cred(%cr)%Creset %C(cyan)[%an]%Creset'
--graph"
diffs
Based on Unified Diff Specification.
First configure Git to limit pagination in command results (avoid press q all the time).
$ git config --global core.pager 'less -RFX'
# Where core.pager is a command to setup pagination, F and X tells less to exit immediately
# if the output fits in a single screen. R option is for raw output. S option to wrap text line
When just a part of a line was modified, we need to tell Git to show only that difference.
git diff --word-diff
By default diff shows only 3 lines after and 3 lines after the difference found. To change that,
git diff --word-diff --unified=10
##
git config --global alias.dp 'diff --word-diff --unified=10'
git dp
Git uses different diff algorithms.
# It takes its time to find the complete block added, deleted, etc, instead of do it separately
$ git diff --patience
# Used to make a more readable/understandable format
$ git diff --histogram
# Or added to the config to apply all commands
$ git config --global diff.algorithm histogram
$ git diff
diff in commits
Showing differences in commits (snapshots) between the commit referenced and its parent
# Show head diff
$ git show head
# Show head parent parent
git show head~2
# Show pretty formated
git show head --pretty='parent %p commit %h %d %n%n%w(72,2,2)%s%n%n%w(72,0,0) %an %ar'
# Show with alias
git config --global alias.so "show head --pretty='parent %p commit %h %d %n%n%w(72,2,2)%s%n%n%w(72,0,0) %an %ar'"
git so head
# Show without metadata (diff area)
git show head --no-patch
# Show a simplified metadata
git show head --stat
Git could show information about: Tree / Blob / Commits
# Low-level content, plumbing, raw content of the object pointed by the specific reference (commit)
git cat-file -p head
# Using the sha-1 of the tree object got in previous command
git cat-file -p 9f4545
# Using the sha-1 of the blob object got in previous command
git cat-file -p 9fbbd
# This blob object does not contain diff content, it shows only file content
Delta chains: Git only stores (in storage subsystem) delta chains calculated on the fly when comparing commits.
Diffs between commits using ..: Using git diff head..head~2 --stat
Diffs between files: Using git diff head~3:README.md..head:README.md
Using diff with command line is not compared using GUI.
References
https://app.pluralsight.com/library/courses/git-advanced-tips-tricks/table-of-contents