55

Cannot get how to perform squash rebase for the current branch. The console command would be

git rebase -i HEAD~2

and then squash as usually. But how to do the same in TGit?

Script to initialize the case

git init .
touch 1
git add 1
git commit -m "1"
touch 2
git add 2
git commit -m "2"
touch 3
git add 3
git commit -m "3"

As a result after squashing we would have 1 commit with 3 files.

Any proposals?

zerkms
  • 249,484
  • 69
  • 436
  • 539
  • The changelog for tortoisegit 1.7.0.0 has this line: Fixed issue #784 : Rebase window should allow easier selection of Pick/Squash/Edit/Skip (keys: space: shifts the state, s: skip, e: edit, p: pick, q: squash) – willoller Sep 24 '12 at 17:57
  • @willoller: I'm sure it's only about adding shortcuts to the already existing buttons – zerkms Sep 24 '12 at 20:44

6 Answers6

68

This works for me using TortoiseGit 1.7.12:

  1. Right-click on the working directory where you want to do an interactive rebase and choose TortoiseGit -> Show log from the context menu.
  2. In the appearing "Log Messages" dialog, right-click on the most recent commit that you would not like to rebase anymore and choose Rebase master onto this... from the context menu.
  3. In the appearing "Rebase" dialog, tick the Force Rebase checkbox and then right-click on the commit to choose between Pick, Squash, etc., or tick the Squash ALL checkbox in your case.
  4. Press the Start Rebase button, which on success turns into a Commit button, and then into a Done button. Press all of them.

Note that in your example script you would squash / fixup to the root commit, which is a special case and does not work as described above because the root commit has no parent that you could select in step 2.

Community
  • 1
  • 1
sschuberth
  • 28,386
  • 6
  • 101
  • 146
  • If I right click to the commit with comment "1", choose "rebase ..." and do what you proposed - I finish with 2 commits: "1" and "2": https://dl.dropbox.com/u/4486681/stackoverflow-git.png Do you get 1 commit? PS: yes, I installed the latest TGit version as well – zerkms Sep 26 '12 at 20:33
  • I also end up with 2 commits instead of 1 for your synthetic example, but this is due to the special case I've mentioned. An interactive rebase that modifies the root commit (i.e. the first commit in the history) is a special thing and cannot currently be done in TortoiseGit to the best of my knowledge. Also on the command line this is sort of tricky. See the link I've mentioned. For any other case that does not involve the root commit you can easily squash as many commits as you like using TortoiseGit and the steps from above. – sschuberth Sep 27 '12 at 06:44
  • 3
    WARNING (TortoiseGit 1.6.5.0): I tried this approach on a branch, rebasing onto the branch-off commit (the one BEFORE the first commit on the branch), and the result was that the branch HEAD was pointing to the branch-off point, with all commits on the branch and their modifications lost! – mistaecko Sep 27 '12 at 07:25
  • What about the cryptic --root? – ATL_DEV Jan 25 '14 at 22:34
  • I'm not using TortoiseGit on a regular basis, but my guess it that TortoiseGit does not support it (yet). However, I think it would be possible to implement some "smart" logic in TortoiseGit to automatically use the "--root" option if you've chosen to rebase the root commit in the GUI. – sschuberth Jan 26 '14 at 21:58
  • In my case, this yielded some "conflicts". To resolve, I just selected them all and pressed "Resolve using master" (rather than the remote contents). End result was as expected: making it as if I'd made all my changes in one commit, directly following the commit I was rebasing onto. Only annoyance is that the merged-commit date was set to the earliest data of the merged-commits (there was a box to change it but I didn't bother). – Venryx May 22 '20 at 15:47
  • Oh also, for git beginners (like me), it's important to note: Rebasing does **not** (reliably) accomplish the task of "take my working tree and create one commit to get there from the commit I'm rebasing onto", but rather, "take my *sequence of change*s, and apply them *after* the changes in the rebasing-onto commit-chain -- with the option to then mark my changes to override wherever there's conflicts". For most cases I have (maybe true for you as well), I want the former rather than the latter -- so should actually be using the soft-reset+commit approach (usually), rather than rebasing. – Venryx May 22 '20 at 16:15
