]> source.dussan.org Git - jgit.git/commitdiff
Do not cherry-pick merge commits during rebase 48/10548/5
authorRobin Rosenberg <robin.rosenberg@dewire.com>
Wed, 20 Feb 2013 23:07:33 +0000 (00:07 +0100)
committerRobin Stocker <robin@nibor.org>
Fri, 8 Mar 2013 15:40:19 +0000 (16:40 +0100)
Rebase computes the list of commits that are included in
the merges, just like Git does, so do not try to include
the merge commits. Re-recreating merges during rebase is
a bit more complicated and might be a useful future extension,
but for now just linearize during rebase.

Change-Id: I61239d265f395e5ead580df2528e46393dc6bdbd
Signed-off-by: Robin Stocker <robin@nibor.org>
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java

index e08fa54d8ad36820c4ba1279e2f6a4506cb2bfa4..27f41b50ff51e669ef7a1dc1a707056a046d34c8 100644 (file)
@@ -42,6 +42,9 @@
  */
 package org.eclipse.jgit.api;
 
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -62,7 +65,6 @@ import org.eclipse.jgit.api.RebaseCommand.InteractiveHandler;
 import org.eclipse.jgit.api.RebaseCommand.Operation;
 import org.eclipse.jgit.api.RebaseCommand.Step;
 import org.eclipse.jgit.api.RebaseResult.Status;
-import org.eclipse.jgit.api.errors.JGitInternalException;
 import org.eclipse.jgit.api.errors.RefNotFoundException;
 import org.eclipse.jgit.api.errors.UnmergedPathsException;
 import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
@@ -161,72 +163,89 @@ public class RebaseCommandTest extends RepositoryTestCase {
                assertEquals(Status.FAST_FORWARD, res.getStatus());
        }
 
+       /**
+        * Create the following commits and then attempt to rebase topic onto
+        * master. This will serialize the branches.
+        *
+        * <pre>
+        * A - B (master)
+        *   \
+        *    C - D - F (topic)
+        *     \      /
+        *      E  -  (side)
+        * </pre>
+        *
+        * into
+        *
+        * <pre>
+        * A - B - (master)  C' - D' - E' (topic')
+        *   \
+        *    C - D - F (topic)
+        *     \      /
+        *      E  -  (side)
+        * </pre>
+        *
+        * @throws Exception
+        */
        @Test
-       public void testRebaseFailsCantCherryPickMergeCommits()
+       public void testRebaseShouldIgnoreMergeCommits()
                        throws Exception {
-               /**
-                * Create the following commits and then attempt to rebase topic onto
-                * master. This will fail as the cherry-pick list C, D, E an F contains
-                * a merge commit (F).
-                *
-                * <pre>
-                * A - B (master)
-                *   \
-                *    C - D - F (topic)
-                *     \      /
-                *      E  -  (side)
-                * </pre>
-                */
                // create file1 on master
                writeTrashFile(FILE1, FILE1);
                git.add().addFilepattern(FILE1).call();
-               RevCommit first = git.commit().setMessage("Add file1").call();
+               RevCommit a = git.commit().setMessage("Add file1").call();
                assertTrue(new File(db.getWorkTree(), FILE1).exists());
 
                // create a topic branch
-               createBranch(first, "refs/heads/topic");
+               createBranch(a, "refs/heads/topic");
 
                // update FILE1 on master
                writeTrashFile(FILE1, "blah");
                git.add().addFilepattern(FILE1).call();
-               git.commit().setMessage("updated file1 on master").call();
+               RevCommit b = git.commit().setMessage("updated file1 on master").call();
 
                checkoutBranch("refs/heads/topic");
                writeTrashFile("file3", "more changess");
                git.add().addFilepattern("file3").call();
-               RevCommit topicCommit = git.commit()
+               RevCommit c = git.commit()
                                .setMessage("update file3 on topic").call();
 
                // create a branch from the topic commit
-               createBranch(topicCommit, "refs/heads/side");
+               createBranch(c, "refs/heads/side");
 
                // second commit on topic
                writeTrashFile("file2", "file2");
                git.add().addFilepattern("file2").call();
-               git.commit().setMessage("Add file2").call();
+               RevCommit d = git.commit().setMessage("Add file2").call();
                assertTrue(new File(db.getWorkTree(), "file2").exists());
 
                // switch to side branch and update file2
                checkoutBranch("refs/heads/side");
                writeTrashFile("file3", "more change");
                git.add().addFilepattern("file3").call();
-               RevCommit sideCommit = git.commit().setMessage("update file2 on side")
+               RevCommit e = git.commit().setMessage("update file2 on side")
                                .call();
 
-               // switch back to topic and merge in side
+               // switch back to topic and merge in side, creating f
                checkoutBranch("refs/heads/topic");
-               MergeResult result = git.merge().include(sideCommit.getId())
+               MergeResult result = git.merge().include(e.getId())
                                .setStrategy(MergeStrategy.RESOLVE).call();
                assertEquals(MergeStatus.MERGED, result.getMergeStatus());
+               RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
+               assertEquals(Status.OK, res.getStatus());
 
-               try {
-                       RebaseResult rebase = git.rebase().setUpstream("refs/heads/master")
-                                       .call();
-                       fail("MultipleParentsNotAllowedException expected: "
-                                       + rebase.getStatus());
-               } catch (JGitInternalException e) {
-                       // expected
-               }
+               RevWalk rw = new RevWalk(db);
+               rw.markStart(rw.parseCommit(db.resolve("refs/heads/topic")));
+               assertDerivedFrom(rw.next(), e);
+               assertDerivedFrom(rw.next(), d);
+               assertDerivedFrom(rw.next(), c);
+               assertEquals(b, rw.next());
+               assertEquals(a, rw.next());
+       }
+
+       static void assertDerivedFrom(RevCommit derived, RevCommit original) {
+               assertThat(derived, not(equalTo(original)));
+               assertEquals(original.getFullMessage(), derived.getFullMessage());
        }
 
        @Test
index 5158c8533bcbb4a6dff37bee907c17a4157f69f1..a100c9d8781bc2e1129ecb6371bf63487d88da77 100644 (file)
@@ -640,11 +640,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
                List<RevCommit> cherryPickList = new ArrayList<RevCommit>();
                for (RevCommit commit : commitsToUse) {
                        if (commit.getParentCount() != 1)
-                               throw new JGitInternalException(
-                                               MessageFormat.format(
-                                                               JGitText.get().canOnlyCherryPickCommitsWithOneParent,
-                                                               commit.name(),
-                                                               Integer.valueOf(commit.getParentCount())));
+                               continue;
                        cherryPickList.add(commit);
                }