git refs ...

Sunday, Apr 6, 2025| Tags: git

DISCLAIMER: Image is generated using FREE version of ChatGPT.




1. Introduction

2. Types of refs

3. List refs

4. Useful Commands

5. HEAD shortcuts

6. Types of HEAD

7. trunk in Git

8. Git Remotes

9. Types of Remote refs


Introduction


Today is such a fine and sunny Sunday morning to do some brain dumping and share it with you.

It’s exactly one week since the end of Ramadan and this is my first blog after Ramadan.

As predicted, I went into my shell after Ramadan, which isn’t a good sign.

I’ll try and keep breaking the cycle and come out of it as much as I can.

This is something I never bothered to look into in detail and because of that, I’ve ended up in a big mess a few times.

Today, I decided to understand it from the ground up, so that during difficult times, I’ll be able to navigate my way out.

So, what are git references or git refs?

As the name suggests, they are pointers to commits in your repository.

They are fundamental to how Git tracks and organizes changes.


Types of refs



1. Branches


These are refs that move forward as you commit e.g. .git/refs/heads/master


2. Tags


These are typically static refs that mark specific points e.g. .git/refs/tags/wk-001


3. Remotes


These track branches from remote repositories e.g. .git/refs/remotes/origin/master


List refs



I am using this repository for reference in the post below.

The command git show-ref lists all refs in the repository.


$ git show-ref
aca905aa8d68c769bcd9a8fd532458398024ed11 refs/heads/master
aca905aa8d68c769bcd9a8fd532458398024ed11 refs/remotes/origin/HEAD
aca905aa8d68c769bcd9a8fd532458398024ed11 refs/remotes/origin/master
9f6decc59edcef202bfddc3d662400a0ad611156 refs/tags/wk-001
7f358d36c3f71f78707ea2149d05a8a646a95282 refs/tags/wk-002
...
...

All refs are stored in the .git/refs/ subfolder as below:


$ tree .git/refs/
.git/refs/
├── heads
│   └── master
├── remotes
│   └── origin
│       ├── HEAD
│       └── master
└── tags
    ├── wk-306
    ├── wk-307
    ├── wk-308
    ├── wk-309
    ├── wk-310
    ├── wk-311
    ├── wk-312
    ├── wk-313
    ├── wk-314
    └── wk-315

There is a special ref i.e. HEAD, which points to your current branch or commit: .git/HEAD


$ cat .git/HEAD
ref: refs/heads/master

Useful Commands



git show HEAD


It shows the commit that HEAD currently points to.


$ git show HEAD
commit aca905aa8d68c769bcd9a8fd532458398024ed11 (HEAD -> master, origin/master, origin/HEAD)
Author: Mohammad Sajid Anwar <mohammad.anwar@yahoo.com>
Date:   Sun Apr 6 01:37:15 2025 +0100

    - Added solutions by Arne Sommer.
    - Added solutions by Jan Krnavek.
    - Added solutions by Kjetil Skotheim.

