Example usage for org.eclipse.jgit.api Git merge

List of usage examples for org.eclipse.jgit.api Git merge

Introduction

In this page you can find the example usage for org.eclipse.jgit.api Git merge.

Prototype

public MergeCommand merge() 

Source Link

Document

Return a command object to execute a Merge command

Usage

From source file:br.com.riselabs.cotonet.builder.NetworkBuilder.java

License:Open Source License

/**
 * Returns the conflicting files of the given scenario.
 * /*ww  w  .j a  va 2 s .c o m*/
 * @param scenario
 * @return
 * @throws CheckoutConflictException
 * @throws GitAPIException
 */
private List<File> getConflictingFiles(MergeScenario scenario)
        throws CheckoutConflictException, GitAPIException {
    Git git = Git.wrap(getProject().getRepository());
    // this is for the cases of restarting after exception in a conflict
    // scenario analysis
    try {
        git.reset().setRef(scenario.getLeft().getName()).setMode(ResetType.HARD).call();
    } catch (JGitInternalException e) {
        Logger.log(log, "[" + project.getName() + "] JGit Reset Command ended with exception."
                + " Trying external reset command.");
        ExternalGitCommand egit = new ExternalGitCommand();
        try {
            egit.setType(CommandType.RESET).setDirectory(project.getRepository().getDirectory().getParentFile())
                    .call();
        } catch (BlameException e1) {
            Logger.logStackTrace(log, e1);
            return null;
        }
    }

    CheckoutCommand ckoutCmd = git.checkout();
    ckoutCmd.setName(scenario.getLeft().getName());
    ckoutCmd.setStartPoint(scenario.getLeft());
    ckoutCmd.call();

    MergeCommand mergeCmd = git.merge();
    mergeCmd.setCommit(false);
    mergeCmd.setStrategy(MergeStrategy.RECURSIVE);
    mergeCmd.include(scenario.getRight());

    Set<String> conflictingPaths;
    try {
        // dealing with MissingObjectException
        MergeResult mResult = mergeCmd.call();
        // dealing with Ghosts conflicts
        conflictingPaths = mResult.getConflicts().keySet();
    } catch (NullPointerException | JGitInternalException e) {
        StringBuilder sb = new StringBuilder();
        sb.append("[" + project.getName() + ":" + project.getUrl() + "] " + "Skipping merge scenario due to '"
                + e.getMessage() + "'\n");
        sb.append("--> Exception: " + e.getClass());
        sb.append("--> Skipped scenario:\n");
        sb.append("::Base:" + scenario.getBase().getName() + "\n");
        sb.append("::Left:" + scenario.getLeft().getName() + "\n");
        sb.append("::Right:" + scenario.getRight().getName() + "\n");
        Logger.log(log, sb.toString());
        return null;
    }
    List<File> result = new ArrayList<File>();
    for (String path : conflictingPaths) {
        result.add(new File(getProject().getRepository().getDirectory().getParent(), path));
    }
    return result;
}

From source file:br.com.riselabs.cotonet.test.helpers.ConflictBasedRepositoryTestCase.java

License:Open Source License

public MergeResult runMerge(MergeScenario scenario) throws RefAlreadyExistsException, RefNotFoundException,
        InvalidRefNameException, CheckoutConflictException, GitAPIException {
    Git git = Git.wrap(db);
    CheckoutCommand ckoutCmd = git.checkout();
    ckoutCmd.setName(scenario.getLeft().getName());
    ckoutCmd.setStartPoint(scenario.getLeft());
    ckoutCmd.call();//from  w w w .  j a va2s  . co  m

    MergeCommand mergeCmd = git.merge();
    mergeCmd.setCommit(false);
    mergeCmd.include(scenario.getRight());
    return mergeCmd.call();
}

From source file:br.com.riselabs.cotonet.test.helpers.ConflictBasedRepositoryTestCase.java

License:Open Source License

/**
 * Merges the scenario created by//w  ww  .  jav  a  2  s . c  o m
 * {@code #setCollaborationScenarioInBareRepository()} or
 * {@code #setCollaborationScenarioInTempRepository()} .
 * 
 * @throws Exception
 */
