Moonshake's site

Git Notes

Table of Contents

Definitions

Commit

of a project content in al particular time. It contains a tree at that revision and a reference to his parent(s) commit.

Branches

Parallel lines of development.

Branch head

A head that reference the last commit of a branch.

HEAD

Special symbol typically used to refer to the current branch head (in a non-detached1 mode); you can see the content of head in .git/HEAD file.

Reachable commits

Reachable commits from commit X are all ancestors from X (parents, grandparent, and so on …).

Tag

Like heads are references into project’s history, but the main difference is that tags are expected to always point at the same version of a project, while heads are expected to advance while development is in progress.

Index

Just a file (.git/index) that stores the tree needed to create a new snapshot. In a higher level you can think about the index as a staging area.

Blob

Just stores file content.

Tree

Consist of blobs and other subtrees to conform a directory structure.

Tag object

Symbolically identifies and can be used to sign other objects.

Git object

Either a blob, tree, commit or tag. Every commit has a 40-hex digit id called “object name” or “SHA1 id”.

Object database

All the data related to git objects in a repo, they can be found in .git/objects.

Commands

git reset

Moves the head of a branch (destructive command, use carefully)

Examples

To go back to previous commit before merge (delete merge commit).

git reset --hard ORIG_HEAD

git show

Shows the most recent commit on the current branch (in non detached mode), in detached mode apparently shows the commit whose HEAD is pointing to

git clone

Clone the content of a repo into a directory. Clone can be downloading from internet (the typical use case) or syncing from a local path – when using a bare repository in localhost for instance.

Git creates the following branches when using git clone command.

  1. A master branch from HEAD in the remote repo.
  2. A remote branch for each of the branch in the remote repo that can be updated using git fetch or git pull (this branches can be retrieved using git branch -r command)

git merge

This command is typically used in a context where there are divergent branches that you want to merge in a new commit. Or when you want to “update” a local branch head with his remote counterpart, for example using git pull.

Examples

Suppose the following tree of revisions.

* c575639 (HEAD -> master) added file4.txt
* 0a55977 updated f1 and added f2
| * d475e54 (dev) added f5
| * 3304a47 added file3.txt
|/  
* 0b0496a added file1.txt

Then, you can do git merge dev to merge the dev branch into master branch. After executing the previous command you should expect the following output to save a new message for the merge commit in you preferred editor.

Merge branch 'dev'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.

After the merge the new tree should look like the following.

*   1efbbb9 (HEAD -> master) Merge branch 'dev'
|\  
| * d475e54 (dev) added f5
| * 3304a47 added file3.txt
* | c575639 added file4.txt
* | 0a55977 updated f1 and added f2
|/  
* 0b0496a added file1.txt

(Note that the current branch head is moved to the new merge commit.)

Sometimes, divergent branches change the same file generating a ‘merge conflict’.

Notes

git merge-base

Find common ancestor.

git log

List commits from a parent.

Examples

Commits not including v2.5 ancestors.

git log v2.5..

Commits that are ancestors of test but not master.

git log test.master

Commits from last 2 weeks.

git log --since="2 weeks ago"

Commits that touch file Makefile

git log Makefile

To show commits that touch unmerged files between merging branches

git log --merge

All commits from master branch.

git log master

All reachable commits by master branch but not dev branch.

git log master ^dev

All commits in master but not in dev that touch path/to/file

git log master ^dev -- path/to/file

Commits that match a regex string in its commit message (it match against the whole message not just the title).

git log --grep="test"

Look for git history (patch text) that contains a given regex pattern;

git log -S <regex>

git diff

Show the difference between files in different snapshots.

Example

Diff between working tree and index.

git diff <path>

Diff between the index and commit (HEAD, when omitted).

git diff --cached <path>

Diff between working tree and commit.

git diff <commit>

git diff <commit> <commit> -- path

Notes

Examples

Diff between two commits

git diff master..test
git diff master test

Changes between test and the merge base commit of test and master this is a shortcut for git diff ${merge-base master test} test.

git diff master...test

git rm

Always use git rm instead of rm on tracked git files.

git show

Show info related to git object, typically is used to view the content of file in previous versions.

Examples

Show the content of the blob/file locks.c in a commit referenced by version v.25.

git show v.25:fs/locks.c

Typically if u use git show with a commit it outputs the diff of the files modified, added, etc. But sometimes you just want to know what are the files touched by a particular commit without getting the huge diff output. In this case you can use the beneath command.

git show --compact-summary <commit>

git revert

Revert the changes made in commit HEAD~1; revert basically fix a mistaken commit with a new commit.

git revert HEAD~1

git restore

To use HEAD~6 version of path/to/file2.

git restore --source=HEAD~6 path/to/file

git rebase

It applies a set of patches3 on top of another branch to maintain a linear history.

git rebase is used to maintain the history of commits simpler without any merge commit.

Before rebase.

 o--o--O--o--o--o <-- origin
        \
         a--b--c <-- mywork

After rebase.

git switch mywork
git rebase origin

 o--o--O--o--o--o <-- origin
                 \
                  a'--b'--c' <-- mywork

Notes

Note that you can use git mergetool to manage rebase conflicts, then you finish the rebase with git rebase –continue and saving the new commit.

If you want to do a rebase but with some changes like:

Use git rebase -i.

git cherry-pick

Select arbitrary commits to create a new commit.

Revisions

A revision can be:

Single revision

@ notation

@ is a shortcut for HEAD, for example.

git switch --detach @~3
{n} notation

master@{3} is the third previous commit where master branch head pointed to.

^n notation

HEAD^2 is the parent number 2 of HEAD.

Also HEAD^1 is equal to HEAD^.

~n notation

HEAD~2 ancestor number 2 (always first parent).

HEAD~1 is equal to HEAD~.

HEAD~4 is equal to HEAD^1^1^1^1.

: suffix notation

master~2:README shows the blob README.

Range revision

Use a single revision in this context means all the commits reachable from the commit referenced by the single revision.

^ not notation

Objects reachable from master, but exclude the ones reachable from branch.

master ^branch1

.. notation

dev..master is a shortcut for ^dev master

... notation

dev...master all commits in master and dev but not in git merge-base --all dev master.

Misc


  1. HEAD is detached when points a commit that isn’t a branch head. ↩︎

  2. The difference between using this command and doing a git checkout HEAD~6 -- path/to/file is that checkout automatically add path/to/file to staging area. ↩︎

  3. This patches are present in one branch but not in the other, for example if some patch is present in both branches git rebase don’t duplicate the patch. ↩︎

  4. In fact this name and path’s relatives to ref can be found in .git/ref↩︎

  5. By default Git stores reflogs for 30 days. ↩︎

  6. Apparently this logs are stored under .git/logs/refs↩︎