Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do cherry-pick and revert work?

I am trying to understand what merge and rebase do, in terms of set operations in math.

In the following, "-" means diff (similar to taking set difference in math, but "A-B" means those in A but not in B and minus those in B not in A), and "+" means patch (i.e. taking disjoint union in math. I haven't used patch before, so I am not sure).

From Version Control with Git, by Loeliger, 2ed

  1. The command git cherry-pick commit applies the changes introduced by the named commit on the current branch. It will introduce a new, distinct commit. Strictly speaking, using git cherry-pick doesn’t alter the existing history within a repository; instead, it adds to the history.

    enter image description here

    enter image description here

    Is it correct that F' = (F-B) + Z?

  2. The git revert commit command is substantially similar to the command git cherry-pick commit with one important difference: it applies the inverse of the given commit. Thus, this command is used to introduce a new commit that reverses the effects of a given commit.

    enter image description here

    enter image description here

    Is it correct that D' = G - D?

like image 819
Tim Avatar asked Jan 03 '16 00:01

Tim


1 Answers

With Git 2.29 (Q4 2020) addresses a similar situation

See commit 087c616, commit 409f066, commit 5065ce4 (20 Sep 2020) by brian m. carlson (bk2204).
(Merged by Junio C Hamano -- gitster -- in commit c5a8f1e, 29 Sep 2020)

docs: explain why reverts are not always applied on merge

Signed-off-by: brian m. carlson

A common scenario is for a user to apply a change to one branch and cherry-pick it into another, then later revert it in the first branch. This results in the change being present when the two branches are merged, which is confusing to many users.

We already have documentation for how this works in git merge(man), but it is clear from the frequency with which this is asked that it's hard to grasp.
We also don't explain to users that they are better off doing a rebase in this case, which will do what they intended.
Let's add an entry to the FAQ telling users what's happening and advising them to use rebase here.

gitfaq now includes in its man page:

If I make a change on two branches but revert it on one, why does the merge of those branches include the change?

By default, when Git does a merge, it uses a strategy called the recursive strategy, which does a fancy three-way merge.
In such a case, when Git performs the merge, it considers exactly three points: the two heads and a third point, called the merge base, which is usually the common ancestor of those commits.
Git does not consider the history or the individual commits that have happened on those branches at all.

As a result, if both sides have a change and one side has reverted that change, the result is to include the change.
This is because the code has changed on one side and there is no net change on the other, and in this scenario, Git adopts the change.

If this is a problem for you, you can do a rebase instead, rebasing the branch with the revert onto the other branch.
A rebase in this scenario will revert the change, because a rebase applies each individual commit, including the revert.
Note that rebases rewrite history, so you should avoid rebasing published branches unless you're sure you're comfortable with that.
See the NOTES section in git rebase for more details.

like image 57
VonC Avatar answered Oct 02 '22 14:10

VonC