public void setResolvedMergeConflictScenario() throws Exception {
    MergeScenario ms = setCollaborationScenarioInTempRepository();
    Git git = Git.wrap(db);
    checkoutBranch("refs/heads/master");
    // Dev Y changes Bar
    git.merge().include(ms.getRight()).call();
    writeTrashFile("Bar.java", "1\n2\n3-merged\n4-merged\n5\n");
    writeTrashFile("Foo.java", "1\n2\n3\n4-merged\n5\n6\n7\n8\n");
    git.add().addFilepattern("Bar.java").addFilepattern("Foo.java").call();
    git.commit().setMessage("merge s3 into m3").setAuthor(devs.get("devY")).call();
}

From source file:com.barchart.jenkins.cascade.PluginScmGit.java

License:BSD License

/**
 * See {@link Git#merge()}/*from  www. ja  v a 2s .  c  o m*/
 */
public static MergeResult doMerge(final File workspace, final ObjectId commit) {
    try {
        final Git git = Git.open(workspace);
        return git.merge().include(commit).call();
    } catch (final Throwable e) {
        throw new RuntimeException(e);
    }
}

From source file:com.gitblit.servlet.GitServletTest.java

License:Apache License

private void testMergeCommitterVerification(boolean expectedSuccess) throws Exception {
    UserModel user = getUser();/*from   w w w.  ja va 2 s . c o  m*/

    delete(user);

    CredentialsProvider cp = new UsernamePasswordCredentialsProvider(user.username, user.password);

    // fork from original to a temporary bare repo
    File verification = new File(GitBlitSuite.REPOSITORIES, "refchecks/verify-committer.git");
    if (verification.exists()) {
        FileUtils.delete(verification, FileUtils.RECURSIVE);
    }
    CloneCommand clone = Git.cloneRepository();
    clone.setURI(MessageFormat.format("{0}/ticgit.git", url));
    clone.setDirectory(verification);
    clone.setBare(true);
    clone.setCloneAllBranches(true);
    clone.setCredentialsProvider(cp);
    GitBlitSuite.close(clone.call());

    // require push permissions and committer verification
    RepositoryModel model = repositories().getRepositoryModel("refchecks/verify-committer.git");
    model.authorizationControl = AuthorizationControl.NAMED;
    model.accessRestriction = AccessRestrictionType.PUSH;
    model.verifyCommitter = true;

    // grant user push permission
    user.setRepositoryPermission(model.name, AccessPermission.PUSH);

    gitblit().addUser(user);
    repositories().updateRepositoryModel(model.name, model, false);

    // clone temp bare repo to working copy
    File local = new File(GitBlitSuite.REPOSITORIES, "refchecks/verify-wc");
    if (local.exists()) {
        FileUtils.delete(local, FileUtils.RECURSIVE);
    }
    clone = Git.cloneRepository();
    clone.setURI(MessageFormat.format("{0}/{1}", url, model.name));
    clone.setDirectory(local);
    clone.setBare(false);
    clone.setCloneAllBranches(true);
    clone.setCredentialsProvider(cp);
    GitBlitSuite.close(clone.call());

    Git git = Git.open(local);

    // checkout a mergetest branch
    git.checkout().setCreateBranch(true).setName("mergetest").call();

    // change identity
    git.getRepository().getConfig().setString("user", null, "name", "mergetest");
    git.getRepository().getConfig().setString("user", null, "email", "mergetest@merge.com");
    git.getRepository().getConfig().save();

    // commit a file
    File file = new File(local, "MERGECHK2");
    OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file, true), Constants.CHARSET);
    BufferedWriter w = new BufferedWriter(os);
    w.write("// " + new Date().toString() + "\n");
    w.close();
    git.add().addFilepattern(file.getName()).call();
    RevCommit mergeTip = git.commit().setMessage(file.getName() + " test").call();

    // return to master
    git.checkout().setName("master").call();

    // restore identity
    if (expectedSuccess) {
        git.getRepository().getConfig().setString("user", null, "name", user.username);
        git.getRepository().getConfig().setString("user", null, "email", user.emailAddress);
        git.getRepository().getConfig().save();
    }

    // commit a file
    file = new File(local, "MERGECHK1");
    os = new OutputStreamWriter(new FileOutputStream(file, true), Constants.CHARSET);
    w = new BufferedWriter(os);
    w.write("// " + new Date().toString() + "\n");
    w.close();
    git.add().addFilepattern(file.getName()).call();
    git.commit().setMessage(file.getName() + " test").call();

    // merge the tip of the mergetest branch into master with --no-ff
    MergeResult mergeResult = git.merge().setFastForward(FastForwardMode.NO_FF).include(mergeTip.getId())
            .call();
    assertEquals(MergeResult.MergeStatus.MERGED, mergeResult.getMergeStatus());

    // push the merged master to the origin
    Iterable<PushResult> results = git.push().setCredentialsProvider(cp).setRemote("origin").call();

    for (PushResult result : results) {
        RemoteRefUpdate ref = result.getRemoteUpdate("refs/heads/master");
        Status status = ref.getStatus();
        if (expectedSuccess) {
            assertTrue("Verification failed! User was NOT able to push commit! " + status.name(),
                    Status.OK.equals(status));
        } else {
            assertTrue("Verification failed! User was able to push commit! " + status.name(),
                    Status.REJECTED_OTHER_REASON.equals(status));
        }
    }

    GitBlitSuite.close(git);
    // close serving repository
    GitBlitSuite.close(verification);
}

