Squash commits

Let's prepare a repo with 3 commits. The first contains fileA.txt-V1, the second contains fileA.txt-V2 and file-B.txt-V1 and the third commit contains fileA.txt-V3 and fileB.txt-V1.

$ git init

$ echo a-V1 > fileA.txt
$ git add fileA.txt
$ git commit -m "a-V1"

$ echo a-V2 > fileA.txt
$ echo b-V1 > fileB.txt
$ git add fileA.txt
$ git add fileB.txt
$ git commit -m "a-V2, b-V1"

$ echo a-V3 > fileA.txt
$ git add fileA.txt
$ git commit -m "a-V3, b-V1"

$ git log --oneline --decorate
2dbc688 (HEAD, master) a-V3, b-V1
f050908 a-V2, b-V1
593c94b a-V1

If the author considers the 2nd commit to be superfluous, he may remove it but moving the HEAD 2 steps back (in this example) and committing again since the INDEX still contains the snapshot of the 3rd commit. Remember, the --soft reset moves only the HEAD and does not change the INDEX.

$ git reset --soft HEAD~2

$ git log --oneline --decorate
593c94b (HEAD, master) a-V1

$ git commit -m "squased a-V3, b-V1"
[master beafb18] squased a-V3, b-V1
 2 files changed, 2 insertions(+), 1 deletion(-)
 create mode 100644 fileB.txt

$ git log --oneline --decorate
beafb18 (HEAD, master) squased a-V3, b-V1
593c94b a-V1

The result is that 2 commits (2dbc688, f050908) are removed and another one (beafb18) is created.