top
upGrad KnowledgeHut SkillFest Sale!

Search

GIT Tutorial

Git objects are the metadata stored under .git/objects repository. There are 4 types of git objects:Git commit, git trees, git blobs and git tags.Each commit object is uniquely identified by a git hash code (SHA-1).Every commit made creates a new commit object that stores a reference to the tree object, blob files, and tags if any.Refer: git commit object diagram1. Git HooksHooks are the metadata objects in the .git directory created at the time of ‘git init .<directory>’ command.These scripts are like triggers that get executed pre or post an action or event; such as a command run.Every git repository comes installed with prebuilt hooks scripts in the .git/hooks directory; that a user can edit as per the project’s requirement.There are two groups of these hooks: client-side and server-side.Client-side hooks:These are hooks installed and maintained on the developers local repository and are executed when events on the local repository are triggered, such as commit and merge and rebase.Server-side hooks:These hooks installed on Server on network operations such as receiving pushed commits.Project: hooksProjhooksProj [master] $ls -1 .git/hooks/ applypatch-msg.sample commit-msg.sample fsmonitor-watchman.sample post-update.sample pre-applypatch.sample pre-commit.sample pre-push.sample pre-rebase.sample pre-receive.sample prepare-commit-msg.sample update.sampleTo enable a hook script, rename the script to the same name truncating the .sample extension.However if you write your own hook scripts, write it in Shell language and place it under .git/hooks folder of your project and make them executable as :git chmod +x <script_name>Scripts are listed in the order of their execution.hooks [topic] $ls -1 *commit* pre-commit prepare-commit-msg commit-msg post-commitCurrent project state:hooksProj [topic] $git status On branch topic Changes to be committed:  (use "git reset HEAD <file>..." to unstage) deleted:    READMEStep 1: Commit the above project snapshothooksProj [topic] $git commit -------------------------------------------- Step 1: Running .git/hooks/pre-commit script. WARNING!!! Aborting the commit. Found Deleted files in the Staging area. README‘pre-commit’ hook fails.‘pre-commit’ script runs a test before making a commit#Aim: Check for any Deleted file in the staging area, if any it stops you from committing this snapshot.Step 2: Reset the project back to HEAD commit and add/modify any file(README).[topic] $git status On branch topic Changes to be committed:  (use "git reset HEAD <file>..." to unstage) modified:   READMEAdd files to staging area and commit:git commit--This opens up the editor:Add date in README. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch topic # Changes to be committed: #       modified:   README # ISSUE#7092‘prepare-commit-msg’ hook:#Aim: Appends the commit message and display the list of staged files that were committed.Step 3: Remove the line ISSUE# while saving the message.hooksProj [topic] $git commit -------------------------------------------- Step 1: Running .git/hooks/pre-commit script. [OK]: No deleted files, proceed to commit. -------------------------------------------- Step 2: Running .git/hooks/prepare-commit-msg script. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch topic # Changes to be committed: # modified:   README # ISSUE#7092 Enter your commit message here. README -------------------------------------------- Step 3: Running .git/hooks/commit-msg script. [NOK]: Missing  an ISSUE number in the message Commit-msg’ hook script fails.#Aim: Reads the commit log message for ISSUE#.Step 4: commit again keeping the ISSUE# in the commit message.hooksProj [topic] $git commit -------------------------------------------- Step 1: Running .git/hooks/pre-commit script. [OK]: No deleted files, proceed to commit. -------------------------------------------- Step 2: Running .git/hooks/prepare-commit-msg script. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch topic # Changes to be committed: # modified:   README # ISSUE#7092 Enter your commit message here. README -------------------------------------------- Step 3: Running .git/hooks/commit-msg script. [OK]: Commit message has an ISSUE number -------------------------------------------- Step 4: Running .git/hooks/post-commit script. New commit made: b33401b Edit README file. ISSUE#7092 [topic b33401b] Edit README file. ISSUE#7092 1 file changed, 1 insertion(+)post-commit’ script triggered after the commit was made.Aim# To trigger a report on the latest commit made.Step 5: All the 4 pre and post commit scripts exited with success status, commit made.hooksProj [topic] $git hist * b33401b 2019-01-29 | Edit README file. ISSUE#7092 (HEAD -> topic) [divya bhushan] * e0a4db8 2019-01-26 | Add README [divya bhushan]‘pre-rebase’ hook:The pre-rebase hook is called before git rebase changes anything, making it a good place to make sure something terrible isn’t about to happen.This hook takes 2 parameters: the upstream branch that the series was forked from, and the branch being rebased. The second parameter is empty when rebasing the current branch. To abort the rebase, exit with a non-zero status.Write a pre-rebase hook script to abort the rebasing on any branch and additionally, display a WARNING message if the upstream rebase branch is ‘master’.--pre-rebase hook code: vi .git/hooks/pre-rebase --Make the script executable: chmod +x .git/hooks/pre-rebaseRebase ‘topic’ branch on ‘dev’ branchhooksProj [dev] $git rebase dev topic pre-rebase: rebasing is dangerous, don't do it. The pre-rebase hook refused to rebase.Rebase ‘topic’ branch on ‘master’ branchhooksProj [dev] $git rebase master topic WARNING!!! upstream branch is master. You are not allowed to rebase on master The pre-rebase hook refused to rebase.Note the difference in output message in each case. Either ways it would not allow you to rebase.Sever-side hooksServer-side hooks work just like local ones, except they reside in server-side repositories (e.g., a central repository, or a developer’s public repository). When attached to the official repository, some of these can serve as a way to enforce policy by rejecting certain commits.‘localRepo’ acts as a client repository and ‘remoteRepo’ as a Server repository.‘pre-receive’: Triggered just before a ‘push’ request on the Server, can be written to reject or allow the push operation.‘update’ hook script: runs after ‘pre-receive’ hook. It gives info on refname(branch/tag) being pushed to, push commits moving from ‘old commit id’ to ‘new commit id’‘post-update’ hook script: This updates the .git/info/refs file with the latest commitId for every branch.--localRepo is ahead of remoteRepo localRepo [dev] $git status On branch dev Your branch is ahead of 'origin/dev' by 1 commit.  (use "git push" to publish your local commits)--Sever side hook scripts:cd remoteRepo remoteRepo [dev] $ls -1 .git/hooks/ pre-receive update post-update--Push from localRepo to remoteRepolocalRepo [dev] $git push Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Writing objects: 100% (2/2), 272 bytes | 272.00 KiB/s, done. Total 2 (delta 0), reused 0 (delta 0) remote: pre-recieve hook script remote: hooks/pre-receive: [NOK]- Abort the push command remote: To /Users/Divya1/OneDrive/gitRepos/remoteRepo/ ! [remote rejected] dev -> dev (pre-receive hook declined) error: failed to push some refs to '/Users/Divya1/OneDrive/gitRepos/remoteRepo/'Edit the ‘pre-receive’ script to allow the push operation on ‘remoteRepo’, other 2 scripts will be auto triggered.localRepo [dev] $git push Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Delta compression using up to 4 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (2/2), 272 bytes | 272.00 KiB/s, done. Total 2 (delta 0), reused 0 (delta 0) remote: remote: hooks/pre-receive: [OK] -  pre-recieve hook script triggered... allow 'push' operation. remote: remote: hooks/update: hooks script triggered... remote: remote: hooks/update: Moving refs/heads/dev from 4f7da8d58db3dc7d5faa4015b589918e06c18843 to e7601cd74f44509afbd07538abcfbbcd7c3ca3aa remote: remote: hooks/post-update: hooks script triggered... remote: hooks/post-update: Update .git/info/refs file with the latest commitId for every branch. To /Users/Divya1/OneDrive/gitRepos/remoteRepo/   4f7da8d..e7601cd  dev -> devCONCLUSION:git provides a level of security by means of hook scripts on both client and server side.It gives you a means to run automated pre and post checks on your repository. Use them wisely.2. Git refs and reflogRefs are also a part of git metadata objects that keeps the references to the commits and tags from each branch.Refs are stored as objects in the .git/refs directory; Below is the git structure for git refs:$.git/refs heads remotes stash tags$.git/refs/heads branch_v1.8 feature1 initialBranch master topicBranchRef is a user-friendly alias for a commit hash.git reflog : Manage reference logs informationreflog records each and every operation performed by git. Right from a adding files, changing their file permissions to staging, committing, branch managements to remote server connections.It stores the history in a chronological order. Consider it as a LIFO list.myProj [master] $git reflog | head 310ddc5 HEAD@{0}: checkout: moving from d1cd65703b8c37c2bd83b634218cab44968cefbe to master d1cd657 HEAD@{1}: checkout: moving from master to 367b4edcfc3dc652c2e2679d2bc74bc328163966~1 310ddc5 HEAD@{2}: checkout: moving from 367b4edcfc3dc652c2e2679d2bc74bc328163966 to master 367b4ed HEAD@{3}: checkout: moving from master to 367b4edcfc3dc652c2e2679d2bc74bc328163966 310ddc5 HEAD@{4}: commit: Add the Linux iso image. 373c878 HEAD@{5}: cherry-pick: Add LFS object : *.tar file. 9ecf5bd HEAD@{6}: checkout: moving from initialBranch to master 394746e HEAD@{7}: commit: Add LFS object : *.tar file. bf031f0 HEAD@{8}: commit (amend): Modify git lfs file to track *.tar files.To see the log of the references use the ‘git show’ commandgit show 310ddc5 git show HEAD@{4} Checkout a reflog snapshot as: git checkout HEAD@{3} or git checkout 367b4ed
logo

GIT Tutorial

Git Objects

Git objects are the metadata stored under .git/objects repository. There are 4 types of git objects:

Git commit, git trees, git blobs and git tags.

Each commit object is uniquely identified by a git hash code (SHA-1).

Every commit made creates a new commit object that stores a reference to the tree object, blob files, and tags if any.

Refer: git commit object diagram

1. Git Hooks

Hooks are the metadata objects in the .git directory created at the time of ‘git init .<directory>’ command.

These scripts are like triggers that get executed pre or post an action or event; such as a command run.

Every git repository comes installed with prebuilt hooks scripts in the .git/hooks directory; that a user can edit as per the project’s requirement.

There are two groups of these hooks: client-side and server-side.

Client-side hooks:

These are hooks installed and maintained on the developers local repository and are executed when events on the local repository are triggered, such as commit and merge and rebase.

Server-side hooks:

These hooks installed on Server on network operations such as receiving pushed commits.

Project: hooksProj

hooksProj [master] $ls -1 .git/hooks/
applypatch-msg.sample
commit-msg.sample
fsmonitor-watchman.sample
post-update.sample
pre-applypatch.sample
pre-commit.sample
pre-push.sample
pre-rebase.sample
pre-receive.sample
prepare-commit-msg.sample
update.sample

To enable a hook script, rename the script to the same name truncating the .sample extension.

However if you write your own hook scripts, write it in Shell language and place it under .git/hooks folder of your project and make them executable as :

git chmod +x <script_name>

Scripts are listed in the order of their execution.

hooks [topic] $ls -1 *commit*
pre-commit
prepare-commit-msg
commit-msg
post-commit

Current project state:

hooksProj [topic] $git status
On branch topic
Changes to be committed:
 (use "git reset HEAD <file>..." to unstage)

       deleted:    README

Step 1: Commit the above project snapshot

hooksProj [topic] $git commit
--------------------------------------------
Step 1: Running .git/hooks/pre-commit script.
WARNING!!! Aborting the commit. Found Deleted files in the Staging area.

README

‘pre-commit’ hook fails.

‘pre-commit’ script runs a test before making a commit

#Aim: Check for any Deleted file in the staging area, if any it stops you from committing this snapshot.

Step 2: Reset the project back to HEAD commit and add/modify any file(README).

[topic] $git status
On branch topic
Changes to be committed:
 (use "git reset HEAD <file>..." to unstage)

      modified:   README

Add files to staging area and commit:

git commit

--This opens up the editor:

Add date in README.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch topic
# Changes to be committed:
#       modified:   README
#
ISSUE#7092

‘prepare-commit-msg’ hook:

#Aim: Appends the commit message and display the list of staged files that were committed.

