0

I have the following ugly history (the repeated messages come from my very beginning use of github).

ba7e5ec PPath begins...
be327e8 Update README.md
585b586 Update README.md
4d2ed26 Update README.md
834b3b6 Update README.md
6c7da1a Update README.md
9d89b1b First version.

I would like to have something like this.

xxxxxxx PPath begins...
yyyyyyy Update README.md
9d89b1b First version.

Is it possible ? The idea is to squash some commits but not necessarily the last ones.

projetmbc
  • 1,332
  • 11
  • 26
  • 4
    You could perform an interactive rebase and squash the commits with README updates. Be careful, though. It's basically rewriting your history and if you share this repo with other developers, it could end in a massive cluster****. It's a good idea to back up your repo and get familiar with the technique befor you unleash it upon your commits. – toniedzwiedz May 17 '15 at 21:30
  • 1
    possible duplicate of [Squash my last X commits together using Git](http://stackoverflow.com/questions/5189560/squash-my-last-x-commits-together-using-git) – stiemannkj1 May 17 '15 at 22:57
  • You can do things with the last few commit (the linked potential dup) that you can't do with earlier commtis, so I'd say not a dup of that anyway. – jthill May 18 '15 at 00:09

2 Answers2

2

The following instructions will help you make a step-by-step changes leading just to the desired result.

There are two ways to achieve the result.

With git rebase -i

This is faster but requires using a text editor.

git checkout master
git branch backup
#pick the sha1 of a commit before the one that will consume further commits.
git rebase -i 9d89b1b

This opens an editor with the text. Change it this way:

pick 6c7da1a Update README.md
squash 834b3b6 Update README.md
squash 4d2ed26 Update README.md
squash 585b586 Update README.md
squash be327e8 Update README.md
pick ba7e5ec PPath begins...
...

Now save and exit. If you're in vim, that's how to exit. A new editor opens with commit message. You can leave it intact or change to whatever you think is good.

# This is a combination of 3 commits.
# The first commit's message is:
Update README.md
...

Save and exit again. Job's done.

With git reset --soft.

This is longer but doesn't require side tools.

#start with a backup
git checkout master
git branch backup

#this returns head to be327e8 and brings the difference into index.
git reset --soft be327e8

# save that index for future use
git stash save

#same trick again
git reset --soft 9d89b1b

#recommit our changes
git commit -m'Update readme.md'

# now use the stashed changes
git stash apply
git commit -m'PPath begins...'

# check the result
git log --oneline

# now if everything is ABSOLUTELY FINE, you can delete the backup
git stash drop

A few links to explain what's going on:
Can you explain what "git reset" does in plain english?
Git cheatsheet

Community
  • 1
  • 1
Nick Volynkin
  • 14,023
  • 6
  • 43
  • 67
  • Personally I think an interactive rebase is to be preferred in this case. It's a picture book use case. – Sascha Wolf May 18 '15 at 06:36
  • I chose this way because it is easier and safer. Also, rebase -i leads to using the text editor, which is probably vim, and that's a difficult issue itself. But for an experienced user rebase is preferred and more universal, I agree. – Nick Volynkin May 18 '15 at 08:15
  • Sorry for this late answer. I did not know before the meaning of squash, no I understand it. Sorry, I'm french. ;-) – projetmbc May 21 '15 at 11:13
  • squash means 'join this commit with the previous one and make them a single commit' – Nick Volynkin May 21 '15 at 11:14
1

In any case, make sure you understand the consequences of history rewriting (read e.g. The perils of rebasing).

As an alternative to the other answer using git reset --soft, you may consider using git rebase -i. In its simplest form, run the command without other arguments, you'll get a todo-list in a text editor, and mark as fixup the commits you want to squash into their predecessor. Save and exit, git will do the rest.

Matthieu Moy
  • 15,151
  • 5
  • 38
  • 65