如何通过 GitHub 的 API 进行挑选

How to cherry-pick through GitHub's API

我在通过 GitHub API 执行 简单 cherry-pick 时遇到问题。这一定是可能的,但我不清楚如何...

我正在使用 C# 为 Slack 开发一个聊天机器人,以帮助管理 Kubernetes 环境和 GitHub 版本,并希望使用 修补程序功能 对其进行扩展。给定一个环境,它应该创建一个与当前版本匹配的分支,并在其中挑选一个或多个提交 SHA,由请求的作者通过 Slack 提供。

所有管道都已就位。使用 POST /repos/:owner/:repo/git/refs 我能够创建与特定版本匹配的分支。这意味着我已经为下一步准备好了 branch namecommit SHAtree SHA;挑选一个或多个提交 SHA 到这个分支。使用 POST /repos/:owner/:repo/git/commits 我可以创建一个提交,但我不确定要使用哪个树 and/or 父级 - 这可能会导致我在调用 POST /repos/:owner/:repo/merges 时遇到问题,因为它 returns me status 409 (merge conflict) where locally, 当然没有.

我能找到的唯一真实例子是 https://github.com/tibdex/github-cherry-pick。然而,它并不真正符合我的场景,我很难理解 Git 内部工作原理。

我的场景(从最新到最旧);

* commit E (current state of `master`)
* commit D
* commit C (deployed to environment)
* commit B
* commit A

在这种情况下,我想将提交 E 挑选到提交 C 的新分支中,创建一个我可以发布的集合(A、B、C、E)。

* commit E (current state of `master`)
* commit D
|
| * commit E (new branch, to be deployed)
|/
* commit C (deployed to environment)
* commit B
* commit A

基本上我需要的是这个 bash;

的 GitHub API 版本
git checkout -b {new-branch-name} {sha}
git cherry-pick {sha}
git push main {new-branch-name}

感谢任何帮助!

以下是我如何在 Git 集线器 API 上用伪代码实现 cherry-pick:

// here is a commit, for example, from a pull request:
listOfCommits = GET /repos/$owner/$repo/pulls/$number/commits
commit = listOfCommits.head // the first one in the list

// Here is the branch we want to cherry-pick to:
branch = GET /repos/$owner/$repo/branches/$branchName
branchSha = branch.commit.sha
branchTree = branch.commit.commit.tree.sha

// Create a temporary commit on the branch, which extends as a sibling of
// the commit we want but contains the current tree of the target branch:
parentSha = commit.parents.head // first parent -- there should only be one
tempCommit = POST /repos/$owner/$repo/git/commits { "message": "temp",
                                                    "tree": branchTree,
                                                    "parents": [parentSha] }

// Now temporarily force the branch over to that commit
PATCH /repos/$owner/$repo/git/refs/heads/$refName { sha = tempCommit.sha,
                                                    force = true }

// Merge the commit we want into this mess:
merge = POST /repos/$owner/$repo/merges { "base": branchName
                                  "head": commit.sha }

// and get that tree!
mergeTree = merge.commit.tree.sha

// Now that we know what the tree should be, create the cherry-pick commit.
// Note that branchSha is the original from up at the top.
cherry = POST /repos/$owner/$repo/git/commits { "message": "looks good!",
                                                "tree": mergeTree,
                                                "parents": [branchSha] }

// Replace the temp commit with the real commit:
PATCH /repos/$owner/$repo/git/refs/heads/$refName { sha = cherry.sha,
                                                    force = true }

// Done!

Git高手请指教,我相信这样就可以了:

git checkout -b {new-branch-name} {sha}
git cherry-pick {sha}
git push main {new-branch-name}

已接受的答案有效,但不清楚原因。

以下内容摘自我对这个脚本的要点(在 golang 中)的评论:https://gist.github.com/sashamor/7918b3be758759440feb7825547370f9

GitHub 不支持直接使用 API 创建 cherry-pick 提交。 但是,它确实支持在 git 树中创建提交对象。所以,我们将 从第一原则创建一个新的 cherry-pick 提交。

要创建提交,我们需要三样东西:

  1. 提交信息。
  2. 父提交。
  3. 树(也就是这次提交时 repo 中所有对象的状态)。

对于 cherry-pick 提交,这很简单:

  1. 消息很简单 - 我们使用来自原始提交的消息,加上一个 “从...中精心挑选”页脚。
  2. 父 SHA 也很简单 - 我们使用我们想要的提交的 SHA 樱桃采摘,延伸树。
  3. 树是棘手的部分 - 我们需要创建一个新的 git 对象 包含我们希望它们处于的状态的文件,然后使用它。

以下步骤用于创建树 SHA。一旦我们有了它,我们就可以 创建提交。

为了得到树,我们可以使用合并API。目前,GitHub 合并 API 需要两件事:

  1. 要合并到的分支。
  2. 我们要合并的提交的 SHA。

乍一看,一个解决方案似乎是使用 merge with:

  1. 要选择的分支。
  2. 对 cherry-pick 的承诺。

然而,这有一个警告,所有提交 before cherry-pick 提交,不在要挑选的分支中,包含在 合并。我们不想要这个。为了解决这个问题,我们可以“欺骗”git 包括 cherry-pick 提交,通过(临时)设置 分支到我们想要挑选的提交的父级。这样,当 git 执行合并,它检测到我们正在提交的分支的父级 merging to 匹配我们正在合并的提交的父级,并合并 一棵大小为 1 的树,仅包含 cherry-pick 提交。

要创建这个新的“树尖”提交:

  1. 消息无关紧要 - 它丢失了。
  2. 父级是我们要挑选的提交的父级 - 这个 这样,cherry-pick 提交和分支都有相同的父级。
  3. 这棵树是我们要挑选的树枝。

然后我们创建一个指向这个提交的临时分支,这样我们就可以合并 到它上面。然后我们可以调用 merge with:

  1. 一个树枝与我们正在挑选的树枝相匹配的树枝,以及一个 父级匹配我们正在挑选的提交的父级。
  2. 对 cherry-pick 的承诺。 此合并操作的结果提交具有我们需要的树 SHA。

最后,我们可以使用它来创建 cherry-pick 提交。这可以是 根据需要重复多次,新的 cherry-pick 提交是 每次基本分支。