Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to update a fork with upstream commits #1833

Closed
Jericho opened this issue Jun 26, 2018 · 5 comments
Closed

How to update a fork with upstream commits #1833

Jericho opened this issue Jun 26, 2018 · 5 comments

Comments

@Jericho
Copy link
Contributor

Jericho commented Jun 26, 2018

Say I compare a fork with its upstream branch and determine that my fork is behind. How can I make sure my branch is up-to-date using octokit.net 0.30.0?

var fork = await _githubClient.Repository.Get("my_user", "the_repo_name").ConfigureAwait(false);
var upstream = fork.Parent;
var compareResult = await _githubClient.Repository.Commit.Compare(upstream.Owner.Login, upstream.Name, upstream.DefaultBranch, $"{fork.Owner.Login}:{fork.DefaultBranch}").ConfigureAwait(false);
if (compareResult.BehindBy > 0)
{
    ... how can I update the fork? ...
}
@ryangribble
Copy link
Contributor

The GitHub API is not the best way to do hardcore git data manipulation stuff. Whilst it does have the rudimentary ability to create blobs/trees, commits and references etc, I dont think it would be that easy to get the exact commits from upstream into your fork.

So if you do want to follow the "traditional pattern" of git fetch/pull from upstream and push to origin, you should look at libgit2 or interoperating a commandline git client.

If you are happy to take a more GitHub based approach (rather than git approach), that WOULD be possible via the API, you could automatically raise a Pull Request from the upstream branch to your fork's branch, then automatically merge it, using the merge option for "rebase merging". I think this would avoid you getting a merge commit on your fork's branch, and thus being transparently up to date with upstream...

@Jericho
Copy link
Contributor Author

Jericho commented Jun 26, 2018

@ryangribble thank you for the suggestions. I would prefer to stick with octokit so your second suggestion is particularly interresting to me. Can you point me to a sample that demonstrates how to create a PR from upstream into my fork, how to automerge, etc.?

@shiftkey
Copy link
Member

I haven't tried this myself, but this SO answer suggests you might be able to get away with just using the Git Data API:

  • Get upstream ref /repos/upstream/repo/git/refs/heads/master, and get the hash from it
  • Update your fork PATCH /repos/my/repo/git/refs/heads/master with the same hash

How this might look with Octokit.NET (the code compiles but No Guarantees™ on anything else):

var upstreamMaster = await client.Git.Reference.Get("upstream", "repo", "heads/master");
var newSha = upstreamMaster.Object.Sha;
Console.WriteLine($"The master branch on upstream/repo is {newSha}");

var forkMaster = await client.Git.Reference.Update("fork", "repo", "heads/master", new ReferenceUpdate(newSha));
var updatedSha = forkMaster.Object.Sha;
Console.WriteLine($"The master branch on fork/repo is {updatedSha}");

@Jericho
Copy link
Contributor Author

Jericho commented Jun 26, 2018

@shiftkey your suggestion works like a charm and so much simpler that anything I tried so far. Thanks

In case anybody is curious here's my code to update my fork if it's behind the upstream repo:

var fork = await _githubClient.Repository.Get("my_username", "the_repo_name").ConfigureAwait(false);
var upstream = fork.Parent;
var compareResult = await _githubClient.Repository.Commit.Compare(upstream.Owner.Login, upstream.Name, upstream.DefaultBranch, $"{fork.Owner.Login}:{fork.DefaultBranch}").ConfigureAwait(false);
if (compareResult.BehindBy > 0)
{
	var upstreamBranchReference = await _githubClient.Git.Reference.Get(upstream.Owner.Login, upstream.Name, $"heads/{upstream.DefaultBranch}").ConfigureAwait(false);
	await _githubClient.Git.Reference.Update(fork.Owner.Login, fork.Name, $"heads/{fork.DefaultBranch}", new ReferenceUpdate(upstreamBranchReference.Object.Sha)).ConfigureAwait(false);
}

@Jericho Jericho closed this as completed Jun 26, 2018
@matks
Copy link

matks commented Jun 27, 2020

@shiftkey your suggestion works like a charm and so much simpler that anything I tried so far. Thanks

In case anybody is curious here's my code to update my fork if it's behind the upstream repo:

var fork = await _githubClient.Repository.Get("my_username", "the_repo_name").ConfigureAwait(false);
var upstream = fork.Parent;
var compareResult = await _githubClient.Repository.Commit.Compare(upstream.Owner.Login, upstream.Name, upstream.DefaultBranch, $"{fork.Owner.Login}:{fork.DefaultBranch}").ConfigureAwait(false);
if (compareResult.BehindBy > 0)
{
	var upstreamBranchReference = await _githubClient.Git.Reference.Get(upstream.Owner.Login, upstream.Name, $"heads/{upstream.DefaultBranch}").ConfigureAwait(false);
	await _githubClient.Git.Reference.Update(fork.Owner.Login, fork.Name, $"heads/{fork.DefaultBranch}", new ReferenceUpdate(upstreamBranchReference.Object.Sha)).ConfigureAwait(false);
}

Just wanted to say thanks for sharing this snippet, this is exactly what I was searching for 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants