# Git
global info
git remote -v
git branch -v
2
# Git Config
# Basic config
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
2
Write config in ~/.gitconfig
# Custom email depending on repositories clone path
requires git 2.13
If you share your workstation between profesional and personal project, you might want to select from which username and email you commit (+ optionaly you sign-off).
cat ~/.gitconfig
[user]
name = Baptiste Dauphin
[commit]
gpgsign = true
[includeIf "gitdir:~/Git/company/**"]
path = ~/.gitconfig-company
[includeIf "gitdir:~/Git/personal/**"]
path = ~/.gitconfig-personal
[core]
editor = subl -n -w
2
3
4
5
6
7
8
9
10
11
12
13
cat ~/.gitconfig-company
[user]
email = *********
signingkey = ***************************
2
3
4
5
cat ~/.gitconfig-personal
[user]
email = baptistedauphin76@gmail.com
signingkey = 5A040187EDDDD936B41E8268E4577920E02746B3
2
3
4
5
# Test at run time
When you commit, git will concatenate all data from :
.git/config
(repository-wide
config)~/.gitconfig
(user-wide
config)
To test
git config --get-all user.name
git config --get-all user.email
git config --get-all user.signingkey
git config --get-all commit.gpgsign
git config --get-all core.editor
2
3
4
5
6
7
# Git add
Add a file to the index.
The inverse command is git reset
.
git add file
Let's you select only a hunk
of the file.
i.e. add just a part of the file
Interactive mode đ
git add --patch file
2
Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?`
Here is a description of each option:
y
stage this hunk for the next commitn
do not stage this hunk for the next commitq
quit; do not stage this hunk or any of the remaining hunksa
stage this hunk and all later hunks in the filed
do not stage this hunk or any of the later hunks in the fileg
select a hunk to go to/
search for a hunk matching the given regexj
leave this hunk undecided, see next undecided hunkJ
leave this hunk undecided, see next hunkk
leave this hunk undecided, see previous undecided hunkK
leave this hunk undecided, see previous hunks
split the current hunk into smaller hunkse
manually edit the current hunk?
print hunk help
The inverse command of git add
is git reset
.
# Git LFS
Track as early as possible
This means that you should tell LFS to track a file before it's committed to the repository.
Otherwise, it has become part of your project's history - including all of its megabytes and gigabytesâŠ
git lfs track "design-resources/design.psd"
See pattern
matching (not listing files).
cat .gitattributes
design-resources/design.psd filter=lfs diff=lfs merge=lfs -text
2
# Tracking file patterns
git lfs track "*.indd"
git lfs track "design-assets/*"
2
# Getting an overview of tracked files
git lfs ls-files
194dcdb603 * design-resources/design.psd
2
Official docopen in new window
# Git Reset
The git reset command is a complex and versatile tool for undoing changes. It has three primary forms of invocation. These forms correspond to command line arguments --soft, --mixed, --hard. The three arguments each correspond to Git's three internal state management mechanism's, The Commit Tree (HEAD), The Staging Index, and The Working Directory.
Git reset & three trees of Git
To properly understand git reset usage, we must first understand Git's internal state management systems. Sometimes these mechanisms are called Git's "three trees".
# Undo a commit and redo
git commit ...
git reset --soft HEAD^
edit
git commit -a -c ORIG_HEAD
2
3
4
# Git rm
If you are simply not interested in this file anymore, you can use the âgit rmâ command in order to delete the file from the index (also called the staging area).
git rm --cached <file>
When you are done with the modifications, you can simply commit your changes again with the ââamendâ option.
git commit --amend
To verify that the files were correctly removed from the repository, you can run the âgit ls-filesâ command and check that the file does not appear in the file (if it was a new one of course)
git ls-files
<file1>
<file2>
2
3
4
# Git remote
Edit remote URL
git remote set-url origin git@git.baptiste-dauphin.com:GROUP/SUB_GROUP/project_name
# Git Tag
create tag at your current commit
git tag temp_tag_2
By default tags are not pushed, nor pulled
git push origin tag_1 tag_2
list tag
git tag -l
delete tag
git tag -d temp_tag_2
Get the current tag
git describe --tags --exact-match HEAD
# Git Checkout
You can checkout at either a branch, a tag or a commit
git checkout dev
git checkout master
git checkout branch
git checkout v_0.9
git checkout ac92da0124997377a3ee30f3159cdee838bd5b0b
2
3
4
5
Give up all your modifications (i.e. git checkout all the files)
git checkout -- .
# Git Branch
Get the current branch name
git branch | grep \* | cut -d ' ' -f2
# Git pull
git pull
whoops?
Want to go one step earlier (just before git pull ?)
git reset --keep HEAD@{1}
This works because it's the last action on your reference log
đ Check it out :
git reflog show
# Git push
git push
Prévient si tu vas écraser des commits créés entretemps par quelqu'un.
Si tu travailles dans un mĂȘme branch avec d'autres c'est pratique.
git push --force-with-lease
# Git Diff
Specific file
git diff -- human/lvm.md
Global diff between your unstagged changes (workspace) and the index
git diff
Global diff between your stagged changes (index) and local repository
git diff --staged
See what will be pushed
git diff --stat --cached origin/master
git diff master@{3.day.ago} master@{0}
2
# Git commit
# Conventional Commits rules
# Automatic commit with
yarn cz
### Dirty way
If you wanna be a pig you could for commit doesn't validate conventional commits rules with git `--no-verify` option:
```bash
git commit -m "Let me be a pig." --no-verify
2
3
4
# Git hook (pre-commit)
Git hooks are managed by husky
, hooks enabled are in .husky
folder.
- commit-msg : Check commit syntax with commitlintopen in new window tool.
- pre-commit : Generate charts README.md files on all charts under example directory.
- prepare-commit-msg : Use commitizenopen in new window for all commit write (This hook is disabled, you can use yarn cz to write a commit with commitizen help).
# Release process
Setup yarn env:
yarn install
# Git Stash
Extract your work from the index
and workspace
.
git stash save
And put your work back !
git stash pop
To list the stashed modifications
git stash list
To show files changed in the last stash
git stash show
To view the content of an arbitrary stash, run something like
git stash show -p stash@{1}
# Git merge
git pull
= git fetch
&& git merge
# Merge conflicts
In case of conflict when pulling, by default git will conserve both version of file(s)
git pull origin master
git status
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
...
...
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: path/to/file
2
3
4
5
6
7
8
9
10
11
12
13
# keep the local file or the remote file during merge (conflict)
git checkout --theirs /path/to/file
git checkout --ours /path/to/file
2
3
# Undo/move your work
with Git reset and Git stash go at the previous commit. will uncommit your last changes
git reset --soft HEAD^
hide temporary your work in a dirty magic directory and verify the content of it
git stash
git stash show
2
Try to FF merge without any conflict
git pull
put back your work by spawning back your modifications
git stash pop
And then commit again
git commit "copy-paste history commit message :)"
# Override a given side by another
You can tell him that you want your modifications take precedance So, in that case of merge conflict cancel your conflict by cancel the current merge,
git merge --abort
Then, pull again telling git to keep YOUR local changes
git pull -X ours origin master
Or if you want to keep only the REMOTE work
git pull -X theirs origin master
# Git ls-tree
How to retrieve the last modification date of all files in a git repository ?
git ls-tree -r --name-only HEAD | while read filename; do
echo "$(git log -1 --format="%ad" -- $filename) $filename"
done
2
3
# Git Log
# Find commit by author or since a specific date
git log --author="b.dauphin" \
--since="2 week ago"
2
# Find n last commit
git log --author="b.dauphin" \
-3
2
# only print specific info from commits
# author
git log --since="2 week ago" \
--pretty=format:"%an"
2
# hash, author name, date, message
git log --author="b.dauphin" \
--since="2 week ago" \
--pretty=format:"%h - %an, %ar : %s"
2
3
# Show modification of specific commits
git show 01624bc338d4a89c09ba2915ff25ce08174b8e93 3d9228fa99eab6c208590df91eb2af05daad8b40
# See changes to a specific file using git
git log --follow -p -- file
git --no-pager log --follow -p -- file
2
# See commit Signature (GPG)
git log --show-signature
# Git Reflog
git reflog show INFRA-5993@{0}
git reflog show master@{0}
2
# Git Shortlog
Qui a le plus commit ? i.e. qui a la plus grosse ?
git shortlog -s -n --all
# Git Revert
The git revert command can be considered an 'undo' type command, however, it is not a traditional undo operation. INSTEAD OF REMOVING the commit from the project history, it figures out how to invert the changes introduced by the commit and appends a new commit with the resulting INVERSE CONTENT. This prevents Git from losing history, which is important for the integrity of your revision history and for reliable collaboration.
Reverting should be used when you want to apply the inverse of a commit from your project history. This can be useful, for example, if youâre tracking down a bug and find that it was introduced by a single commit. Instead of manually going in, fixing it, and committing a new snapshot, you can use git revert to automatically do all of this for you.
git revert <commit hash>
git revert c6c94d459b4e1ed81d523d53ef81b6a4744eac12
2
find a specific commit
git log --pretty=format:"%h - %an, %ar : %s"
# Git Cherry-pick
I have 2 branches, master
and dev
.
I am on dev branch and I want to cherry-pick 1 commit from master to dev. So I did.
git cherry-pick 125842ac1228c2a2c37b3be4a5ab7681e648a7fb
In case of conflicts it's still possible to keep theirs
or ours
modifications
git cherry-pick 125842ac1228c2a2c37b3be4a5ab7681e648a7fb -X ours
git cherry-pick 125842ac1228c2a2c37b3be4a5ab7681e648a7fb -X theirs
2
# Git Blame
See who
last edited each lines of file.
git blame file
# Git Bisect
Helps you to find the commit that introduced a bug by dicotomy
or bisection
.
division of something into two equal, usually by a line, which is then called a bisector.
The idea behind git bisect
is to perform a binary search in the history to find a particular regression. Imagine that you have the following development history:
... --- 0 --- 1 --- 2 --- 3 --- 4 --- 5 --- current
You know that your program is not working properly at the current
revision, and that it was working at the revision 0
. So the regression was likely introduced in one of the commits 1
, 2
, 3
, 4
, 5
, current
.
You could try to check out each commit, build it, check if the regression is present or not. If there is a large number of commits, this can take a long time. This is a linear search. We can do better by doing a binary search. This is what the git bisect
command does. At each step it tries to reduce the number of revisions that are potentially bad by half.
You'll use the command like this:
git stash save
git bisect start
git bisect bad
git bisect good 0
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[< ... sha ... >] 3
2
3
4
5
6
After this command, git
will checkout a commit. In our case, it'll be commit 3
. You need to build your program, and check whether or not the regression is present. You'll also need to tell git
the status of this revision with either git bisect bad
if the regression is present, or git bisect good
if it is not.
Let's suppose that the regression was introduced in commit 4
. Then the regression is not present in this revision, and we tell it to git.
make
make test
... ... ...
git bisect good
Bisecting: 0 revisions left to test after this (roughly 1 step)
[< ... sha ... >] 5
2
3
4
5
6
It will then checkout another commit. Either 4
or 5
(as there are only two commits). Let's suppose it picked 5
. After a build we test the program and see that the regression is present. We then tell it to git
:
make
make test
... ... ...
git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[< ... sha ... >] 4
2
3
4
5
6
We test the last revision, 4
. And since it is the one that introduced the regression, we tell it to git
:
make
make test
... ... ...
git bisect bad
< ... sha ... > is the first bad commit
< ... commit message ... >
2
3
4
5
6
In this simple situation, we only had to test 3 versions (3
, 4
, 5
) instead of 4 (1
, 2
, 3
, 4
). This is a small win, but this is because our history is so small. If the search range is of N commits, we should expect to test 1 + log2 N commits with git bisect
instead of roughly N / 2 commits with a linear search.
Once you've found the commit that introduced the regression, you can study it to find the issue. Once this is done, you use git bisect reset
to put everything back on the original state before using git bisect
command.
# Submodules
###Â First time First time, clone a repo including its submodules
git clone --recurse-submodules \
-j8 \
git@github.com:FataPlex/documentation.git
2
3
# Daily usage
Update an existing local repositories after adding submodules or updating them
git pull --recurse-submodules
git submodule update --init --recursive
2
# Remove a submodule you need to:
- Delete the relevant section from the .gitmodules file
- Stage the .gitmodules changes git add .gitmodules
- Delete the relevant section from .git/config
- Run git rm --cached path_to_submodule (no trailing slash)
- Run rm -rf .git/modules/path_to_submodule (no trailing slash).
- Commit git commit -m "Removed submodule"
- Delete the now untracked submodule files rm -rf path_to_submodule
##Â Install specific version Check the latest not-release-candidate, so a stable version, on the mirror on github https://github.com/git/git/releases
apt install make libssl-dev libghc-zlib-dev libcurl4-gnutls-dev libexpat1-dev gettext unzip
git clone git@github.com:git/git.git
cd git
git checkout v2.13.7
sudo apt remove git
whereis git
make prefix=/usr/local all -j$(grep -c ^processor /proc/cpuinfo)
sudo make prefix=/usr/local install -j$(grep -c ^processor /proc/cpuinfo)
git --version
2
3
4
5
6
7
8
9