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
git log
git reflog
git reset
(in one of its forms)git fsck --full
(show dangling objects)git show
git rebase -i
There a are three tasks to be done.
- Find a secret which was committed and removed later
- Squash all commit after the "second commit" into the second commit
- Find the contents of a staged but not yet committed blob
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!