From source file:com.google.gerrit.server.change.IncludedInResolverTest.java

License:Apache License

@Override
@Before/* w  w  w  .  j a v a2  s . c  o m*/
public void setUp() throws Exception {
    super.setUp();

    /*- The following graph will be created.
            
      o   tag 2.5, 2.5_annotated, 2.5_annotated_twice
      |\
      | o tag 2.0.1
      | o tag 2.0
      o | tag 1.3
      |/
      o   c3
            
      | o tag 1.0.1
      |/
      o   tag 1.0
      o   c2
      o   c1
            
     */

    // TODO(dborowitz): Use try/finally when this doesn't double-close the repo.
    @SuppressWarnings("resource")
    Git git = new Git(db);
    revWalk = new RevWalk(db);
    // Version 1.0
    commit_initial = git.commit().setMessage("c1").call();
    git.commit().setMessage("c2").call();
    RevCommit commit_v1_0 = git.commit().setMessage("version 1.0").call();
    git.tag().setName(TAG_1_0).setObjectId(commit_v1_0).call();
    RevCommit c3 = git.commit().setMessage("c3").call();
    // Version 1.01
    createAndCheckoutBranch(commit_v1_0, BRANCH_1_0);
    RevCommit commit_v1_0_1 = git.commit().setMessage("verREFS_HEADS_RELsion 1.0.1").call();
    git.tag().setName(TAG_1_0_1).setObjectId(commit_v1_0_1).call();
    // Version 1.3
    createAndCheckoutBranch(c3, BRANCH_1_3);
    commit_v1_3 = git.commit().setMessage("version 1.3").call();
    git.tag().setName(TAG_1_3).setObjectId(commit_v1_3).call();
    // Version 2.0
    createAndCheckoutBranch(c3, BRANCH_2_0);
    RevCommit commit_v2_0 = git.commit().setMessage("version 2.0").call();
    git.tag().setName(TAG_2_0).setObjectId(commit_v2_0).call();
    RevCommit commit_v2_0_1 = git.commit().setMessage("version 2.0.1").call();
    git.tag().setName(TAG_2_0_1).setObjectId(commit_v2_0_1).call();

    // Version 2.5
    createAndCheckoutBranch(commit_v1_3, BRANCH_2_5);
    git.merge().include(commit_v2_0_1).setCommit(false).setFastForward(FastForwardMode.NO_FF).call();
    commit_v2_5 = git.commit().setMessage("version 2.5").call();
    git.tag().setName(TAG_2_5).setObjectId(commit_v2_5).setAnnotated(false).call();
    Ref ref_tag_2_5_annotated = git.tag().setName(TAG_2_5_ANNOTATED).setObjectId(commit_v2_5).setAnnotated(true)
            .call();
    RevTag tag_2_5_annotated = revWalk.parseTag(ref_tag_2_5_annotated.getObjectId());
    git.tag().setName(TAG_2_5_ANNOTATED_TWICE).setObjectId(tag_2_5_annotated).setAnnotated(true).call();
}

From source file:de.blizzy.documentr.page.CherryPicker.java

License:Open Source License

