RTFM

[Read This Fine Material] from Joshua Hoblitt

How to [nicely] merge a git template repo into an existing project

| 1 Comment

A few months ago I created a simple template of a Puppet forge module to make clones of when starting a new module due to puppet module generate ... leaving much to be manually edited/created. This is very handy when starting from scratch but makes a mess of the commit history if just merging it into an existing puppet module repo. It turns out that git does have the ability to squash all commits from a branch during a merge.

Start by adding git@github.com:jhoblitt/puppet-module_skel.git as a remote for an existing repo.

$ git clone ssh://git@bitbucket.org/.../puppet-yum_base.git
Cloning into 'puppet-yum_base'...
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (4/4), done.
$ cd puppet-yum_base
$ git remote add skel git@github.com:jhoblitt/puppet-module_skel.git
$ git fetch skel

warning: no common commits
remote: Counting objects: 13, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 13 (delta 0), reused 13 (delta 0)
Unpacking objects: 100% (13/13), done.
From github.com:jhoblitt/puppet-module_skel
 * [new branch]      master     -> skel/master
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/skel/master


Now we want to merge everything from remotes/skel/master into master with git merge but squash all the commits in remotes/skel/master while discarding anything merge changes that has a conflict in master.

Note that git merge --squash --commit -m"msg" will not cause a commit. It seems that with the --squash flag you must make a manual commit.

$ git merge --squash -s recursive -X ours remotes/skel/master
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
$ git status .
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#	new file:   .fixtures.yml
#	new file:   .gitignore
#	new file:   Gemfile
#	new file:   LICENSE
#	new file:   Modulefile
#	new file:   README.md
#	new file:   Rakefile
#	new file:   spec/spec_helper.rb
#
$ git commit -m"Merge puppet-module_skel"
[master 8ba5245] Merge puppet-module_skel
 8 files changed, 71 insertions(+)
 create mode 100644 .fixtures.yml
 create mode 100644 .gitignore
 create mode 100644 Gemfile
 create mode 100644 LICENSE
 create mode 100644 Modulefile
 create mode 100644 README.md
 create mode 100644 Rakefile
 create mode 100644 spec/spec_helper.rb

And we have a nice clean looking history that isn’t polluted with commit ids from the template repo.

$ git --no-pager log
commit 8ba5245a30775181ceb611a27fd79e3ad4a8d82c
Author: Joshua Hoblitt 
Date:   Mon Jun 3 11:48:26 2013 -0700

    Merge puppet-module_skel

commit 1a7c4ce1187c0ae35d249fc460b92af19d410e0b
Author: Joshua Hoblitt 
Date:   Mon Jun 3 11:08:51 2013 -0700

    first commit

Easy cut’n’paste version of the git commands:

git remote add skel git@github.com:jhoblitt/puppet-module_skel.git
git fetch skel
git merge --squash -s recursive -X ours remotes/skel/master
git commit -m"Merge puppet-module_skel"

One Comment

  1. Thanks a bunch for this nice, concise article! I was messing around with merge, rebase and squash for hours and still wasn’t able to figure out how to realise that specific workflow I intended to achieve. You saved my day! (and probably my weekend, as well) 😉

Leave a Reply