Git notes

Summary

1.Introduction

This is intended to be a help to use and learn git, and this is intentionnaly not verbose to keep it short. If you want more detail about somethings you should be googling it. I’m gonna describe very shortly few notions of git here in case you just started learning about git.
Also, pay attention to what is being said in the console, take your time to read it once.

Caption:
- Any element between ‘<>’ is a variable that you should replace by a string, what you want.
- ‘dangerous’ tag: you should be carrefull when using this command
- ‘shortcut’ tag: you could do this the longer way if you wanted.

Not used to command line ?:
- Git commands start with ‘git’ then a space between each word.
- The character ‘-‘ indicate a short parameter and the character ‘–‘ indicate a long parameter. The difference between ‘-‘ ‘–‘ is just the length of the parameter you will write behind. Both short and long version exist. (--message equivalent to -m)

Commit

It is a set of changes that is packed together into a commit.

Hash

It is a unique identifier for a commit.

Branch

It is a continious ‘line’ of commits.

Remote

The server that everyone can access to share their work.

.gitinore

It is a file, that indicate to git what should be ignored.

Conflict(s)

When git cannot automatically merge changes, you have to merge manually files or choose wich version you wanna keep.

master

The first and default branch on a git repository is called master.

Where you actually are, on wich commit.

Can be a file or directory. Example: ./Git/test or ./Git/test/temp.txt

Look like c49da6a2e459b90b22927658e190cebe29f7f9c5, usually can be changed by HEAD~1 (previous commit) or HEAD~<number_of_commit_to_go_back>.

gitk

This is a graphic interface that come by default, some ‘minimalistic version of sourceTree’.


2.Basic

Stuff you should be knowing because you gonna use it all time.

Log

Display commit history

git log
or
gitk

Status

Display current state of your workspace

It also show what files have changed since the previous commit.
git status
or
gitk

Pull

Get latest work from server

git pull

Get latest work from server for a specific branch

git pull origin <branch_name>

Add

Add your changed files to the next commit

git add <path_to_the_file>
You can check with git status that it worked with your file changing from red to green color.

Add all change to your next commit

git add .

Commit

Create a commit

git commit

Create a commit (shortcut)

git commit -m"<your_commit_message>"

Create a commit (shortcut)

git commit -m"<your_commit_message>"

Push

Put your work on the server

git push

Put your work on the server on a specific branch

git push origin <branch_name>
Create the branch if it does not exist on the server.

Branch

Display on wich branch you are

git branch

Create a branch

git branch <branch_name>

Checkout

Move to another branch

You usually should have all changed commited or stashed (we’ll see stashing later) before changing branch.
git checkout <branch_name>


3.Intermediate

Stuff that you will need often, but that you don’t need to know immediately after starting git.

Merge

Merging a branch to another branch

git checkout <branch_name_A>
git merge <branch_name_B>
You merge B on A.
Will add the commits that only B has on A.
If B has no commit that A don’t have. Then all the commits will be merged individually without any ‘merge commit’.
If B has a commit that A don’t have. Then it will merge all changes and create a ‘merge commit’.
In case you have conflict the merge commit will be done by yourself (git commit -m"Merged branch_B")after resolving conflicts. The ‘merge commit’ will then contains all changes that has been made when merging.

Abort a merge

git merge --abort
The merge never happened.

Rebase

It is another way to merge, that give a more clean history. In short, it will do magic so that it will be like if you started and finished your work before anyone pushed a commit on the branch you want to merge on.
Also, it can be used to rewrite history of commits, to edit them, squash them, and more.
Don’t do rebase on commits that are on the server unless you are sure of what you do.

Rebase on a branch

git checkout <branch_name_A>
git rebase -v <branch_name_B>
This will only modify branch A. -v argument is for verbosity, it will help understand what is happening.
Conflict will be handled commit per commit, this has pros and cons.
When you resolved a conflict, do not use git commit but git rebase --continue instead to move to the next conflict until you finish rebasing.

Abort a rebase

git rebase --abort
The rebase never happened.

Branch

Delete a branch locally

git branch -d <branch_name>
In case the branch has not been fully merged you have to use -D to ‘force’ deletion. (you will use the uppercase version often).
git branch -D <branch_name>

Pull

Get latest work from server with rebase as merge method

git pull origin <branch_name> --rebase
This can be used to keep your feature branch up to date to master branch whitout creating ugly merge commit each time you want to get latest change from master.

Checkout

Create and go on branch (shortcut)

git checkout -b <branch_name>

Diff

Show what changed comparing with previous commit

git diff
If you just wanna know what file have changed instead of what have changed in the files you should use git status.
You could also use gitk.

Compare two commits

git diff <first_commit_hash> <second_commit_hash>

Reset

Remove latest commit(s) but keep their set of changes

