kiran thejo
kiran thejo

Reputation: 11

Git squash multiple commit versus reset to base commit

Suppose I have a Base commit B1 and on top of it I create local commits say C1,C2,C3. There are two ways for pushing the latest changes (C1,C2,C3) into git:-

  1. To squash C1,C2,C3 into one commit and push that as a single commit.
  2. To reset to old Base B1 (not hard) and create a new commit C4 which will have all the commits C1,C2,C3 included in it.

I want to know which way is better and which way is worse and why?

Upvotes: 1

Views: 634

Answers (1)

mnestorov
mnestorov

Reputation: 4484

I would assume that by squash you mean rebase n commits and then squash them.

So, the way I see it, here is what the different approaches offer.

1. Using reset

When you are using reset, what you are doing is moving what HEAD is pointing to.

Reset current HEAD to the specified state.

The first thing reset will do is move what HEAD points to. This isn’t the same as changing HEAD itself (which is what checkout does); reset moves the branch that HEAD is pointing to. This means if HEAD is set to the master branch (i.e. you’re currently on the master branch), running git reset 9e5e6a4 will start by making master point to 9e5e6a4.

Given the three parameters you can pass to the command, --soft --hard --mixed, you might completely loose your work, or you can have your changes in the "Changes to be committed" state.

The benefit of this approach is that it's easy and quick. You tell git where you want HEAD to point to, and the rest of the changes (in this case all 3 commits) would be mashed together into one big change. Then commit and push. Pretty easy.

The downside of this is that it gives you a limited control over your squash (because this is the goal of the operation, to squash). You don't see the commit hashes, you don't see the 3 commit messages, you are not given the option to re-order them, to reword/fixup any of the commits.

2. Using rebase

NOTE: Here I am talking about an interactive rebase, again with the idea to properly squash commits.

When you rebase interactively in git, you are given a list of all of the commits you have specified to rebase. They are ordered, formatted, and below them, you have a set of commands you can specify for each commit. Because we are interested in squashing, we can pick our commit to squash into, and the rest we can tag with squash.

What this allows us to do is to see the commits we are squashing. We can read the messages they have, we can see our history. At this point we might say that we actually want to reorder them, or to just reword the messages. Git gives us more flexibility to have the history we want to (although some might tell you that changing git history is a bad thing, and that argument sure has merit sometimes).

But even when we just want to squash all of the commits, git then makes us write a new commit message, and we can see all of the commit messages from the commits we want to squash. No need to hunt or remember previous messages.

The downside of this approach is that it might be more difficult to use the git-interactive menu and that it might take you a bit longer to do a squash.


Personally, I believe that both strategies work, but it feels like rebase-ing is more in-tune for squashing commits. It just depends in what situation you are in. If you think that you might be better off with resetting and re-committing, then go for that. But I think that using an interactive rebase might save you from messing things up in your history.


Edit I didn't see that the comments pointed out correctly that squashing is not the only way to push commits to your remote. Maybe that's the most straightforward and easy way :)

Upvotes: 2

Related Questions