Inspecting and changing history

The setup script is located in the git.zip file in the exercsises folder.

Run ./inspecting.sh for setup!

In this exercise we can use any of

There a are three tasks to be done.

You can give this a try on your own, or read on. The command from above should be enough to solve all this tasks.

Find the secret

Our first task is to find a secret which was accidentally committed and removed later.

You can either try this by yourself or follow the walkthrough. You will need to use some of the commands from above.

What is the content of the secret?

Walkthrough

First of all we need to check what happened in this repository.

NOTE: Your commit hashes will differ!

$ git log


commit d0c56c143d70c9391a47b460399b39e08123a90e
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    dang, need a break, forgot to make changes to file 05

commit 7f6bae525c24edbb393cf9440be790d159628f01
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    ups, forgot file 4

commit 83a0facaba03b146e492c96c4d675ec1d92df6d2
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    third commit

commit f9a9195b67ef88942dc5f1c05ad5b6b3edea7042
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    add .gitignore

commit 290001a8c9ceff0dfd9242273f5055334791e396
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    second commit

commit 0b24aa2dc89fa76eff39fa644bfd625562b25eed
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    initial commit

Apparently the author was tired and added a .gitignore file sometimes. But nothing to see here.

But wait, there is a second type of log. The reflog It logs movements of HEAD.

$ git reflog  

d0c56c1 HEAD@{0}: reset: moving to HEAD
d0c56c1 HEAD@{1}: commit: dang, need a break, forgot to make changes to file 05
7f6bae5 HEAD@{2}: commit: ups, forgot file 4
83a0fac HEAD@{3}: commit: third commit
f9a9195 HEAD@{4}: commit: add .gitignore
290001a HEAD@{5}: commit: second commit
0b24aa2 HEAD@{6}: reset: moving to HEAD^
08f652e HEAD@{7}: commit: second commit
0b24aa2 HEAD@{8}: commit (initial): initial commit

Interesting, there was a reset. Which reset the HEAD to the commit before (HEAD^). And then there was a commit with the same commit message as before ("second commit). Maybe we find something in this commit which also does not show up in our normal git log

$ git show 08f652

commit 08f652e240c3ad380e9addb457b8cc6ea70eb417
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    second commit

diff --git a/.env b/.env
new file mode 100644
index 0000000..b5f9078
--- /dev/null
+++ b/.env
@@ -0,0 +1 @@
+supersecret
diff --git a/file02.txt b/file02.txt
index 6c493ff..b602e20 100644
--- a/file02.txt
+++ b/file02.txt
@@ -1 +1,2 @@
 file2
+line2

Nice, we fond the secret. This may also explain the .gitignore. Maybe it was to not commit .env files by accident.

Squash the commits into 'second commit'

We want to clean up our history by squashing all the commit after "second commit" into the "second commit".

Again, you can do this in your own, or follow the walkthrough.

Walkthrough

First we need to find a commit hash to reset to

$ git log

commit d0c56c143d70c9391a47b460399b39e08123a90e
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    dang, need a break, forgot to make changes to file 05

commit 7f6bae525c24edbb393cf9440be790d159628f01
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    ups, forgot file 4

commit 83a0facaba03b146e492c96c4d675ec1d92df6d2
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    third commit

commit f9a9195b67ef88942dc5f1c05ad5b6b3edea7042
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    add .gitignore

commit 290001a8c9ceff0dfd9242273f5055334791e396
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    second commit

commit 0b24aa2dc89fa76eff39fa644bfd625562b25eed
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    initial commit

We need to reset to the initial commit as we want to create a whole new "second commit".

$ git reset --soft 0b24aa
$ git status --short

A  .gitignore
M  file02.txt
A  file03.txt
A  file04.txt
A  file05.txt

Nice, all our files are already staged. That was the reason we used --soft and not --mixed or nothing. If we had used the default (mixed) we would need to stage the changed files again. Mixed resets the index and the HEAD, soft only the HEAD.

Now we commit.

$ git commit -m "second commit"

[master 8c7be32] second commit
 Author: maschmi <maschmi@maschmi.net>
 5 files changed, 6 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 file03.txt
 create mode 100644 file04.txt
 create mode 100644 file05.txt

and check with

$ git log

commit 8c7be32d558dc85e52f5d02bc6e2745742864b78
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:49:20 2025 +0200

    second commit

commit 0b24aa2dc89fa76eff39fa644bfd625562b25eed
Author: maschmi <maschmi@maschmi.net>
Date:   Tue Jun 3 16:46:49 2025 +0200

    initial commit

Finding a staged but not committed blob

Oh no, you started to do some complex experiments. You staged them and planned to commit them. But then you need to do something else. And in a hurry you just type git reset --hard HEAD. Can you recover the staged file?

Yes you can, but it is a bit more involved. We need to think about how git knows the content of staged files.

Git creates a blob for staged content. But no tree and no commit. The filename and commit hash is written to the index file. Using git fsck --full we can check our graph for nodes without connections. Running this may help.

$ git fsck --full


Checking object directories: 100% (256/256), done.
dangling blob a163ec362b152ccc3a0dac6f262e877ab05b7e58

Let's have a look at this dangling blob.


$ git show a163ec
supercomplexstuff

Nice, we recovered the staged blob!