diff --git a/LibGit2Sharp.Tests/BranchFixture.cs b/LibGit2Sharp.Tests/BranchFixture.cs
index 8091d781d..830574888 100644
--- a/LibGit2Sharp.Tests/BranchFixture.cs
+++ b/LibGit2Sharp.Tests/BranchFixture.cs
@@ -470,6 +470,38 @@ public void CanSetUpstreamBranch()
}
}
+ [Fact]
+ public void CanSetUpstreamMergeBranch()
+ {
+ const string testBranchName = "branchToSetUpstreamInfoFor";
+ const string mergeBranchName = "refs/heads/master";
+ const string upstreamBranchName = "refs/remotes/origin/master";
+ const string upstreamRemoteName = "origin";
+
+ TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(StandardTestRepoPath);
+
+ using (var repo = new Repository(path.RepositoryPath))
+ {
+ Branch branch = repo.CreateBranch(testBranchName);
+ Assert.False(branch.IsTracking);
+
+ Branch upstreamBranch = repo.Branches[upstreamBranchName];
+ Branch updatedBranch = repo.Branches.Update(branch,
+ b => b.UpstreamRemote = upstreamRemoteName,
+ b => b.UpstreamMergeBranch = mergeBranchName);
+
+ // Verify the immutability of the branch.
+ Assert.False(branch.IsTracking);
+
+ Remote upstreamRemote = repo.Network.Remotes[upstreamRemoteName];
+ Assert.NotNull(upstreamRemote);
+
+ Assert.True(updatedBranch.IsTracking);
+ Assert.Equal(upstreamBranch, updatedBranch.TrackedBranch);
+ Assert.Equal(upstreamRemote, updatedBranch.Remote);
+ }
+ }
+
[Fact]
public void CanSetLocalUpstreamBranch()
{
diff --git a/LibGit2Sharp/BranchUpdater.cs b/LibGit2Sharp/BranchUpdater.cs
index fd834b90e..a1bb7b945 100644
--- a/LibGit2Sharp/BranchUpdater.cs
+++ b/LibGit2Sharp/BranchUpdater.cs
@@ -33,6 +33,13 @@ internal BranchUpdater(Repository repo, Branch branch)
///
/// Passing null or string.Empty will unset the upstream.
///
+ ///
+ /// The upstream branch name is with respect to the current repository.
+ /// So, passing "refs/remotes/origin/master" will set the current branch
+ /// to track "refs/heads/master" on the origin. Passing in
+ /// "refs/heads/master" will result in the branch tracking the local
+ /// master branch.
+ ///
///
public virtual string Upstream
{
@@ -48,17 +55,56 @@ public virtual string Upstream
}
}
+ ///
+ /// Set the upstream merge branch directly for this branch.
+ ///
+ /// To track the "master" branch on the "origin" remote, set the
+ /// UpstreamRemote property to "origin" and the UpstreamMergeBranch
+ /// property to "refs/heads/master".
+ ///
+ ///
+ public virtual string UpstreamMergeBranch
+ {
+ set
+ {
+ SetUpstreamMergeBranch(value);
+ }
+ }
+
+ ///
+ /// Set the upstream remote for this branch.
+ ///
+ /// To track the "master" branch on the "origin" remote, set the
+ /// UpstreamRemote property to "origin" and the UpstreamMergeBranch
+ /// property to "refs/heads/master".
+ ///
+ ///
+ public virtual string UpstreamRemote
+ {
+ set
+ {
+ SetUpstreamRemote(value);
+ }
+ }
+
private void UnsetUpstream()
{
- repo.Config.Unset(string.Format("branch.{0}.remote", branch.Name));
- repo.Config.Unset(string.Format("branch.{0}.merge", branch.Name));
+ SetUpstreamRemote(string.Empty);
+ SetUpstreamMergeBranch(string.Empty);
}
///
/// Set the upstream information for the current branch.
- ///
- /// The upstream branch to track.
- private void SetUpstream(string upStreamBranchName)
+ ///
+ /// The upstream branch name is with respect to the current repository.
+ /// So, passing "refs/remotes/origin/master" will set the current branch
+ /// to track "refs/heads/master" on the origin. Passing in
+ /// "refs/heads/master" will result in the branch tracking the local
+ /// master branch.
+ ///
+ ///
+ /// The remote branch to track (e.g. refs/remotes/origin/master).
+ private void SetUpstream(string upstreamBranchName)
{
if (branch.IsRemote)
{
@@ -68,21 +114,52 @@ private void SetUpstream(string upStreamBranchName)
string remoteName;
string branchName;
- GetUpstreamInformation(upStreamBranchName, out remoteName, out branchName);
+ GetUpstreamInformation(upstreamBranchName, out remoteName, out branchName);
- SetUpstreamTo(remoteName, branchName);
+ SetUpstreamRemote(remoteName);
+ SetUpstreamMergeBranch(branchName);
}
- private void SetUpstreamTo(string remoteName, string branchName)
+ ///
+ /// Set the upstream merge branch for the local branch.
+ ///
+ /// The merge branch in the upstream remote's namespace.
+ private void SetUpstreamMergeBranch(string mergeBranchName)
{
- if (!remoteName.Equals(".", StringComparison.Ordinal))
+ string configKey = string.Format("branch.{0}.merge", branch.Name);
+
+ if (string.IsNullOrEmpty(mergeBranchName))
{
- // Verify that remote exists.
- repo.Network.Remotes.RemoteForName(remoteName);
+ repo.Config.Unset(configKey);
}
+ else
+ {
+ repo.Config.Set(configKey, mergeBranchName);
+ }
+ }
- repo.Config.Set(string.Format("branch.{0}.remote", branch.Name), remoteName);
- repo.Config.Set(string.Format("branch.{0}.merge", branch.Name), branchName);
+ ///
+ /// Set the upstream remote for the local branch.
+ ///
+ /// The name of the remote to set as the upstream branch.
+ private void SetUpstreamRemote(string remoteName)
+ {
+ string configKey = string.Format("branch.{0}.remote", branch.Name);
+
+ if (string.IsNullOrEmpty(remoteName))
+ {
+ repo.Config.Unset(configKey);
+ }
+ else
+ {
+ if (!remoteName.Equals(".", StringComparison.Ordinal))
+ {
+ // Verify that remote exists.
+ repo.Network.Remotes.RemoteForName(remoteName);
+ }
+
+ repo.Config.Set(configKey, remoteName);
+ }
}
///