Don’t do that if your commit has already been pushed on the server, you would have to force push and only users that are sure of what they do should use that.
git checkout <branch_name>
then
git reset HEAD~<number_of_commit_to_go_back>
or
git reset <hash_fo_commit_to_go_back_to>
This can be usefull when you want to rewrite your(s) commit(s). Like if you want to split the latest commit into three

Remove latest commit(s) from a branch locally (dangerous)

This is a way to remove latest commit(s) from a branch, the option –hard will remove the changes definitely, be sure of what you do.
git checkout <branch_name>
then
git reset --hard HEAD~<number_of_commit_to_go_back>
or
git reset --hard <hash_fo_commit_to_go_back_to>
Note that the commit correponding to the hash you provide will be kept.

Init

Create repository

git init


4.Advanced

Stash

Keep your WIP in a ‘temporary’ place, not a commit

git stash
This will keep all your changes (except files not follow by git, like file waiting to be added), in the ‘stash’. It is quite similar to a commit without being a commit. It can be used for WIP change that you don’t want to commit. You should prefer commit when possible (if you reset the commit later).

Show stashed set of changes

git stash list
Because you can have many stashed set of changes in the stash.

Apply stashed changes

git stash apply
Will apply latest stashed set of changes.

Branch

Delete from server

git push origin --delete <branch_name>

Force push your changes (dangereous)

git push origin <branch_name> --force
This will overwrite the server and might create lot of problem for the others users, use with caution.

Fetch

Get latest changes from server without applying them on your branch(s)

git fetch
or specify a branch
git fetch origin <branch_name>
If you then do git merge origin/<branch_name> you will have done the same work as a git pull origin <branch_name> in two commands.
Fetching is usefull to look/download the server version of your project/branch without changing you local version. If you use github or similar you probably won’t need it that much.

Rebase

Rewrite history of one or many commits

Don’t do that if the commits are already on the server, since it will change the hash of the commits, the server will take them for new commits. Unless you can safely overwrite the branch on the server (overwrite mean you know what you’re doing).
git rebase -i <commit_hash>
Will rebase back to this commit excluded.

Checkout

Keep your work on a conflict

If you are using merge:
git checkout --ours <path>
If you are using rebase:
git chekcout --theirs <path>
Avoid using git checkout --ours . (or --theirs) because it will be applied to everything included non conflicting file.

Keep the other work on a conflict

If you are using merge:
git checkout --theirs <path>
If you are using rebase:
git checkout --ours <path>
Avoid using git checkout --ours . (or --theirs) because it will be applied to everything included non conflicting file.

Reset a directory/file to an anterior version

git checkout <commit_hash> -- <path>

Diff

View diff for a specific path

git diff <commit_hash> <path>

View diff with only name of files

git diff <commit_hash> --name-only

Settings/level_design.json
TowerDefense/Config.hpp
TowerDefense/ExternalConstants.hpp

View diff statistics

git diff <commit_hash> --shortstat

1 file changed, 3 insertions(+), 1 deletion(-)

Cherry-pick

Take a commit for anywhere to place it here

git cherry-pick <commit_hash>

Log

Log history of commit with file name modified

git log --name_only
or more verbose
git whatchanged
or only modified files
git diff-tree --no-commit-id --name-only -r

Git log ‘compressed’

git log --oneline

View log statistics

git log --shortstat
or
git log --shortstat --oneline

Log server branch

git fetch
git remote -v
or for a specific branch to log:
git log origin/<branch_name>
or
git log <remote_name>/<branch_name>
where remote_name can be the github repo url.

Revert

Cancel a commit without deleting it

git revert <commit_hash>
This will not delete the commit, but will create another commit reverting the changes that has been made. This is usually used for commit that are already pushed on server.

Tags

Tag current commit

git tag <your_tag>

Push your tag on the server

You only need to do that if you have already push the commit that has the tag.
git push origin <tag_name>

Push all tag that you have locally on the server

git push --tags
This is not recommended (todo why ?).

Move tag to another commit

git tag -d <tag_name> <commit_hash> (default hash is current commit)
git push origin <tagname>

Clean

Show what file will be remove

git clean -n

Remove untracked files

git clean -f
Will remove all files that appear in red and are not tracked by git when doing git status.
git clean -fd
Will remove all files and directory that appear in red and are not tracked by git when doing git status.
git clean -fdx (dangerous)
Will remove all files and directory that appear in red and are not tracked by git when doing git status and all files ignorted by .gitignore

Bisect

Search for origin of bug

Take a look at the documentation, but here is a quick reminder:
git bisect start
git bisect bad
git bisect good


5.Occasional

Stuff you will only use occasionaly.

Merge all changes from another branch as a single commit

