Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to squash all git commits into one?

How do you squash your entire repository down to the first commit?

I can rebase to the first commit, but that would leave me with 2 commits. Is there a way to reference the commit before the first one?

like image 554
Verhogen Avatar asked Nov 01 '09 08:11

Verhogen


People also ask

How do I squash multiple commits in github?

Squashing a commit In the list of branches, select the branch that has the commits that you want to squash. Click History. Select the commits to squash and drop them on the commit you want to combine them with. You can select one commit or select multiple commits using Command or Shift .

How do you merge all commits into one in a branch?

Another simple way to do this: go on the origin branch and do a merge --squash . This command doesn't do the "squashed" commit. when you do it, all commit messages of yourBranch will be gathered.


2 Answers

As of git 1.6.2, you can use git rebase --root -i.

For each commit except the first, change pick to squash.

like image 52
Jordan Lewis Avatar answered Oct 23 '22 18:10

Jordan Lewis


Update

I've made an alias git squash-all.
Example usage: git squash-all "a brand new start".

[alias]   squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} -m \"${1:-A new start}\");};f" 

Note: the optional message is for commit message, if omitted, it will default to "A new start".

Or you can create the alias with the following command:

git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f' 

One Liner

git reset $(git commit-tree HEAD^{tree} -m "A new start") 

Here, the commit message "A new start" is just an example, feel free to use your own language.

TL;DR

No need to squash, use git commit-tree to create an orphan commit and go with it.

Explain

  1. create a single commit via git commit-tree

    What git commit-tree HEAD^{tree} -m "A new start" does is:

Creates a new commit object based on the provided tree object and emits the new commit object id on stdout. The log message is read from the standard input, unless -m or -F options are given.

The expression HEAD^{tree} means the tree object corresponding to HEAD, namely the tip of your current branch. see Tree-Objects and Commit-Objects.

  1. reset the current branch to the new commit

Then git reset simply reset the current branch to the newly created commit object.

This way, nothing in the workspace is touched, nor there's need for rebase/squash, which makes it really fast. And the time needed is irrelevant to the repository size or history depth.

Variation: New Repo from a Project Template

This is useful to create the "initial commit" in a new project using another repository as the template/archetype/seed/skeleton. For example:

cd my-new-project git init git fetch --depth=1 -n https://github.com/toolbear/panda.git git reset --hard $(git commit-tree FETCH_HEAD^{tree} -m "initial commit") 

This avoids adding the template repo as a remote (origin or otherwise) and collapses the template repo's history into your initial commit.

like image 25
ryenus Avatar answered Oct 23 '22 19:10

ryenus