private List<CommitCherryPickResult> cherryPick(String projectName, String branchName, String path,
        List<String> commits, String targetBranch, Set<CommitCherryPickConflictResolve> conflictResolves,
        boolean dryRun, User user, Locale locale) throws IOException, GitAPIException {

    ILockedRepository repo = null;/*  w w  w. j a va 2  s.  com*/
    List<CommitCherryPickResult> cherryPickResults = Lists.newArrayList();
    boolean hadConflicts = false;
    boolean failed = false;
    try {
        repo = globalRepositoryManager.getProjectBranchRepository(projectName, targetBranch);

        String tempBranchName = "_temp_" + String.valueOf((long) (Math.random() * Long.MAX_VALUE)); //$NON-NLS-1$
        Git git = Git.wrap(repo.r());

        git.branchCreate().setName(tempBranchName).setStartPoint(targetBranch).call();

        git.checkout().setName(tempBranchName).call();

        for (String commit : commits) {
            PageVersion pageVersion = PageUtil.toPageVersion(CommitUtils.getCommit(repo.r(), commit));
            if (!hadConflicts) {
                CommitCherryPickResult singleCherryPickResult = cherryPick(repo, branchName, path, pageVersion,
                        targetBranch, conflictResolves, user, locale);
                if (singleCherryPickResult != null) {
                    cherryPickResults.add(singleCherryPickResult);
                    if (singleCherryPickResult.getStatus() == CommitCherryPickResult.Status.CONFLICT) {
                        hadConflicts = true;
                    }
                } else {
                    failed = true;
                    break;
                }
            } else {
                cherryPickResults
                        .add(new CommitCherryPickResult(pageVersion, CommitCherryPickResult.Status.UNKNOWN));
            }
        }

        if (hadConflicts || failed) {
            git.reset().setMode(ResetCommand.ResetType.HARD).call();
        }

        git.checkout().setName(targetBranch).call();

        if (!dryRun && !hadConflicts && !failed) {
            git.merge().include(repo.r().resolve(tempBranchName)).call();
        }

        git.branchDelete().setBranchNames(tempBranchName).setForce(true).call();

        if (failed) {
            throw new IOException("cherry-picking failed"); //$NON-NLS-1$
        }
    } finally {
        Closeables.closeQuietly(repo);
    }

    if (!dryRun && !hadConflicts && !failed) {
        eventBus.post(new PageChangedEvent(projectName, targetBranch, path));
    }

    return cherryPickResults;
}

From source file:de.blizzy.documentr.page.PageStore.java

License:Open Source License

private MergeConflict savePageInternal(String projectName, String branchName, String path, String suffix,
        Page page, String baseCommit, String rootDir, User user, ILockedRepository repo, boolean push)
        throws IOException, GitAPIException {

    Git git = Git.wrap(repo.r());

    String headCommit = CommitUtils.getHead(repo.r()).getName();
    if ((baseCommit != null) && headCommit.equals(baseCommit)) {
        baseCommit = null;/*from   w  w  w . j  a va2  s  . co  m*/
    }

    String editBranchName = "_edit_" + String.valueOf((long) (Math.random() * Long.MAX_VALUE)); //$NON-NLS-1$
    if (baseCommit != null) {
        git.branchCreate().setName(editBranchName).setStartPoint(baseCommit).call();

        git.checkout().setName(editBranchName).call();
    }

    Map<String, Object> metaMap = new HashMap<String, Object>();
    metaMap.put(TITLE, page.getTitle());
    metaMap.put(CONTENT_TYPE, page.getContentType());
    if (!page.getTags().isEmpty()) {
        metaMap.put(TAGS, page.getTags());
    }
    metaMap.put(VIEW_RESTRICTION_ROLE, page.getViewRestrictionRole());
    Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
    String json = gson.toJson(metaMap);
    File workingDir = RepositoryUtil.getWorkingDir(repo.r());
    File pagesDir = new File(workingDir, rootDir);
    File workingFile = Util.toFile(pagesDir, path + DocumentrConstants.META_SUFFIX);
    FileUtils.write(workingFile, json, Charsets.UTF_8);

    PageData pageData = page.getData();
    if (pageData != null) {
        workingFile = Util.toFile(pagesDir, path + suffix);
        FileUtils.writeByteArrayToFile(workingFile, pageData.getData());
    }

    AddCommand addCommand = git.add().addFilepattern(rootDir + "/" + path + DocumentrConstants.META_SUFFIX); //$NON-NLS-1$
    if (pageData != null) {
        addCommand.addFilepattern(rootDir + "/" + path + suffix); //$NON-NLS-1$
    }
    addCommand.call();

    PersonIdent ident = new PersonIdent(user.getLoginName(), user.getEmail());
    git.commit().setAuthor(ident).setCommitter(ident).setMessage(rootDir + "/" + path + suffix).call(); //$NON-NLS-1$

    MergeConflict conflict = null;

    if (baseCommit != null) {
        git.rebase().setUpstream(branchName).call();

        if (repo.r().getRepositoryState() != RepositoryState.SAFE) {
            String text = FileUtils.readFileToString(workingFile, Charsets.UTF_8);
            conflict = new MergeConflict(text, headCommit);

            git.rebase().setOperation(RebaseCommand.Operation.ABORT).call();
        }

        git.checkout().setName(branchName).call();

        if (conflict == null) {
            git.merge().include(repo.r().resolve(editBranchName)).call();
        }

        git.branchDelete().setBranchNames(editBranchName).setForce(true).call();
    }

    if (push && (conflict == null)) {
        git.push().call();
    }

    page.setParentPagePath(getParentPagePath(path, repo.r()));

    if (conflict == null) {
        PageUtil.updateProjectEditTime(projectName);
    }

    return conflict;
}

