Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save bittrance/afeed361f6a192e5b52021ebb3479399 to your computer and use it in GitHub Desktop.
Save bittrance/afeed361f6a192e5b52021ebb3479399 to your computer and use it in GitHub Desktop.

Original repository

A simple repository with two commits.

$ mkdir repo
$ cd repo/
$ git init .
Initialized empty Git repository in /Users/bittrance/tmp/repo/.git/
$ echo 1 > ze-file
$ git add ze-file
$ git commit -m 'Commit 1'
[master (root-commit) 4445377] Commit 1
 1 file changed, 1 insertion(+)
 create mode 100644 ze-file
$ echo 2 > ze-file
$ git commit -m 'Commit 2' ze-file
[master 361012f] Commit 2
 1 file changed, 1 insertion(+), 1 deletion(-)

Create a local checkout

$ cd ../
$ git clone ./repo/ ./checkout
Cloning into './checkout'...
done.
$ cd checkout/
$ cat ze-file
2

Malicious actor replaces upstream

Unrelated repository with two commit replaces the previous one.

$ cd ../repo/
$ rm -rf .git/ ze-file
$ git init .
Initialized empty Git repository in /Users/bittrance/tmp/repo/.git/
$ echo 3 > ze-file
$ git add ze-file
$ git commit -m 'Commit 3' ze-file
[master (root-commit) 0be964f] Commit 3
 1 file changed, 1 insertion(+)
 create mode 100644 ze-file
$ echo 4 > ze-file
$ git commit -m 'Commit 4' ze-file
[master 1480d0d] Commit 4
 1 file changed, 1 insertion(+), 1 deletion(-)

Pull from evil repository

Note that git says it did a forced update of master when you pulled.

$ cd ../checkout/
$ git pull origin
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (6/6), 401 bytes | 133.00 KiB/s, done.
From /Users/bittrance/tmp/./repo
 + 361012f...1480d0d master     -> origin/master  (forced update)
Successfully rebased and updated refs/heads/master.
$ cat ze-file
4
$ git log --oneline
1480d0d (HEAD -> master, origin/master, origin/HEAD) Commit 4
0be964f Commit 3

Oh no, we've been pwned! My previous history is lost!

Chill, nothing's lost.

The reflog holds historical positions of all branches.

$ git reflog
1480d0d (HEAD -> master, origin/master, origin/HEAD, old-master) HEAD@{3}: pull origin (finish): returning to refs/heads/master
1480d0d (HEAD -> master, origin/master, origin/HEAD, old-master) HEAD@{4}: pull origin (start): checkout 1480d0d518b8ac9085f10f0b6462fb36e98c926b
361012f HEAD@{5}: clone: from /Users/bittrance/tmp/./repo/
$ git log --oneline --reflog
1480d0d (HEAD -> master, origin/master, origin/HEAD) Commit 4
0be964f Commit 3
361012f Commit 2
4445377 Commit 1

Let's revert our local checkout branches (using master as example). For forensic purposes, we tag the evil branches.

$ git checkout -b evil-master
Switched to a new branch 'evil-master'
$ git branch -f master 361012f
$ git checkout master
Switched to branch 'master'
Your branch and 'origin/master' have diverged,
and have 2 and 2 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)
$ git log --oneline
361012f (HEAD -> master) Commit 2
4445377 Commit 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment