LinuxCommandLibrary

git-squash

Combine multiple Git commits into a single commit

TLDR

Merge all commits from a specific branch into the current branch as a single commit

$ git squash [source_branch]
copy

Squash all commits starting with a specific commit on the current branch
$ git squash [commit]
copy

Squash the n latest commits and commit with a message
$ git squash HEAD~[n] "[message]"
copy

Squash the n latest commits and commit concatenating all individual messages
$ git squash --squash-msg HEAD~[n]
copy

SYNOPSIS

Since git-squash is not a standalone command, its functionality is typically achieved via git rebase -i.

git rebase -i [commit-ish]
git rebase -i HEAD~

Where is the number of commits from HEAD to include in the interactive rebase, and commit-ish specifies the commit before the series you want to rebase. When in interactive mode, you mark commits with 'squash' or 'fixup'.

PARAMETERS

-i, --interactive
    Required to enter interactive rebase mode. This opens an editor with a list of commits in your rebase range, allowing you to specify actions for each commit, including 'squash' or 'fixup'.

squash
    An action keyword used within the interactive rebase editor. Marks the current commit to be combined with the previous commit, merging their commit messages. Git will prompt you to edit the combined message.

fixup
    An action keyword used within the interactive rebase editor. Similar to 'squash', it combines the current commit with the previous one, but discards the current commit's log message, using only the previous commit's message. No message editing prompt occurs.


    Specifies the commit before the range of commits you want to rebase (and potentially squash). All commits from this commit-ish to HEAD will be presented in the interactive todo list.

HEAD~
    A common way to specify the range for interactive rebase. It indicates the last commits from the current HEAD that you want to rebase and potentially squash.

DESCRIPTION

git-squash is not a native Git command; rather, it commonly refers to the process of combining multiple Git commits into a single, more meaningful commit. This powerful operation is most frequently achieved using git rebase -i (interactive rebase). The primary purpose of squashing commits is to clean up a branch's history, making it more linear, understandable, and easier to review. For instance, a series of incremental commits (e.g., 'fix typo', 'add feature part 1', 'fix bug', 'add feature part 2') can be consolidated into a single, comprehensive commit like 'Implement Feature X'. This practice helps maintain a clean, concise project history, particularly before merging a feature branch into main development lines like main or master, contributing to cleaner pull requests and easier future debugging.

CAVEATS

Squashing commits rewrites Git history. This means the SHA-1 hashes of the squashed commits will change. Therefore:
1. Do not squash commits that have already been pushed to a shared, public repository unless you coordinate with all collaborators, as it will require a force push (git push --force-with-lease or git push --force) and can lead to merge conflicts for others.
2. Always be cautious when rewriting history. If unsure, create a backup branch before starting the rebase.
3. Ensure the final squashed commit retains all necessary changes and a clear, descriptive commit message.

WHEN TO SQUASH

Squashing is ideal for:
1. Cleaning up local feature branches before merging them into a main branch.
2. Combining several small, incremental commits (e.g., 'WIP', 'fix typo', 'minor refactor') into a single, logical unit of work.
3. Simplifying pull requests by presenting a clean, easy-to-review history to maintainers.
4. Reverting complex changes more easily by having fewer, larger commits to revert.

INTERACTIVE REBASE PROCESS

When you run git rebase -i, Git opens your default text editor with a 'todo list'. Each line represents a commit, prefixed with 'pick'. To squash:
1. Change 'pick' to 'squash' (or 's') for commits you want to merge into the previous commit.
2. Change 'pick' to 'fixup' (or 'f') for commits you want to merge into the previous commit, discarding the current commit's message.
3. Save and close the editor. Git will then apply the changes, potentially opening another editor for you to refine the combined commit message(s).

HISTORY

The concept of squashing commits has been an integral part of Git's powerful interactive rebase functionality since its inception. While specific aliases or scripts named git-squash might appear in various workflows, the underlying capability to combine commits through 'squash' and 'fixup' commands within git rebase -i has been a core feature of Git for many years, enabling developers to maintain clean and linear project histories.

SEE ALSO

Copied to clipboard