public Commit GetCommit(string commitId) { //commitId = repository.Resolve(commitId).Name; //return Commits.Where(c => c.Id.StartsWith(commitId)).FirstOrDefault(); var id = repository.Resolve(commitId); if (id == null) { return(null); } RevWalk walk = new RevWalk(repository); RevCommit commit = walk.ParseCommit(id); walk.Dispose(); return(commit == null || commit.Tree == null ? null : new Commit { Id = commit.Id.Name, ParentIds = commit.Parents.Select(p => p.Id.Name).ToList(), CommitDateRelative = RelativeDateFormatter.Format(commit.GetAuthorIdent().GetWhen()), CommitterName = commit.GetCommitterIdent().GetName(), CommitterEmail = commit.GetCommitterIdent().GetEmailAddress(), CommitDate = commit.GetCommitterIdent().GetWhen(), Message = commit.GetShortMessage(), }); }
public virtual void LogAllCommitsWithSkip() { Git git = Git.Wrap(db); IList <RevCommit> commits = CreateCommits(git); Iterator <RevCommit> log = git.Log().All().SetSkip(1).Call().Iterator(); NUnit.Framework.Assert.IsTrue(log.HasNext()); RevCommit commit = log.Next(); NUnit.Framework.Assert.IsTrue(commits.Contains(commit)); NUnit.Framework.Assert.AreEqual("commit#2", commit.GetShortMessage()); NUnit.Framework.Assert.IsTrue(log.HasNext()); commit = log.Next(); NUnit.Framework.Assert.IsTrue(commits.Contains(commit)); NUnit.Framework.Assert.AreEqual("commit#1", commit.GetShortMessage()); NUnit.Framework.Assert.IsFalse(log.HasNext()); }
private static Commit ToCommit(RevCommit commit, Repository repository) { return(new Commit ( repository, commit.Name, commit.GetShortMessage(), ToPerson(commit.GetAuthorIdent()), ToPerson(commit.GetCommitterIdent()), commit.GetCommitterIdent().GetWhen(), commit.Parents.Select(p => p.Name) )); }
public virtual void LogPathWithMaxCount() { Git git = Git.Wrap(db); IList <RevCommit> commits = CreateCommits(git); Iterator <RevCommit> log = git.Log().AddPath("Test.txt").SetMaxCount(1).Call().Iterator (); NUnit.Framework.Assert.IsTrue(log.HasNext()); RevCommit commit = log.Next(); NUnit.Framework.Assert.IsTrue(commits.Contains(commit)); NUnit.Framework.Assert.AreEqual("commit#2", commit.GetShortMessage()); NUnit.Framework.Assert.IsFalse(log.HasNext()); }
/// <exception cref="NGit.Api.Errors.RefAlreadyExistsException"> /// when trying to create (without force) a branch with a name /// that already exists /// </exception> /// <exception cref="NGit.Api.Errors.RefNotFoundException">if the start point can not be found /// </exception> /// <exception cref="NGit.Api.Errors.InvalidRefNameException"> /// if the provided name is <code>null</code> or otherwise /// invalid /// </exception> /// <returns>the newly created branch</returns> /// <exception cref="NGit.Api.Errors.GitAPIException"></exception> public override Ref Call() { CheckCallable(); ProcessOptions(); RevWalk revWalk = new RevWalk(repo); try { Ref refToCheck = repo.GetRef(name); bool exists = refToCheck != null && refToCheck.GetName().StartsWith(Constants.R_HEADS ); if (!force && exists) { throw new RefAlreadyExistsException(MessageFormat.Format(JGitText.Get().refAlreadyExists1 , name)); } ObjectId startAt = GetStartPoint(); string startPointFullName = null; if (startPoint != null) { Ref baseRef = repo.GetRef(startPoint); if (baseRef != null) { startPointFullName = baseRef.GetName(); } } // determine whether we are based on a commit, // a branch, or a tag and compose the reflog message string refLogMessage; string baseBranch = string.Empty; if (startPointFullName == null) { string baseCommit; if (startCommit != null) { baseCommit = startCommit.GetShortMessage(); } else { RevCommit commit = revWalk.ParseCommit(repo.Resolve(startPoint)); baseCommit = commit.GetShortMessage(); } if (exists) { refLogMessage = "branch: Reset start-point to commit " + baseCommit; } else { refLogMessage = "branch: Created from commit " + baseCommit; } } else { if (startPointFullName.StartsWith(Constants.R_HEADS) || startPointFullName.StartsWith (Constants.R_REMOTES)) { baseBranch = startPointFullName; if (exists) { refLogMessage = "branch: Reset start-point to branch " + startPointFullName; } else { // TODO refLogMessage = "branch: Created from branch " + baseBranch; } } else { startAt = revWalk.Peel(revWalk.ParseAny(startAt)); if (exists) { refLogMessage = "branch: Reset start-point to tag " + startPointFullName; } else { refLogMessage = "branch: Created from tag " + startPointFullName; } } } RefUpdate updateRef = repo.UpdateRef(Constants.R_HEADS + name); updateRef.SetNewObjectId(startAt); updateRef.SetRefLogMessage(refLogMessage, false); RefUpdate.Result updateResult; if (exists && force) { updateResult = updateRef.ForceUpdate(); } else { updateResult = updateRef.Update(); } SetCallable(false); bool ok = false; switch (updateResult) { case RefUpdate.Result.NEW: { ok = !exists; break; } case RefUpdate.Result.NO_CHANGE: case RefUpdate.Result.FAST_FORWARD: case RefUpdate.Result.FORCED: { ok = exists; break; } default: { break; break; } } if (!ok) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().createBranchUnexpectedResult , updateResult.ToString())); } Ref result = repo.GetRef(name); if (result == null) { throw new JGitInternalException(JGitText.Get().createBranchFailedUnknownReason); } if (baseBranch.Length == 0) { return(result); } // if we are based on another branch, see // if we need to configure upstream configuration: first check // whether the setting was done explicitly bool doConfigure; if (upstreamMode == CreateBranchCommand.SetupUpstreamMode.SET_UPSTREAM || upstreamMode == CreateBranchCommand.SetupUpstreamMode.TRACK) { // explicitly set to configure doConfigure = true; } else { if (upstreamMode == CreateBranchCommand.SetupUpstreamMode.NOTRACK) { // explicitly set to not configure doConfigure = false; } else { // if there was no explicit setting, check the configuration string autosetupflag = repo.GetConfig().GetString(ConfigConstants.CONFIG_BRANCH_SECTION , null, ConfigConstants.CONFIG_KEY_AUTOSETUPMERGE); if ("false".Equals(autosetupflag)) { doConfigure = false; } else { if ("always".Equals(autosetupflag)) { doConfigure = true; } else { // in this case, the default is to configure // only in case the base branch was a remote branch doConfigure = baseBranch.StartsWith(Constants.R_REMOTES); } } } } if (doConfigure) { StoredConfig config = repo.GetConfig(); string[] tokens = baseBranch.RegexSplit("/", 4); bool isRemote = tokens[1].Equals("remotes"); if (isRemote) { // refs/remotes/<remote name>/<branch> string remoteName = tokens[2]; string branchName = tokens[3]; config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_REMOTE , remoteName); config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_MERGE , Constants.R_HEADS + branchName); } else { // set "." as remote config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_REMOTE , "."); config.SetString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_MERGE , baseBranch); } config.Save(); } return(result); } catch (IOException ioe) { throw new JGitInternalException(ioe.Message, ioe); } finally { revWalk.Release(); } }
/// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception> /// <exception cref="System.IO.IOException"></exception> /// <exception cref="NGit.Api.Errors.NoHeadException"></exception> /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception> private RebaseResult InitFilesAndRewind() { // we need to store everything into files so that we can implement // --skip, --continue, and --abort // first of all, we determine the commits to be applied IList <RevCommit> cherryPickList = new AList <RevCommit>(); Ref head = repo.GetRef(Constants.HEAD); if (head == null || head.GetObjectId() == null) { throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved , Constants.HEAD)); } string headName; if (head.IsSymbolic()) { headName = head.GetTarget().GetName(); } else { headName = "detached HEAD"; } ObjectId headId = head.GetObjectId(); if (headId == null) { throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved , Constants.HEAD)); } RevCommit headCommit = walk.LookupCommit(headId); monitor.BeginTask(JGitText.Get().obtainingCommitsForCherryPick, ProgressMonitor.UNKNOWN ); LogCommand cmd = new Git(repo).Log().AddRange(upstreamCommit, headCommit); Iterable <RevCommit> commitsToUse = cmd.Call(); foreach (RevCommit commit in commitsToUse) { cherryPickList.AddItem(commit); } // if the upstream commit is in a direct line to the current head, // the log command will not report any commits; in this case, // we create the cherry-pick list ourselves if (cherryPickList.IsEmpty()) { Iterable <RevCommit> parents = new Git(repo).Log().Add(upstreamCommit).Call(); foreach (RevCommit parent in parents) { if (parent.Equals(headCommit)) { break; } if (parent.ParentCount != 1) { throw new JGitInternalException(JGitText.Get().canOnlyCherryPickCommitsWithOneParent ); } cherryPickList.AddItem(parent); } } // nothing to do: return with UP_TO_DATE_RESULT if (cherryPickList.IsEmpty()) { return(RebaseResult.UP_TO_DATE_RESULT); } Sharpen.Collections.Reverse(cherryPickList); // create the folder for the meta information FileUtils.Mkdir(rebaseDir); CreateFile(repo.Directory, Constants.ORIG_HEAD, headId.Name); CreateFile(rebaseDir, REBASE_HEAD, headId.Name); CreateFile(rebaseDir, HEAD_NAME, headName); CreateFile(rebaseDir, ONTO, upstreamCommit.Name); CreateFile(rebaseDir, INTERACTIVE, string.Empty); BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream (new FilePath(rebaseDir, GIT_REBASE_TODO)), Constants.CHARACTER_ENCODING)); fw.Write("# Created by EGit: rebasing " + upstreamCommit.Name + " onto " + headId .Name); fw.NewLine(); try { StringBuilder sb = new StringBuilder(); ObjectReader reader = walk.GetObjectReader(); foreach (RevCommit commit_1 in cherryPickList) { sb.Length = 0; sb.Append(RebaseCommand.Action.PICK.ToToken()); sb.Append(" "); sb.Append(reader.Abbreviate(commit_1).Name); sb.Append(" "); sb.Append(commit_1.GetShortMessage()); fw.Write(sb.ToString()); fw.NewLine(); } } finally { fw.Close(); } monitor.EndTask(); // we rewind to the upstream commit monitor.BeginTask(MessageFormat.Format(JGitText.Get().rewinding, upstreamCommit.GetShortMessage ()), ProgressMonitor.UNKNOWN); CheckoutCommit(upstreamCommit); monitor.EndTask(); return(null); }
/// <summary> /// Executes the /// <code>Rebase</code> /// command with all the options and parameters /// collected by the setter methods of this class. Each instance of this /// class should only be used for one invocation of the command. Don't call /// this method twice on an instance. /// </summary> /// <returns>an object describing the result of this command</returns> /// <exception cref="NGit.Api.Errors.NoHeadException"></exception> /// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception> /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception> /// <exception cref="NGit.Api.Errors.GitAPIException"></exception> public override RebaseResult Call() { RevCommit newHead = null; bool lastStepWasForward = false; CheckCallable(); CheckParameters(); try { switch (operation) { case RebaseCommand.Operation.ABORT: { try { return(Abort()); } catch (IOException ioe) { throw new JGitInternalException(ioe.Message, ioe); } goto case RebaseCommand.Operation.SKIP; } case RebaseCommand.Operation.SKIP: case RebaseCommand.Operation.CONTINUE: { // fall through string upstreamCommitName = ReadFile(rebaseDir, ONTO); this.upstreamCommit = walk.ParseCommit(repo.Resolve(upstreamCommitName)); break; } case RebaseCommand.Operation.BEGIN: { RebaseResult res = InitFilesAndRewind(); if (res != null) { return(res); } break; } } if (monitor.IsCancelled()) { return(Abort()); } if (this.operation == RebaseCommand.Operation.CONTINUE) { newHead = ContinueRebase(); } if (this.operation == RebaseCommand.Operation.SKIP) { newHead = CheckoutCurrentHead(); } ObjectReader or = repo.NewObjectReader(); IList <RebaseCommand.Step> steps = LoadSteps(); foreach (RebaseCommand.Step step in steps) { PopSteps(1); ICollection <ObjectId> ids = or.Resolve(step.commit); if (ids.Count != 1) { throw new JGitInternalException("Could not resolve uniquely the abbreviated object ID" ); } RevCommit commitToPick = walk.ParseCommit(ids.Iterator().Next()); if (monitor.IsCancelled()) { return(new RebaseResult(commitToPick)); } monitor.BeginTask(MessageFormat.Format(JGitText.Get().applyingCommit, commitToPick .GetShortMessage()), ProgressMonitor.UNKNOWN); // if the first parent of commitToPick is the current HEAD, // we do a fast-forward instead of cherry-pick to avoid // unnecessary object rewriting newHead = TryFastForward(commitToPick); lastStepWasForward = newHead != null; if (!lastStepWasForward) { // TODO if the content of this commit is already merged here // we should skip this step in order to avoid confusing // pseudo-changed newHead = new Git(repo).CherryPick().Include(commitToPick).Call(); } monitor.EndTask(); if (newHead == null) { return(Stop(commitToPick)); } } if (newHead != null) { // point the previous head (if any) to the new commit string headName = ReadFile(rebaseDir, HEAD_NAME); if (headName.StartsWith(Constants.R_REFS)) { RefUpdate rup = repo.UpdateRef(headName); rup.SetNewObjectId(newHead); RefUpdate.Result res_1 = rup.ForceUpdate(); switch (res_1) { case RefUpdate.Result.FAST_FORWARD: case RefUpdate.Result.FORCED: case RefUpdate.Result.NO_CHANGE: { break; } default: { throw new JGitInternalException("Updating HEAD failed"); } } rup = repo.UpdateRef(Constants.HEAD); res_1 = rup.Link(headName); switch (res_1) { case RefUpdate.Result.FAST_FORWARD: case RefUpdate.Result.FORCED: case RefUpdate.Result.NO_CHANGE: { break; } default: { throw new JGitInternalException("Updating HEAD failed"); } } } FileUtils.Delete(rebaseDir, FileUtils.RECURSIVE); if (lastStepWasForward) { return(new RebaseResult(RebaseResult.Status.FAST_FORWARD)); } return(new RebaseResult(RebaseResult.Status.OK)); } return(new RebaseResult(RebaseResult.Status.UP_TO_DATE)); } catch (IOException ioe) { throw new JGitInternalException(ioe.Message, ioe); } }
/// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception> /// <exception cref="System.IO.IOException"></exception> /// <exception cref="NGit.Api.Errors.NoHeadException"></exception> /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception> private RebaseResult InitFilesAndRewind() { // we need to store everything into files so that we can implement // --skip, --continue, and --abort Ref head = repo.GetRef(Constants.HEAD); if (head == null || head.GetObjectId() == null) { throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved , Constants.HEAD)); } string headName; if (head.IsSymbolic()) { headName = head.GetTarget().GetName(); } else { headName = "detached HEAD"; } ObjectId headId = head.GetObjectId(); if (headId == null) { throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved , Constants.HEAD)); } RevCommit headCommit = walk.LookupCommit(headId); RevCommit upstream = walk.LookupCommit(upstreamCommit.Id); if (walk.IsMergedInto(upstream, headCommit)) { return(RebaseResult.UP_TO_DATE_RESULT); } else { if (walk.IsMergedInto(headCommit, upstream)) { // head is already merged into upstream, fast-foward monitor.BeginTask(MessageFormat.Format(JGitText.Get().resettingHead, upstreamCommit .GetShortMessage()), ProgressMonitor.UNKNOWN); CheckoutCommit(upstreamCommit); monitor.EndTask(); UpdateHead(headName, upstreamCommit); return(RebaseResult.FAST_FORWARD_RESULT); } } monitor.BeginTask(JGitText.Get().obtainingCommitsForCherryPick, ProgressMonitor.UNKNOWN ); // determine the commits to be applied LogCommand cmd = new Git(repo).Log().AddRange(upstreamCommit, headCommit); Iterable <RevCommit> commitsToUse = cmd.Call(); IList <RevCommit> cherryPickList = new AList <RevCommit>(); foreach (RevCommit commit in commitsToUse) { if (commit.ParentCount != 1) { throw new JGitInternalException(JGitText.Get().canOnlyCherryPickCommitsWithOneParent ); } cherryPickList.AddItem(commit); } Sharpen.Collections.Reverse(cherryPickList); // create the folder for the meta information FileUtils.Mkdir(rebaseDir); CreateFile(repo.Directory, Constants.ORIG_HEAD, headId.Name); CreateFile(rebaseDir, REBASE_HEAD, headId.Name); CreateFile(rebaseDir, HEAD_NAME, headName); CreateFile(rebaseDir, ONTO, upstreamCommit.Name); CreateFile(rebaseDir, INTERACTIVE, string.Empty); BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream (new FilePath(rebaseDir, GIT_REBASE_TODO)), Constants.CHARACTER_ENCODING)); fw.Write("# Created by EGit: rebasing " + upstreamCommit.Name + " onto " + headId .Name); fw.NewLine(); try { StringBuilder sb = new StringBuilder(); ObjectReader reader = walk.GetObjectReader(); foreach (RevCommit commit_1 in cherryPickList) { sb.Length = 0; sb.Append(RebaseCommand.Action.PICK.ToToken()); sb.Append(" "); sb.Append(reader.Abbreviate(commit_1).Name); sb.Append(" "); sb.Append(commit_1.GetShortMessage()); fw.Write(sb.ToString()); fw.NewLine(); } } finally { fw.Close(); } monitor.EndTask(); // we rewind to the upstream commit monitor.BeginTask(MessageFormat.Format(JGitText.Get().rewinding, upstreamCommit.GetShortMessage ()), ProgressMonitor.UNKNOWN); bool checkoutOk = false; try { checkoutOk = CheckoutCommit(upstreamCommit); } finally { if (!checkoutOk) { FileUtils.Delete(rebaseDir, FileUtils.RECURSIVE); } } monitor.EndTask(); return(null); }
/// <summary> /// Executes the /// <code>Rebase</code> /// command with all the options and parameters /// collected by the setter methods of this class. Each instance of this /// class should only be used for one invocation of the command. Don't call /// this method twice on an instance. /// </summary> /// <returns>an object describing the result of this command</returns> /// <exception cref="NGit.Api.Errors.NoHeadException"></exception> /// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception> /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception> /// <exception cref="NGit.Api.Errors.GitAPIException"></exception> public override RebaseResult Call() { RevCommit newHead = null; bool lastStepWasForward = false; CheckCallable(); CheckParameters(); try { switch (operation) { case RebaseCommand.Operation.ABORT: { try { return(Abort(RebaseResult.ABORTED_RESULT)); } catch (IOException ioe) { throw new JGitInternalException(ioe.Message, ioe); } goto case RebaseCommand.Operation.SKIP; } case RebaseCommand.Operation.SKIP: case RebaseCommand.Operation.CONTINUE: { // fall through string upstreamCommitName = ReadFile(rebaseDir, ONTO); this.upstreamCommit = walk.ParseCommit(repo.Resolve(upstreamCommitName)); break; } case RebaseCommand.Operation.BEGIN: { RebaseResult res = InitFilesAndRewind(); if (res != null) { return(res); } break; } } if (monitor.IsCancelled()) { return(Abort(RebaseResult.ABORTED_RESULT)); } if (operation == RebaseCommand.Operation.CONTINUE) { newHead = ContinueRebase(); } if (operation == RebaseCommand.Operation.SKIP) { newHead = CheckoutCurrentHead(); } ObjectReader or = repo.NewObjectReader(); IList <RebaseCommand.Step> steps = LoadSteps(); foreach (RebaseCommand.Step step in steps) { PopSteps(1); ICollection <ObjectId> ids = or.Resolve(step.commit); if (ids.Count != 1) { throw new JGitInternalException("Could not resolve uniquely the abbreviated object ID" ); } RevCommit commitToPick = walk.ParseCommit(ids.Iterator().Next()); if (monitor.IsCancelled()) { return(new RebaseResult(commitToPick)); } try { monitor.BeginTask(MessageFormat.Format(JGitText.Get().applyingCommit, commitToPick .GetShortMessage()), ProgressMonitor.UNKNOWN); // if the first parent of commitToPick is the current HEAD, // we do a fast-forward instead of cherry-pick to avoid // unnecessary object rewriting newHead = TryFastForward(commitToPick); lastStepWasForward = newHead != null; if (!lastStepWasForward) { // TODO if the content of this commit is already merged // here we should skip this step in order to avoid // confusing pseudo-changed CherryPickResult cherryPickResult = new Git(repo).CherryPick().Include(commitToPick ).Call(); switch (cherryPickResult.GetStatus()) { case CherryPickResult.CherryPickStatus.FAILED: { if (operation == RebaseCommand.Operation.BEGIN) { return(Abort(new RebaseResult(cherryPickResult.GetFailingPaths()))); } else { return(Stop(commitToPick)); } goto case CherryPickResult.CherryPickStatus.CONFLICTING; } case CherryPickResult.CherryPickStatus.CONFLICTING: { return(Stop(commitToPick)); } case CherryPickResult.CherryPickStatus.OK: { newHead = cherryPickResult.GetNewHead(); break; } } } } finally { monitor.EndTask(); } } if (newHead != null) { string headName = ReadFile(rebaseDir, HEAD_NAME); UpdateHead(headName, newHead); FileUtils.Delete(rebaseDir, FileUtils.RECURSIVE); if (lastStepWasForward) { return(RebaseResult.FAST_FORWARD_RESULT); } return(RebaseResult.OK_RESULT); } return(RebaseResult.FAST_FORWARD_RESULT); } catch (IOException ioe) { throw new JGitInternalException(ioe.Message, ioe); } }
/// <summary> /// Executes the /// <code>Cherry-Pick</code> /// command with all the options and /// parameters collected by the setter methods (e.g. /// <see cref="Include(NGit.Ref)">Include(NGit.Ref)</see> /// of /// this class. Each instance of this class should only be used for one /// invocation of the command. Don't call this method twice on an instance. /// </summary> /// <returns>the result of the cherry-pick</returns> /// <exception cref="NGit.Api.Errors.GitAPIException">NGit.Api.Errors.GitAPIException /// </exception> /// <exception cref="NGit.Api.Errors.WrongRepositoryStateException">NGit.Api.Errors.WrongRepositoryStateException /// </exception> /// <exception cref="NGit.Api.Errors.ConcurrentRefUpdateException">NGit.Api.Errors.ConcurrentRefUpdateException /// </exception> /// <exception cref="NGit.Api.Errors.UnmergedPathsException">NGit.Api.Errors.UnmergedPathsException /// </exception> /// <exception cref="NGit.Api.Errors.NoMessageException">NGit.Api.Errors.NoMessageException /// </exception> /// <exception cref="NGit.Api.Errors.NoHeadException">NGit.Api.Errors.NoHeadException /// </exception> public override CherryPickResult Call() { RevCommit newHead = null; IList <Ref> cherryPickedRefs = new List <Ref>(); CheckCallable(); RevWalk revWalk = new RevWalk(repo); try { // get the head commit Ref headRef = repo.GetRef(Constants.HEAD); if (headRef == null) { throw new NoHeadException(JGitText.Get().commitOnRepoWithoutHEADCurrentlyNotSupported ); } RevCommit headCommit = revWalk.ParseCommit(headRef.GetObjectId()); newHead = headCommit; // loop through all refs to be cherry-picked foreach (Ref src in commits) { // get the commit to be cherry-picked // handle annotated tags ObjectId srcObjectId = src.GetPeeledObjectId(); if (srcObjectId == null) { srcObjectId = src.GetObjectId(); } RevCommit srcCommit = revWalk.ParseCommit(srcObjectId); // get the parent of the commit to cherry-pick if (srcCommit.ParentCount != 1) { throw new MultipleParentsNotAllowedException(MessageFormat.Format(JGitText.Get(). canOnlyCherryPickCommitsWithOneParent, srcCommit.Name, Sharpen.Extensions.ValueOf (srcCommit.ParentCount))); } RevCommit srcParent = srcCommit.GetParent(0); revWalk.ParseHeaders(srcParent); string ourName = CalculateOurName(headRef); string cherryPickName = srcCommit.Id.Abbreviate(7).Name + " " + srcCommit.GetShortMessage (); ResolveMerger merger = (ResolveMerger)((ThreeWayMerger)MergeStrategy.RESOLVE.NewMerger (repo)); merger.SetWorkingTreeIterator(new FileTreeIterator(repo)); merger.SetBase(srcParent.Tree); merger.SetCommitNames(new string[] { "BASE", ourName, cherryPickName }); if (merger.Merge(headCommit, srcCommit)) { if (AnyObjectId.Equals(headCommit.Tree.Id, merger.GetResultTreeId())) { continue; } DirCacheCheckout dco = new DirCacheCheckout(repo, headCommit.Tree, repo.LockDirCache (), merger.GetResultTreeId()); dco.SetFailOnConflict(true); dco.Checkout(); newHead = new Git(GetRepository()).Commit().SetMessage(srcCommit.GetFullMessage() ).SetReflogComment("cherry-pick: " + srcCommit.GetShortMessage()).SetAuthor(srcCommit .GetAuthorIdent()).Call(); cherryPickedRefs.AddItem(src); } else { if (merger.Failed()) { return(new CherryPickResult(merger.GetFailingPaths())); } // there are merge conflicts string message = new MergeMessageFormatter().FormatWithConflicts(srcCommit.GetFullMessage (), merger.GetUnmergedPaths()); repo.WriteCherryPickHead(srcCommit.Id); repo.WriteMergeCommitMsg(message); return(CherryPickResult.CONFLICT); } } } catch (IOException e) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().exceptionCaughtDuringExecutionOfCherryPickCommand , e), e); } finally { revWalk.Release(); } return(new CherryPickResult(newHead, cherryPickedRefs)); }