From source file:gov.va.isaac.sync.git.SyncServiceGIT.java

License:Apache License

/**
 * @throws MergeFailure/*from   w w  w .j  a  v a  2 s  .c o m*/
 * @throws AuthenticationException 
 * @see gov.va.isaac.interfaces.sync.ProfileSyncI#updateFromRemote(java.io.File, java.lang.String, java.lang.String,
 * gov.va.isaac.interfaces.sync.MergeFailOption)
 */
@Override
public Set<String> updateFromRemote(String username, String password, MergeFailOption mergeFailOption)
        throws IllegalArgumentException, IOException, MergeFailure, AuthenticationException {
    Set<String> filesChangedDuringPull;
    try {
        log.info("update from remote called ");

        Git git = getGit();

        log.debug("Fetching from remote");

        if (git.status().call().getConflicting().size() > 0) {
            log.info("Previous merge failure not yet resolved");
            throw new MergeFailure(git.status().call().getConflicting(), new HashSet<>());
        }

        CredentialsProvider cp = new UsernamePasswordCredentialsProvider(username,
                (password == null ? new char[] {} : password.toCharArray()));
        log.debug("Fetch Message" + git.fetch().setCredentialsProvider(cp).call().getMessages());

        ObjectId masterIdBeforeMerge = git.getRepository().getRef("master").getObjectId();
        if (git.getRepository().getRef("refs/remotes/origin/master").getObjectId().getName()
                .equals(masterIdBeforeMerge.getName())) {
            log.info("No changes to merge");
            return new HashSet<String>();
        }

        RevCommit stash = null;
        if (git.status().call().getUncommittedChanges().size() > 0) {
            log.info("Stashing uncommitted changes");
            stash = git.stashCreate().call();
        }

        {
            log.debug("Merging from remotes/origin/master");
            MergeResult mr = git.merge().include(git.getRepository().getRef("refs/remotes/origin/master"))
                    .call();
            AnyObjectId headAfterMergeID = mr.getNewHead();

            if (!mr.getMergeStatus().isSuccessful()) {
                if (mergeFailOption == null || MergeFailOption.FAIL == mergeFailOption) {
                    addNote(NOTE_FAILED_MERGE_HAPPENED_ON_REMOTE
                            + (stash == null ? ":NO_STASH" : STASH_MARKER + stash.getName()), git);
                    //We can use the status here - because we already stashed the stuff that they had uncommitted above.
                    throw new MergeFailure(mr.getConflicts().keySet(),
                            git.status().call().getUncommittedChanges());
                } else if (MergeFailOption.KEEP_LOCAL == mergeFailOption
                        || MergeFailOption.KEEP_REMOTE == mergeFailOption) {
                    HashMap<String, MergeFailOption> resolutions = new HashMap<>();
                    for (String s : mr.getConflicts().keySet()) {
                        resolutions.put(s, mergeFailOption);
                    }
                    log.debug("Resolving merge failures with option {}", mergeFailOption);
                    filesChangedDuringPull = resolveMergeFailures(MergeFailType.REMOTE_TO_LOCAL,
                            (stash == null ? null : stash.getName()), resolutions);
                } else {
                    throw new IllegalArgumentException("Unexpected option");
                }
            } else {
                //Conflict free merge - or perhaps, no merge at all.
                if (masterIdBeforeMerge.getName().equals(headAfterMergeID.getName())) {
                    log.debug("Merge didn't result in a commit - no incoming changes");
                    filesChangedDuringPull = new HashSet<>();
                } else {
                    filesChangedDuringPull = listFilesChangedInCommit(git.getRepository(), masterIdBeforeMerge,
                            headAfterMergeID);
                }
            }
        }

        if (stash != null) {
            log.info("Replaying stash");
            try {
                git.stashApply().setStashRef(stash.getName()).call();
                log.debug("stash applied cleanly, dropping stash");
                git.stashDrop().call();
            } catch (StashApplyFailureException e) {
                log.debug("Stash failed to merge");
                if (mergeFailOption == null || MergeFailOption.FAIL == mergeFailOption) {
                    addNote(NOTE_FAILED_MERGE_HAPPENED_ON_STASH, git);
                    throw new MergeFailure(git.status().call().getConflicting(), filesChangedDuringPull);
                }

                else if (MergeFailOption.KEEP_LOCAL == mergeFailOption
                        || MergeFailOption.KEEP_REMOTE == mergeFailOption) {
                    HashMap<String, MergeFailOption> resolutions = new HashMap<>();
                    for (String s : git.status().call().getConflicting()) {
                        resolutions.put(s, mergeFailOption);
                    }
                    log.debug("Resolving stash apply merge failures with option {}", mergeFailOption);
                    resolveMergeFailures(MergeFailType.STASH_TO_LOCAL, null, resolutions);
                    //When we auto resolve to KEEP_LOCAL - these files won't have really changed, even though we recorded a change above.
                    for (Entry<String, MergeFailOption> r : resolutions.entrySet()) {
                        if (MergeFailOption.KEEP_LOCAL == r.getValue()) {
                            filesChangedDuringPull.remove(r.getKey());
                        }
                    }
                } else {
                    throw new IllegalArgumentException("Unexpected option");
                }
            }
        }
        log.info("Files changed during updateFromRemote: {}", filesChangedDuringPull);
        return filesChangedDuringPull;
    } catch (CheckoutConflictException e) {
        log.error("Unexpected", e);
        throw new IOException(
                "A local file exists (but is not yet added to source control) which conflicts with a file from the server."
                        + "  Either delete the local file, or call addFile(...) on the offending file prior to attempting to update from remote.",
                e);
    } catch (TransportException te) {
        if (te.getMessage().contains("Auth fail")) {
            log.info("Auth fail", te);
            throw new AuthenticationException("Auth fail");
        } else {
            log.error("Unexpected", te);
            throw new IOException("Internal error", te);
        }
    } catch (GitAPIException e) {
        log.error("Unexpected", e);
        throw new IOException("Internal error", e);
    }
}

