如何通过 GitHub 的 API 进行挑选

Coe*_*oen 3 git github github-api

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

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

所有管道均已就位。使用POST /repos/:owner/:repo/git/refs我可以创建与特定版本匹配的分支。这意味着我已经有了branch name,commit SHAtree SHA为下一步做好了准备;挑选一个或多个提交 SHA 到此分支中。使用POST /repos/:owner/:repo/git/commits我能够创建一个提交,但我不确定要使用哪棵树和/或父级 - 这可能会导致我在调用时遇到问题POST /repos/:owner/:repo/merges,因为它返回我状态 409(合并冲突),当然,在本地,它才不是。

我似乎找到的唯一真实的例子是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
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我想将提交 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
Run Code Online (Sandbox Code Playgroud)

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

git checkout -b {new-branch-name} {sha}
git cherry-pick {sha}
git push main {new-branch-name}
Run Code Online (Sandbox Code Playgroud)

任何帮助表示赞赏!

Jim*_*ood 8

以下是我通过 Github 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!
Run Code Online (Sandbox Code Playgroud)

Git 专家请指教,但我相信这可以实现:

git checkout -b {new-branch-name} {sha}
git cherry-pick {sha}
git push main {new-branch-name}
Run Code Online (Sandbox Code Playgroud)


小智 6

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

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

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

要创建提交,我们需要三件事:

  1. 提交消息。
  2. 父级提交。
  3. 树(又名,本次提交时存储库中所有对象的状态)。

对于挑选提交,这很简单:

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

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

要获取树,我们可以使用合并 API。目前,GitHub 合并 API 需要两件事:

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

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

  1. 用来采摘樱桃的树枝。
  2. 致力于挑选。

但是,这需要注意的是,在cherry-pick提交之前的所有提交(不在要cherry-pick的分支中)都包含在合并中。我们不想要这个。为了解决这个问题,我们可以通过(暂时)将分支的父级设置为我们想要选择的提交的父级来“欺骗”git 仅包含选择的提交。这样,当 git 执行合并时,它会检测到我们要合并的分支提交的父级与我们要合并的提交的父级相匹配,并合并大小为 1 的树,仅包含cherry-pick 提交。

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

  1. 该消息并不重要——它已经丢失了。
  2. 父级是我们想要樱桃选择的提交的父级 - 这样,樱桃选择提交和分支都具有相同的父级。
  3. 这棵树是我们想要挑选的树枝的树。

然后我们创建一个指向此提交的临时分支,以便我们可以合并到它。然后我们可以调用 merge:

  1. 一个分支的树与我们正在挑选的分支相匹配,并且其父级与我们正在挑选的提交的父级相匹配。
  2. 致力于挑选。此合并操作的结果提交具有我们需要的树 SHA。

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