1

I've read about the unwanted side effects of cherry picking in regards to git history and ability to merge. However all examples I've come across assume that the branch, where a commit is cherry picked from, will continue to be actively developed-

In my case it is different. Since I am still learning about CICD (in particular in GitLab) I would often have the following approach:

  1. Create a project skeleton in my master or develop branch depending on how the project is managed
  2. Checkout a new branch for the CICD pipeline setup
  3. Experiment in that new branch until the pipeline is fully functional
  4. Merge back into the source branch (master or develop)
  5. Delete the branch for the pipeline

The problem here is that my playground branch is filled with commits such as "Added log message to debug error XYZ" or "Trying to adjust XYZ". The number of such commits can be astonishingly high (I am working on a Django project currently where this branch accumulated over 200 commits until the pipeline was finally working!). In the grand scheme of things this will create clutter in the git history, which I would like to avoid (not to mention it shows my incompetence in setting up a CICD pipeline :D).

I was thinking of using git cherry picking to just select the last commit and move it to the source branch thus leaving no trail behind. It is important to note that, while working on my pipeline setup branch, the source branch is not changed at all.

Will this break something in the git history of the branch that will receive the new data?

rbaleksandar
  • 8,713
  • 7
  • 76
  • 161
  • 2
    Maybe what you want here is rather an interactive rebase in which you squash down trivial commits into more meaningful ones. – Tim Biegeleisen May 13 '23 at 04:12
  • 1
    If you only cherry-pick the last commit, then what about all other changes from the commits that lead up to that last commit? Cherry-pick recreates a commit based on its changeset. It sounds like you want to do `merge --squash` (which will _not_ perform a real merge, but create a new commit with all changes). Interactive rebase, as already suggested, would be a very good idea too. If you throw away your old commits for good, there's nothing wrong with rebasing, squash-merging, or cherry-picking. – knittl May 13 '23 at 06:10
  • @knittl Small correction: `merge --squash` *does* perform a merge (with consequences like merge conflicts), but it does not create a merge commit. – j6t May 13 '23 at 07:13
  • @j6t yes, totally correct, thanks. That was not the best choice of words in my comment. Correction: it performs a real merge, but it creates a normal commit (single parent), not a merge commit (multiple parents) – which can cause problems down the line, but only if you keep working on the merged-in history – knittl May 13 '23 at 07:20
  • @knittl All previous commits in that branch are not important. I just want the final result to be in the git history of the master/develop branch and remove the branch where I experimented with the CICD. I will look into the rebase using squash. Haven't used it before. – rbaleksandar May 13 '23 at 11:42
  • @rbaleksandar Then a so-called squash is exactly what you want. :) – Guildenstern May 13 '23 at 12:29
  • Actually a soft reset, followed by a checkout of master/develop, adding the files and committing those did the trick perfectly fine. For the over 200 commits squashing would involve too much work in my case especially since I don't care about anything but the last commit. It does provide an alternative. – rbaleksandar May 13 '23 at 15:50

1 Answers1

2

A cherry-pick is the wrong option here, not because of unwanted side effects, but because it's missing desired effects.

A cherry-pick is roughly equivalent to making a patch of a particular change. It is useful, for instance, if you have a commit that fixes a typo in a file, on a branch that makes a whole bunch of other changes which are not ready yet. So you cherry-pick the typo fix into a new commit somewhere else.

You want the opposite: you want to include all the changes on a branch, regardless of which order they were committed in; but you want to shorten the history as though they were all changed at once. You want to keep the final state, not the most recent change.

This is referred to as squashing the commits, and can be achieved:

  • Using git merge --squash when you merge your branch to develop/master/wherever
  • Using git rebase -i and setting all but the first commit to "squash" or "fixup" (the difference being whether you want git to combine all the commit messages)
  • Using git reset --soft to rewind history but keep the final state of the files, then committing then in a fresh commit
IMSoP
  • 89,526
  • 13
  • 117
  • 169