From source file:io.fabric8.git.internal.GitDataStore.java

License:Apache License

/**
 * Performs a pull so the git repo is pretty much up to date before we start performing operations on it.
 *
 * @param git                 The {@link Git} instance to use.
 * @param credentialsProvider The {@link CredentialsProvider} to use.
 * @param doDeleteBranches    Flag that determines if local branches that don't exist in remote should get deleted.
 *///  www. j  av  a 2s  . c  om
protected void doPull(Git git, CredentialsProvider credentialsProvider, boolean doDeleteBranches) {
    assertValid();
    try {
        Repository repository = git.getRepository();
        StoredConfig config = repository.getConfig();
        String url = config.getString("remote", remoteRef.get(), "url");
        if (Strings.isNullOrBlank(url)) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("No remote repository defined for the git repository at "
                        + GitHelpers.getRootGitDirectory(git) + " so not doing a pull");
            }
            return;
        }
        /*
        String branch = repository.getBranch();
        String mergeUrl = config.getString("branch", branch, "merge");
        if (Strings.isNullOrBlank(mergeUrl)) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("No merge spec for branch." + branch + ".merge in the git repository at "
                    + GitHelpers.getRootGitDirectory(git) + " so not doing a pull");
        }
        return;
        }
        */
        if (LOG.isDebugEnabled()) {
            LOG.debug("Performing a fetch in git repository " + GitHelpers.getRootGitDirectory(git)
                    + " on remote URL: " + url);
        }

        boolean hasChanged = false;
        try {
            FetchResult result = git.fetch().setTimeout(gitTimeout).setCredentialsProvider(credentialsProvider)
                    .setRemote(remoteRef.get()).call();
            if (LOG.isDebugEnabled()) {
                LOG.debug("Git fetch result: {}", result.getMessages());
            }
            lastFetchWarning = null;
        } catch (Exception ex) {
            String fetchWarning = ex.getMessage();
            if (!fetchWarning.equals(lastFetchWarning)) {
                LOG.warn("Fetch failed because of: " + fetchWarning);
                LOG.debug("Fetch failed - the error will be ignored", ex);
                lastFetchWarning = fetchWarning;
            }
            return;
        }

        // Get local and remote branches
        Map<String, Ref> localBranches = new HashMap<String, Ref>();
        Map<String, Ref> remoteBranches = new HashMap<String, Ref>();
        Set<String> gitVersions = new HashSet<String>();
        for (Ref ref : git.branchList().setListMode(ListBranchCommand.ListMode.ALL).call()) {
            if (ref.getName().startsWith("refs/remotes/" + remoteRef.get() + "/")) {
                String name = ref.getName().substring(("refs/remotes/" + remoteRef.get() + "/").length());
                remoteBranches.put(name, ref);
                gitVersions.add(name);
            } else if (ref.getName().startsWith("refs/heads/")) {
                String name = ref.getName().substring(("refs/heads/").length());
                localBranches.put(name, ref);
                gitVersions.add(name);
            }
        }

        // Check git commits
        for (String version : gitVersions) {
            // Delete unneeded local branches.
            //Check if any remote branches was found as a guard for unwanted deletions.
            if (remoteBranches.isEmpty()) {
                //Do nothing
            } else if (!remoteBranches.containsKey(version)) {
                //We never want to delete the master branch.
                if (doDeleteBranches && !version.equals(MASTER_BRANCH)) {
                    try {
                        git.branchDelete().setBranchNames(localBranches.get(version).getName()).setForce(true)
                                .call();
                    } catch (CannotDeleteCurrentBranchException ex) {
                        git.checkout().setName(MASTER_BRANCH).setForce(true).call();
                        git.branchDelete().setBranchNames(localBranches.get(version).getName()).setForce(true)
                                .call();
                    }
                    removeVersion(version);
                    hasChanged = true;
                }
            }
            // Create new local branches
            else if (!localBranches.containsKey(version)) {
                addVersion(version);
                git.checkout().setCreateBranch(true).setName(version)
                        .setStartPoint(remoteRef.get() + "/" + version)
                        .setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK).setForce(true).call();
                hasChanged = true;
            } else {
                String localCommit = localBranches.get(version).getObjectId().getName();
                String remoteCommit = remoteBranches.get(version).getObjectId().getName();
                if (!localCommit.equals(remoteCommit)) {
                    git.clean().setCleanDirectories(true).call();
                    git.checkout().setName("HEAD").setForce(true).call();
                    git.checkout().setName(version).setForce(true).call();
                    MergeResult result = git.merge().setStrategy(MergeStrategy.THEIRS)
                            .include(remoteBranches.get(version).getObjectId()).call();
                    if (result.getMergeStatus() != MergeResult.MergeStatus.ALREADY_UP_TO_DATE
                            && hasChanged(git, localCommit, remoteCommit)) {
                        hasChanged = true;
                    }
                    // TODO: handle conflicts
                }
            }
        }
        if (hasChanged) {
            LOG.debug("Changed after pull!");
            if (credentialsProvider != null) {
                // TODO lets test if the profiles directory is present after checking out version 1.0?
                getProfilesDirectory(git);
            }
            fireChangeNotifications();
        }
    } catch (Throwable ex) {
        LOG.debug("Failed to pull from the remote git repo " + GitHelpers.getRootGitDirectory(git), ex);
        LOG.warn("Failed to pull from the remote git repo " + GitHelpers.getRootGitDirectory(git) + " due "
                + ex.getMessage() + ". This exception is ignored.");
    }
}