diff --git a/stats/pwc-challenge-310.json b/stats/pwc-challenge-310.json
index 89a729bc16..8c017f3efb 100644
--- a/stats/pwc-challenge-310.json
+++ b/stats/pwc-challenge-310.json
@@ -1,184 +1,30 @@
 {
+   "legend" : {
+      "enabled" : 0
+   },
    "yAxis" : {
       "title" : {
          "text" : "Total Solutions"
       }
    },

The first line: commit aca905aa8d68c769bcd9a8fd532458398024ed11 (HEAD -> master, origin/master, origin/HEAD) is particularly very handy.

It tells the HEAD is currently pointing to local master branch as well as remote master and HEAD.

This mean, my local repository is in good health.


git symbolic-ref HEAD


It shows which branch HEAD is pointing to.


$ git symbolic-ref HEAD
refs/heads/master


git diff HEAD~1 HEAD


It compares the previous commit with the current one.


$ git diff HEAD~1 HEAD
diff --git a/stats/pwc-challenge-310.json b/stats/pwc-challenge-310.json
index 89a729bc16..8c017f3efb 100644
--- a/stats/pwc-challenge-310.json
+++ b/stats/pwc-challenge-310.json
@@ -1,184 +1,30 @@
 {
+   "legend" : {
+      "enabled" : 0
+   },
    "yAxis" : {
       "title" : {
          "text" : "Total Solutions"
       }
    },
...
...
...

You can also use this instead to get the same result: git diff HEAD^1 HEAD


HEAD shortcuts



HEAD~ / HEAD^ - Parent of HEAD.

HEAD@{n} - The nth prior position of HEAD (useful with reflog).


$ git diff HEAD@{7} HEAD
diff --git a/challenge-310/kjetillll/perl/ch-1.pl b/challenge-310/kjetillll/perl/ch-1.pl
new file mode 100644
index 0000000000..c6fa2056a2
--- /dev/null
+++ b/challenge-310/kjetillll/perl/ch-1.pl
@@ -0,0 +1,13 @@
+sub f {
+    my @arr = @_;
+    my %elem;
+    for my $i ( 0 .. $#arr ){
+        $elem{$_}{$i}++ for @{ $arr[$i] };
+    }
+    sort{ $a <=> $b } grep @_ == keys %{ $elem{$_} }, keys %elem
+}
+
+use Test::More tests => 3;
+is_deeply [ f( [1, 2, 3, 4], [4, 5, 6, 1], [4, 2, 1, 3] ) ], [1, 4];
+is_deeply [ f( [1, 0, 2, 3], [2, 4, 5] )                  ], [2];
+is_deeply [ f( [1, 2, 3], [4, 5], [6] )                   ], [];

The command: git reflog keeps track of changes to the tips of branches and other references in the local repository.

It is essentially a safety net that records when the tips of branches were updated in the local repository.

It maintains history of:


- Branch checkouts
- Resets
- Rebases
- Commits

Unlike git log, which shows the commit history, the reflog shows the history of your refs and HEAD.


$ git reflog
aca905aa8d (HEAD -> master, origin/master, origin/HEAD) HEAD@{0}: checkout: moving from 68323c4b8f9cd1240b453d353c019470086799a4 to master
68323c4b8f HEAD@{1}: checkout: moving from master to 68323c4b8
aca905aa8d (HEAD -> master, origin/master, origin/HEAD) HEAD@{2}: commit: - Added solutions by Arne Sommer.
68323c4b8f HEAD@{3}: merge refs/remotes/origin/master: Fast-forward
d077b4b0d2 HEAD@{4}: commit: - Added solutions by Jorg Sommrey.
9c04e8a9a8 HEAD@{5}: merge refs/remotes/origin/master: Fast-forward
...
...

Always remember, it exists only in your local repository and isn’t shared when you push/pull.

It expires after 90 days by default and configurable.

It helps recover lost commits and branches.


Common Use Cases


Recover Lost Work


Use git reflog to find the commit before the error then use this to recover: git reset --hard HEAD@{3}


$ git reflog
aca905aa8d (HEAD -> master, origin/master, origin/HEAD) HEAD@{0}: checkout: moving from 68323c4b8f9cd1240b453d353c019470086799a4 to master
68323c4b8f HEAD@{1}: checkout: moving from master to 68323c4b8
aca905aa8d (HEAD -> master, origin/master, origin/HEAD) HEAD@{2}: commit: - Added solutions by Arne Sommer.
68323c4b8f HEAD@{3}: merge refs/remotes/origin/master: Fast-forward
d077b4b0d2 HEAD@{4}: commit: - Added solutions by Jorg Sommrey.
9c04e8a9a8 HEAD@{5}: merge refs/remotes/origin/master: Fast-forward
...
...

Reflog of Branch


Show reflog for a specific branch: git reflog show <branch_name>


$ git reflog show master
aca905aa8d (HEAD -> master, origin/master, origin/HEAD) master@{0}: commit: - Added solutions by Arne Sommer.
68323c4b8f master@{1}: merge refs/remotes/origin/master: Fast-forward
d077b4b0d2 master@{2}: commit: - Added solutions by Jorg Sommrey.
9c04e8a9a8 master@{3}: merge refs/remotes/origin/master: Fast-forward
1be16da34e master@{4}: commit: - Added solutions by Peter Pentchev.
fc88fe7ab3 master@{5}: merge refs/remotes/origin/master: Fast-forward
c458ab51a3 master@{6}: merge refs/remotes/origin/master: Fast-forward
...
...

More details than the git log


$ git reflog --format=fuller
commit aca905aa8d (HEAD -> master, origin/master, origin/HEAD)
Reflog: HEAD@{0} (Mohammad Sajid Anwar <mohammad.anwar@yahoo.com>)
Reflog message: checkout: moving from 68323c4b8f9cd1240b453d353c019470086799a4 to master
Author:     Mohammad Sajid Anwar <mohammad.anwar@yahoo.com>
AuthorDate: Sun Apr 6 01:37:15 2025 +0100
Commit:     Mohammad Sajid Anwar <mohammad.anwar@yahoo.com>
CommitDate: Sun Apr 6 01:37:15 2025 +0100

    - Added solutions by Arne Sommer.
    - Added solutions by Jan Krnavek.
    - Added solutions by Kjetil Skotheim.

...
...

Types of HEAD



1. Attached HEAD


When HEAD points to a branch, it is called attached HEAD.


$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean

2. Detached HEAD


When HEAD points directly to a commit, it is called detached HEAD.


$ git checkout 68323c4b8
Note: switching to '68323c4b8'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 68323c4b8f Merge pull request #11828 from arnesom/branch-for-challenge-315

trunk in Git



Have you heard of the trunk in Git?

The term trunk refers to the primary branch where main development happens.

It’s borrowed from older version control systems like Subversion (SVN).

In Git, there’s no official branch called trunk, but the idea maps to the main or master branch, the default primary branch in most repositories.


Git Remotes



Remotes (or remote repositories) are references to versions of your project hosted on another server.

They allow collaboration by pushing and pulling changes between your local repo and the remote.

The default remote name is origin, which is created when you clone a repository.

Remote configurations are stored in .git/config and .git/refs/remotes/.

Common remote hosts include GitHub, GitLab, Bitbucket etc.


$ cat .git/config
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = https://github.com/manwar/perlweeklychallenge-club
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        vscode-merge-base = origin/master
        merge = refs/heads/master

$ tree .git/refs/remotes/
.git/refs/remotes/
└── origin
    ├── HEAD
    └── master

2 directories, 2 files

Types of Remote refs



1. Remote Branch


These track the state of branches on the remote server.


$ cat .git/refs/remotes/origin/master
aca905aa8d68c769bcd9a8fd532458398024ed11

2. Remote HEAD


It points to the default branch on the remote repository.


$ cat .git/refs/remotes/origin/HEAD
ref: refs/remotes/origin/master

Common remote commands


To lists all remotes and their URLs: git remote -v


$ git remote -v
origin  https://github.com/manwar/perlweeklychallenge-club (fetch)
origin  https://github.com/manwar/perlweeklychallenge-club (push)

To add new remote: git remote add <remote_name> <remote_url>

To remove a remote: git remote remove <remote_name>

To fetch changes from a remote: git fetch <remote_name>

To Fetch and merge changes from a remote branch into your current branch: git pull <remote_name> <branch>




Don't stop learning !!!

SO WHAT DO YOU THINK ?

If you have any suggestions or ideas then please do share with us.

Contact with me