Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git merge squash repeatedly

I'm trying to have two branches with binary files in git - one "development" and one "stable". The development branch can have several changes of these files before I want to "release" them to the stable branch (and the stable branch has those files renamed, in case that's relevant).

I could do a normal merge, this works fine, but preserves too much history - when pulling the "stable" branch, all intermediate commits from the "development" branch are pulled as well (because they're parent commits). But we're talking about binary files that don't have any sensible merging strategy (except theirs/ours), so the actual history of the files on the development branch is useless. When I pull the "stable" branch, I get this:

           X-------------------G stable          /                   /     a---b---c---d---e---f---g development 

Because G has a parent in the development branch, I get the whole history of the development branch (data objects for c, d, e, f and g) in my repository, which I'm not interested in (X is the same as b, with some file renaming applied).

So I tried to git merge --squash changes from the development branch to the stable branch. The first such merge and commit went OK, the results were as expected (nice change log in the commit message, no relation to the development branch):

          X-------------------G stable          /                        a---b---c---d---e---f---g development

After I pull this squashed stable branch, I get this in my repository, which is what I want:

 a---b---X---G 

But the second merge failed (because git had no way to know how much I merged already and got confused).

  • Is it possible to somehow record the merge, without producing a "merge commit" with two parents?
  • Or, is it possible to tell git to merge only a certain "range" of revisions, like in SVN?
  • Or, is it possible to do a normal merge without having to download all refs from the other branch when pulling?
  • Or should I provide a custom merge driver for the files in question, that simply renames "their" version to "our", thereby resolving the conflicts? I'm still afraid that --squash will always try to merge the whole history, up to the common parent, solving only half of my problem.

Update: rebasing

If I understand rebasing correctly, I'll end up with this:

                               X stable                              /     a---b---c---d---e---f---g development 

Which gets me all the data I'm not interested in (c, d, e, f) and as a bonus, I'll loose the information that b was a stable version in the branch.

Each development revision adds about 5MB to the repository size (and repacking the whole repo shrinks it only about 10%), the "stable" branch comes almost for free (the data is already there). I want pulling a single new revision from the stable branch to pull only the new 5MB, but instead updating from X to G downloads 25MB, because I'm somehow not able to say that I don't care about the contents of c, d, e and f.

like image 697
Kim Sullivan Avatar asked Sep 23 '09 08:09

Kim Sullivan


People also ask

How do you force merge squash?

Under your repository name, click Settings. Under "Pull Requests", optionally select Allow merge commits. This allows contributors to merge a pull request with a full history of commits. Under "Pull Requests", select Allow squash merging.

Is it better to squash and merge?

You should consider using squash if your team prefers a linear project history. This means that the history held by your main branch should not contain merges. A squash merge makes it possible to keep changes condensed to a single commit, supporting this strategy nicely.

What does Git merge -- squash do?

Squash merging is a merge option that allows you to condense the Git history of topic branches when you complete a pull request. Instead of each commit on the topic branch being added to the history of the default branch, a squash merge adds all the file changes to a single new commit on the default branch.

How would you squash multiple commits together using Git merge -- squash?

In case you are using the Tower Git client, using Interactive Rebase to squash some commits is very simple: just select the commits you want to combine, right-click any of them, and select the "Squash Revisions..." option from the contextual menu.


1 Answers

Starting with

      X stable      /                    a---b---c---d---e---f---g development 

You can use the following steps to copy the last commit from your development branch to your stable branch:

git checkout development@{0}  # get working tree from "development", detach HEAD git reset --soft stable  # reposition detached HEAD on "stable" git commit  # enter the appropriate commit message git branch temp  # create a temporary branch "temp" at HEAD git checkout temp  # get on the new temporary branch git branch -M stable  # rename "temp" to "stable" 

so you end up with:

      X-------------------G stable      /                    a---b---c---d---e---f---g development 

If you continue work on "development", e.g.,

      X-------------------G stable      /                    a---b---c---d---e---f---g---h---i---j development 

you can repeat the same git commands as above and you will end up with:

      X-------------------G-----------J stable      /                    a---b---c---d---e---f---g---h---i---j development 
like image 167
pvillela Avatar answered Oct 02 '22 14:10

pvillela