git merge --squash <feature branch>
git commit
- https://stackoverflow.com/questions/3697178/merge-all-changes-from-another-branch-as-a-single-commit

Reset local repository branch to be just like remote repository HEAD

git fetch origin
git reset --hard origin/master
- https://stackoverflow.com/questions/1628088/reset-local-repository-branch-to-be-just-like-remote-repository-head#1628334

Get history of a file

gitk --follow [filename]
https://stackoverflow.com/questions/278192/view-the-change-history-of-a-file-using-git-versioning

Merge work on previous commit

git commit --amend

Change remote url

git rebase --continue do not work

Sometimes when you have an ‘empty conflict’ you need to use git rebase --skip.

Move a branch

git checkout <branch_name_to_move>
git rebase --onto <branch_name_to_be_parent>

Before any of the given operations your repository looks like this

           o---o---o---o---o  master
                \
                 x---x---x---x---x  A
                                  \
                                   o---o---o  B

After a standard rebase (without --onto master) the structure will be:

           o---o---o---o---o  master
               |            \
               |             x'--x'--x'--x'--x'--o'--o'--o'  B
                \
                 x---x---x---x---x  A

…where the x' are commits from the A branch. (Note how they’re now duplicated at the base of branch B.)

Instead, a rebase with --onto master will create the following cleaner and simpler structure:

           o---o---o---o---o  master
               |            \
               |             o'--o'--o'  B
                \
                 x---x---x---x---x  A

View history of commands

history
Example:

  501  26/02/18 10:45:22 echo "hello world"
  502  26/02/18 10:45:26 git commit -am"Adding new player"
  503  26/02/18 10:46:35 history

Add date to history of command, permantely

In C:\Users\<user_name>\.bash_profile add export HISTTIMEFORMAT="%d/%m/%y %T ", save and restart bash console.

View history of git

git reflog --all
Example:

386b760 (HEAD -> temp) HEAD@{0}: checkout: moving from master to temp
7865cdd (master) refs/heads/master@{0}: commit (merge): merged success
7865cdd (master) HEAD@{1}: commit (merge): merged success

Save it into a txt file

history > history.txt or/and git reflog --all > reflog_all.txt
Note that it will replace any file with the same name without warning.

Get commit per person on a defined time

git shortlog -s -n --since="24-Nov-2016" --until="16-Jan-2017"

69  Matthias
57  ambroise
36  Rafired
24  Valefors
22  Victor g
2  killico

View history of a file

gitk <file_name>

Log by author

git log –author=”ambroiseRabier”

Search in a commit message

git log --grep="<search>"

Log with statistic +/-

git log --stat

 .gitignore                                         |    3 +
 Libs/SFML/doc/html/AlResource_8hpp_source.html     |  102 -
 Libs/SFML/doc/html/Audio_2Export_8hpp_source.html  |   97 -

or if you want to separate line deleted from line added:
git log --numstat --oneline

Diff with statistic +/-

git diff --stat <commit_hash> <commit_hash>

Filter diff by type of change

--diff-filter=[ACDMRTUXB*] # A for added, m for modified, etc

Loop over branch (shell script)

#!bin/bash
echo "Starting..."
for branch in $(git for-each-ref --format='%(refname)' refs/heads/); do
    echo "$branch"
done

View all users

git shortlog -sn
or
git log | grep Author: | sort | uniq
or
git shortlog -sn | grep -oP '[^\d\W]\w+'

Loop over all users

This method is imperfect, it do not support space in usernames.

#!bin/bash
echo "Starting..."
for user in $(git shortlog -sn | grep -oP '[^\d\W]\w+'); do
    echo "$user"
done

Get number of log per user excluding merges

git shortlog -sn --no-merges

Log all merges

git log --merges

More lisible git log

git log --graph --decorate

Limit git log

git log -3
Will log 3 commit max.

Filter git log by name

git log -- <file_name>

Fitler git log by content

git log -S"<search_string>"

Gain space on your disk

git gc
It run garbage collector, no risk. check the size of your repository before and after to know how frequently you should use it. There are options to have a more aggressiv cleaning, at your risk.

Commit and add modified file (shortcut)

git commit -am"<commit_message>"

Remove a file from all commits (very dangerous)

In the case you have leaked your passwords on the repository on github. Or if you have put some heavy files by mistake on the repo a long time ago.
It can rewrite history of the whole git repository. Others people will probably have to re-download the entire git repo after to be synchronised.
It the github documentation it is called “nuclear option”.
git filter-branch

Change origin of a repository

If you need to change from github to gitlab or to bitbucket for example.
git remote set-url origin <git://new.url.here>

Push not everything

git push origin <commit_hash>:<branch_name>

Rename branch

git branch -m <old_name> <new_name>
git branch -m <new_name> (current branch will be renamed)