Step 3: Remove the line ISSUE# while saving the message.

hooksProj [topic] $git commit
--------------------------------------------
Step 1: Running .git/hooks/pre-commit script.
[OK]: No deleted files, proceed to commit.
--------------------------------------------
Step 2: Running .git/hooks/prepare-commit-msg script.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch topic
# Changes to be committed:
# modified:   README
#
ISSUE#7092

Enter your commit message here.

README
--------------------------------------------
Step 3: Running .git/hooks/commit-msg script.
[NOK]: Missing  an ISSUE number in the message

 

Commit-msg’ hook script fails.

#Aim: Reads the commit log message for ISSUE#.

Step 4: commit again keeping the ISSUE# in the commit message.

hooksProj [topic] $git commit
--------------------------------------------
Step 1: Running .git/hooks/pre-commit script.
[OK]: No deleted files, proceed to commit.
--------------------------------------------
Step 2: Running .git/hooks/prepare-commit-msg script.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch topic
# Changes to be committed:
# modified:   README
#
ISSUE#7092

Enter your commit message here.

README
--------------------------------------------
Step 3: Running .git/hooks/commit-msg script.
[OK]: Commit message has an ISSUE number

--------------------------------------------
Step 4: Running .git/hooks/post-commit script.
New commit made:

b33401b Edit README file. ISSUE#7092

[topic b33401b] Edit README file. ISSUE#7092
1 file changed, 1 insertion(+)

post-commit’ script triggered after the commit was made.

Aim# To trigger a report on the latest commit made.

Step 5: All the 4 pre and post commit scripts exited with success status, commit made.

hooksProj [topic] $git hist
* b33401b 2019-01-29 | Edit README file. ISSUE#7092 (HEAD -> topic) [divya bhushan]
* e0a4db8 2019-01-26 | Add README [divya bhushan]

‘pre-rebase’ hook:

The pre-rebase hook is called before git rebase changes anything, making it a good place to make sure something terrible isn’t about to happen.

This hook takes 2 parameters: the upstream branch that the series was forked from, and the branch being rebased. The second parameter is empty when rebasing the current branch. To abort the rebase, exit with a non-zero status.

Write a pre-rebase hook script to abort the rebasing on any branch and additionally, display a WARNING message if the upstream rebase branch is ‘master’.

--pre-rebase hook code:
vi .git/hooks/pre-rebase

--Make the script executable:
chmod +x .git/hooks/pre-rebase

Rebase ‘topic’ branch on ‘dev’ branch

hooksProj [dev] $git rebase dev topic
pre-rebase: rebasing is dangerous, don't do it.
The pre-rebase hook refused to rebase.

Rebase ‘topic’ branch on ‘master’ branch

hooksProj [dev] $git rebase master topic
WARNING!!! upstream branch is master.

You are not allowed to rebase on master

The pre-rebase hook refused to rebase.

Note the difference in output message in each case. Either ways it would not allow you to rebase.

Sever-side hooks
Server-side hooks work just like local ones, except they reside in server-side repositories (e.g., a central repository, or a developer’s public repository). When attached to the official repository, some of these can serve as a way to enforce policy by rejecting certain commits.

‘localRepo’ acts as a client repository and ‘remoteRepo’ as a Server repository.

pre-receive’: Triggered just before a ‘push’ request on the Server, can be written to reject or allow the push operation.

update’ hook script: runs after ‘pre-receive’ hook. It gives info on refname(branch/tag) being pushed to, push commits moving from ‘old commit id’ to ‘new commit id’
post-update’ hook script: This updates the .git/info/refs file with the latest commitId for every branch.