64

You can combine two adjacent commits using the GUI as follows. Remember not do combine commits already on the shared repository. See: Right click 2 commits

sschuberth
  • 28,386
  • 6
  • 101
  • 146
regisbsb
  • 3,664
  • 2
  • 35
  • 41
  • 10
    Combining two (adjacent) commits like this is a very special case of rebasing / squashing. For a more generic solution (e.g. to squash commits that are not already adjacent) see my answer. – sschuberth Jan 25 '14 at 14:07
  • 4
    I'm on TortoiseGit 1.8.7 and I used to see this menu option, a long time ago, but no matter what commits I select now, the option to "Combine to one commit" never turns up. All the others you display are showing. Either it's been removed or something about all my commits is preventing me from doing it (I wish they'd show it and disable it in that case) – PandaWood Feb 12 '14 at 02:43
  • 2
    @PandaWood the commits need to be in the "tail" of the graph, without any merges etc, like in the picture. – regisbsb Jan 29 '16 at 14:17
  • 3
    @sschuberth you can select more than two I think – regisbsb Jan 29 '16 at 14:18
  • 1
    @regisbsb is correct. This can combine as many commits as you like – Richard Tingle Dec 19 '20 at 18:14
  • This option doesn't seem to be available if the commits do not include the most recent one. – robross0606 Nov 10 '22 at 15:55
6

Here's what I did using Tortoise Git & storing the repo on Assembla (a service which competes with GitLab, BitBucket, etc).

I decided I wanted to effectively delete my entire commit history, and start the repo over from scratch. I could have deleted the local git folder and the corresponding repo in Assembla, and then recreated it, but thought it was better to figure out how to do this the “right way”.

So, here’s how I achieved it:

  1. Using Tortoise Git, display the repo’s log. Highlight all the commits, right click on them, and select “combine into one commit”.

  2. In the dialog that pops up, delete the commit comment (which becomes a combination of all the prior comments), and replace it with a single comment e.g. REBASE. Then initiate the commit. The local repo will then be effectively started from scratch (with all the files still added to it of course) without having to delete and recreate it.

  3. Unfortunately, you can’t just push it to Assembla. It will reject this, insisting that your “head” is behind the remote branch. So, to solve that first go to the “Settings” page for the repo in Assembla. Enable “Allow –force push”.

  4. Now perform a “forced push”. I don’t know if Tortoise Git has a gui option for this, but it is easy to do via the command prompt:

    cd [your repo folder] git push -f origin

Done!

UPDATE:

To "force push" with TortoiseGit, in the push dialog there are checkboxes to force "known changes" and "unknown changes". I'm not sure what the difference is, but they both result in using the git --force switch. Try "known changes" to begin with.

BuvinJ
  • 10,221
  • 5
  • 83
  • 96
3
  • Go to Show Log, then make a tag at your current commit (e.g. "tmp").
  • Reset hard to the first commit back in history you don't want to change.
  • Toggle All Branches at the bottom of the log, if you don't see all commits.
  • Then select all newer commits and make a right click on them: Cherry Pick selected commits...
  • Now you are in interactive rebase mode. There you can do what is common for interactive rebase.
armin.miedl
  • 1,070
  • 1
  • 11
  • 16
3

You can do this from the Rebase window. This video covers it well: https://youtu.be/qrMubRPkkrE?t=490

As shown in the video:

  1. Right click TortoiseGit/Rebase...
  2. Change Upstream: to FETCH_HEAD
  3. Change Pick ALL to Squash ALL
  4. Click Start Rebase
ShawnFeatherly
  • 2,470
  • 27
  • 20
0

One way is: Go to log dialog and select "rebase onto *" and then check the "Force" checkbox and mark the commits for "squash" (e.g. by typing 'q').

Sven
  • 11