diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeTest.java index 8c5066af5..975e8c4f7 100644 --- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeTest.java +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, IBM Corporation and others. + * Copyright (C) 2012, 2014 IBM Corporation and others. * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -45,9 +45,12 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import java.util.Iterator; + import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.CLIRepositoryTestCase; import org.eclipse.jgit.merge.MergeStrategy; +import org.eclipse.jgit.revwalk.RevCommit; import org.junit.Before; import org.junit.Test; @@ -209,4 +212,24 @@ public void testFastForwardOnly() throws Exception { assertEquals("fatal: Not possible to fast-forward, aborting.", execute("git merge master --ff-only")[0]); } + + @Test + public void testMergeWithUserMessage() throws Exception { + git.branchCreate().setName("side").call(); + writeTrashFile("master", "content"); + git.add().addFilepattern("master").call(); + git.commit().setMessage("master commit").call(); + git.checkout().setName("side").call(); + writeTrashFile("side", "content"); + git.add().addFilepattern("side").call(); + git.commit().setMessage("side commit").call(); + + assertEquals("Merge made by the '" + MergeStrategy.RECURSIVE.getName() + + "' strategy.", + execute("git merge master -m \"user message\"")[0]); + + Iterator it = git.log().call().iterator(); + RevCommit newHead = it.next(); + assertEquals("user message", newHead.getFullMessage()); + } } diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties index d80145619..574981d38 100644 --- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties +++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties @@ -298,6 +298,7 @@ usage_mergeNoFf=Create a merge commit even when the merge resolves as a fast-for usage_mergeFfOnly=Refuse to merge and exit with a non-zero status unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward. usage_mergeRef=Ref to be merged usage_mergeStrategy=Use the given merge strategy. Can be supplied more than once to specify them in the order they should be tried. If there is no -s option, the recursive strategy is used. Currently the following strategies are supported: ours, theirs, simple-two-way-in-core, resolve, recursive +usage_message=Set the commit message to be used for the merge commit (in case one is created). usage_moveRenameABranch=move/rename a branch usage_nameStatus=show only name and status of files usage_noCheckoutAfterClone=no checkout of HEAD is performed after the clone is complete diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java index b3ff527eb..93c4388db 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, Christian Halstrick + * Copyright (C) 2011, 2014 Christian Halstrick * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -98,6 +98,9 @@ void ffonly(@SuppressWarnings("unused") final boolean ignored) { ff = FastForwardMode.FF_ONLY; } + @Option(name = "-m", usage = "usage_message") + private String message; + @Override protected void run() throws Exception { if (squash && ff == FastForwardMode.NO_FF) @@ -125,6 +128,10 @@ protected void run() throws Exception { mergeCmd.include(srcRef); else mergeCmd.include(src); + + if (message != null) + mergeCmd.setMessage(message); + MergeResult result; try { result = mergeCmd.call(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java index 1eeb9f7c0..761aafa3f 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2010, Stefan Lay - * Copyright (C) 2010-2012, Christian Halstrick + * Copyright (C) 2010-2014, Christian Halstrick * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -1566,6 +1566,69 @@ public void testRecursiveMergeWithConflict() throws Exception { assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus()); } + @Test + public void testMergeWithMessageOption() throws Exception { + Git git = new Git(db); + + writeTrashFile("a", "1\na\n3\n"); + git.add().addFilepattern("a").call(); + RevCommit initialCommit = git.commit().setMessage("initial").call(); + + createBranch(initialCommit, "refs/heads/side"); + checkoutBranch("refs/heads/side"); + + writeTrashFile("b", "1\nb\n3\n"); + git.add().addFilepattern("b").call(); + git.commit().setMessage("side").call(); + + checkoutBranch("refs/heads/master"); + + writeTrashFile("c", "1\nc\n3\n"); + git.add().addFilepattern("c").call(); + git.commit().setMessage("main").call(); + + Ref sideBranch = db.getRef("side"); + + git.merge().include(sideBranch).setStrategy(MergeStrategy.RESOLVE) + .setMessage("user message").call(); + + assertNull(db.readMergeCommitMsg()); + + Iterator it = git.log().call().iterator(); + RevCommit newHead = it.next(); + assertEquals("user message", newHead.getFullMessage()); + } + + @Test + public void testMergeConflictWithMessageOption() throws Exception { + Git git = new Git(db); + + writeTrashFile("a", "1\na\n3\n"); + git.add().addFilepattern("a").call(); + RevCommit initialCommit = git.commit().setMessage("initial").call(); + + createBranch(initialCommit, "refs/heads/side"); + checkoutBranch("refs/heads/side"); + + writeTrashFile("a", "1\na(side)\n3\n"); + git.add().addFilepattern("a").call(); + git.commit().setMessage("side").call(); + + checkoutBranch("refs/heads/master"); + + writeTrashFile("a", "1\na(main)\n3\n"); + git.add().addFilepattern("a").call(); + git.commit().setMessage("main").call(); + + Ref sideBranch = db.getRef("side"); + + git.merge().include(sideBranch).setStrategy(MergeStrategy.RESOLVE) + .setMessage("user message").call(); + + assertEquals("user message\n\nConflicts:\n\ta\n", + db.readMergeCommitMsg()); + } + private static void setExecutable(Git git, String path, boolean executable) { FS.DETECTED.setExecute( new File(git.getRepository().getWorkTree(), path), executable); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java index 6f0313dfd..0488a418a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2010, Christian Halstrick - * Copyright (C) 2010-2012, Stefan Lay + * Copyright (C) 2010-2014, Stefan Lay * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -104,6 +104,8 @@ public class MergeCommand extends GitCommand { private FastForwardMode fastForwardMode; + private String message; + /** * The modes available for fast forward merges corresponding to the * --ff, --no-ff and --ff-only @@ -313,7 +315,10 @@ public MergeResult call() throws GitAPIException, NoHeadException, } String mergeMessage = ""; //$NON-NLS-1$ if (!squash) { - mergeMessage = new MergeMessageFormatter().format( + if (message != null) + mergeMessage = message; + else + mergeMessage = new MergeMessageFormatter().format( commits, head); repo.writeMergeCommitMsg(mergeMessage); repo.writeMergeHeads(Arrays.asList(ref.getObjectId())); @@ -565,4 +570,18 @@ public MergeCommand setCommit(boolean commit) { this.commit = Boolean.valueOf(commit); return this; } + + /** + * Set the commit message to be used for the merge commit (in case one is + * created) + * + * @param message + * the message to be used for the merge commit + * @return {@code this} + * @since 3.5 + */ + public MergeCommand setMessage(String message) { + this.message = message; + return this; + } }