5

I'm about to set up and automated build environment for a client. I want to push the Git repository to the client's build server, but without complete Git history.

I'm thinking about an approach with git checkout --orphan ci, but it's unclear to me how to work on a daily basis with a branch setup like this.

Maybe something like this (?):

  • New commits will be created on the master.
  • A feature is finished after several commits.
  • The ci branch is then rebased/merged (fast-forwarded) on the master.
  • ci branch is checked out.
  • The recent commits (which are not pushed to any server yet) are squashed to hide unnecessary history from the client.
  • The ci branch gets pushed to the build server.
  • ...

Is that a valid approach and/or does an easier way exists?

Alexander
  • 1,495
  • 2
  • 19
  • 24

2 Answers2

6

One simple way of managing this could be:

  • Work normally on master (or use any other feature branching model).
  • Every time you finish a feature and want to push it to the CI system you:

    • git checkout ci
    • git merge --squash master This will bring all of the changes in master to your ci branch.
    • git commit You will have a pre-populated commit message with all of the squashed commit messages. You can then edit this message to reflect all of the changes in the feature.
    • git push origin ci To send your changes to the CI system.

There are many branching models out there, but this should be simple enough and give you what you want.

I hope this helps.

mamapitufo
  • 4,680
  • 2
  • 25
  • 19
  • Thanks! And how do I create the `ci` branch? – Alexander Jul 10 '12 at 20:11
  • A simple `git checkout -b ci` should do. This will have all of the history in the repo up to now. If you don't want this, you can create the `ci` branch from the first commit. You can find the id of the first commit with something like `git log --reverse --pretty=oneline | head -1`. Then `git checkout -b ci `. At that point you can checkout the `ci` branch and do the first squashed merge from the master branch. – mamapitufo Jul 10 '12 at 20:25
  • Is it advisable to run `git checkout master && git merge ci` to have a reference for future squash merges? – Alexander Jul 11 '12 at 13:55
  • You can run `git merge master --squash -Xtheirs` while you are in the ci branch. The `-Xtheirs` will take the changes from master and overwrite any conflicts in ci. This should be fine as long as you don't use the ci branch for anything else other than pushing code from master to the CI system, – mamapitufo Jul 11 '12 at 21:01
  • @mampitufo But doesn't `git merge master` (even with `--squash`) make the history of `master` available from `ci`? This is what the OP said he wished to avoid: "I want to push the Git repository to the client's build server, but _without complete Git history_." – matt Feb 13 '14 at 00:12
  • @matt, no the history won't be available since you are squashing all of the changes into one commit. Check out the previous comments, there is a way of getting rid of the initial history in preparation for the first `ci` commit. – mamapitufo Feb 13 '14 at 09:26
  • @mamapitufo You are squashing the changes into one commit, but you are still just doing a merge. This means that this new (squashed) commit has the tip of the old `master` branch as one of its parents. This means that it is possible to follow the `master` branch history backwards from this new commit. The remote repo will still contain the entire history and it will still be possible to read it. – matt Feb 13 '14 at 16:03
  • @mamapitufo See for example this answer: http://stackoverflow.com/a/4020670/341994 "The tree contains the SHA of every blob in the tree." That is the fundamental nature of git! The solution proposed on that page is more the kind of thing the OP would need to do in order to hide the development history. As soon as you do a merge from `master` into `ci`, the whole previous history of `master` is available from `ci`. But that is what you have advised the OP to do. If the OP can see his history, so can the remote user of the same repo. – matt Feb 13 '14 at 16:13
  • @matt, maybe I can't explain myself clearly. Check this repo: https://github.com/mamapitufo/dotfiles where the `ci` branch has 3 milestones pulled from `master`, without showing `master`'s history. You need to understand that a `git merge --squash` will only merge the code, but it won't pull the commits from the branch you are merging. – mamapitufo Feb 13 '14 at 17:10
  • @mamapitufo What a great example! Thank you for helping me understand this. – matt Feb 13 '14 at 17:36
  • @matt no worries, glad I could help. Just for completeness sake, you could have 2 remotes on the repo: one for development (where `master` is) and another one for deployment, possibly under control of the client. The latter is where you would push `ci`. – mamapitufo Feb 13 '14 at 17:53
0

I'd look at something such as http://nvie.com/posts/a-successful-git-branching-model/

As for CI, you'll probably end up with pretty much the entire branch cloned/checkedout anyway, but unless you're putting in a bunch of large binaries I wouldn't worry too much about it.

Robert
  • 2,441
  • 21
  • 12