--localRepo is ahead of remoteRepo
localRepo [dev] $git status
On branch dev
Your branch is ahead of 'origin/dev' by 1 commit.
 (use "git push" to publish your local commits)

--Sever side hook scripts:

cd remoteRepo
remoteRepo [dev] $ls -1 .git/hooks/
pre-receive
update
post-update

--Push from localRepo to remoteRepo

localRepo [dev] $git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (2/2), 272 bytes | 272.00 KiB/s, done.
Total 2 (delta 0), reused 0 (delta 0)
remote: pre-recieve hook script
remote: hooks/pre-receive: [NOK]- Abort the push command
remote:
To /Users/Divya1/OneDrive/gitRepos/remoteRepo/
! [remote rejected] dev -> dev (pre-receive hook declined)
error: failed to push some refs to '/Users/Divya1/OneDrive/gitRepos/remoteRepo/'

Edit the ‘pre-receive’ script to allow the push operation on ‘remoteRepo’, other 2 scripts will be auto triggered.

localRepo [dev] $git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 272 bytes | 272.00 KiB/s, done.
Total 2 (delta 0), reused 0 (delta 0)
remote:
remote: hooks/pre-receive: [OK] -  pre-recieve hook script triggered... allow 'push' operation.
remote:
remote: hooks/update: hooks script triggered...
remote:
remote: hooks/update: Moving refs/heads/dev from 4f7da8d58db3dc7d5faa4015b589918e06c18843 to e7601cd74f44509afbd07538abcfbbcd7c3ca3aa
remote:
remote: hooks/post-update: hooks script triggered...
remote: hooks/post-update: Update .git/info/refs file with the latest commitId for every branch.
To /Users/Divya1/OneDrive/gitRepos/remoteRepo/
  4f7da8d..e7601cd  dev -> dev

CONCLUSION:

git provides a level of security by means of hook scripts on both client and server side.

It gives you a means to run automated pre and post checks on your repository. Use them wisely.

2. Git refs and reflog

Refs are also a part of git metadata objects that keeps the references to the commits and tags from each branch.

Refs are stored as objects in the .git/refs directory; Below is the git structure for git refs:

$.git/refs
heads
remotes
stash
tags

$.git/refs/heads
branch_v1.8
feature1
initialBranch
master
topicBranch

Ref is a user-friendly alias for a commit hash.

git reflog : Manage reference logs information

reflog records each and every operation performed by git. Right from a adding files, changing their file permissions to staging, committing, branch managements to remote server connections.

It stores the history in a chronological order. Consider it as a LIFO list.

myProj [master] $git reflog | head
310ddc5 HEAD@{0}: checkout: moving from d1cd65703b8c37c2bd83b634218cab44968cefbe to master
d1cd657 HEAD@{1}: checkout: moving from master to 367b4edcfc3dc652c2e2679d2bc74bc328163966~1
310ddc5 HEAD@{2}: checkout: moving from 367b4edcfc3dc652c2e2679d2bc74bc328163966 to master
367b4ed HEAD@{3}: checkout: moving from master to 367b4edcfc3dc652c2e2679d2bc74bc328163966
310ddc5 HEAD@{4}: commit: Add the Linux iso image.
373c878 HEAD@{5}: cherry-pick: Add LFS object : *.tar file.
9ecf5bd HEAD@{6}: checkout: moving from initialBranch to master
394746e HEAD@{7}: commit: Add LFS object : *.tar file.
bf031f0 HEAD@{8}: commit (amend): Modify git lfs file to track *.tar files.

To see the log of the references use the ‘git show’ command

git show 310ddc5
git show HEAD@{4}

Checkout a reflog snapshot as:
git checkout HEAD@{3}
or
git checkout 367b4ed

Leave a Reply

Your email address will not be published. Required fields are marked *

Comments

Ezeelogin

Thanks for the post. I liked the way all the details have been provided!

stephen

Firstly thanks for providing this tutorial from this article I have gathered lots of information. I can say that whatever the information provided by knowledgeHut is more useful to know more about the git.

Saurabh

Written nicely