首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用git轻松地管理提交链和它们各自的拉请求?

如何使用git轻松地管理提交链和它们各自的拉请求?
EN

Stack Overflow用户
提问于 2020-05-19 17:54:06
回答 2查看 972关注 0票数 2

我有一个提交链,每个提交都有自己的分支,但是它们都是相同特性的一部分。

当我收到关于我的拉请求(GitHub/Bitbucket/任何其他)的评论时,我希望下面所有的拉请求都能以尽可能少的手工工作得到修复。

在这种情况下,没有其他人使用我的分支,所以如果需要的话,我可以自由地向它们施加压力。

我曾经在一家主要的Android设备制造商工作,我喜欢Gerrit轻松地处理这个问题的方式。Gerrit在Android之外并没有被广泛使用,所以我想找到一个很好的工作流程来覆盖90%的情况,即使在一个庞大的团队中也是如此。

我通常用两种方法之一来解决这个问题:

  1. 执行固定提交,将它们推送到各自的分支,然后向上合并,无论需要多少次,直到所有分支都有了所有的修复。这可能是很多工作,取决于提交链的长度。
  2. 执行git rebase -i,然后根据需要多次执行git push origin <sha>:remote-branch。这也是很多工作,然后本地分支和远程分支之间出现了不匹配(这可以通过git reset进行补救,但这会增加更多的工作)。这也是容易出错的,因为它很容易拼错沙或分支的名称。

是否有一种更简单的方法来管理指定用于拉请求的提交链?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-05-19 17:54:06

我在威廉·查金的博客上找到了一个很好的方法来处理这个问题,因为他称之为“依赖的拉请求”,这是描述它的一个很好的方法。

编辑2021-11-08:我已经开始使用git notes来管理remote-branch,而不是将它添加到提交消息中。这使得git提交消息历史更加清晰。

我修改了原来的脚本,因为它使用了MIT许可证,所以我遵循了指导方针,并添加了我的名字。

对脚本进行了以下修改:

  • 通过使用在macOS的macOS版本上工作的regexp,使其与sed兼容。
  • 使用git命令git notes show获取远程分支消息,而不是git show
  • 对分支名称匹配器使用更通用的标签。
  • 默认为空分支前缀。

前言

要遵循这个答案,您需要相当熟练地使用git,并且您可能已经使用了足够多的git rebase -i来适应它。

如果这是你的第一次吉特竞技,它可能是明智的,获得一些经验,并回来另一个时间。

潜在缺陷

该方法使您更接近Gerrit的方便,只要您意识到潜在的缺点:

  • 武力推进并不总是一个好策略。
  • 如果您有CI,所有更新的分支都将再次运行它们的测试(这是好的,但如果您的CI很昂贵,也会很糟糕)。
  • 注意远程分支名称的冲突。
  • 一些审查员更喜欢逐个提交更改。
  • 可能还有别的东西!

方法

先决条件

要使此方法正常工作,您必须配置git以使用这些设置(我喜欢全局配置它,但如果只需要针对特定的存储库,则可以删除--global )。

代码语言:javascript
复制
git config --global notes.rewriteRef refs/notes/commits
git config --global notes.rewrite.amend true
git config --global notes.rewrite.rebase true

分支策略

所有提交都在单个本地分支上运行,这不一定需要推送,除非您希望在工作进行期间保持远程备份(建议)。

添加您需要的多个提交来构建依赖的拉请求的逻辑链。我曾经用11条链提交。

代码语言:javascript
复制
$ git log --oneline
aaaaaaa3 (HEAD -> my-backup-branch) Feature: Step 3
aaaaaaa2 Feature: Step 2
aaaaaaa1 Feature: Step 1
aaaaaaaa (origin/master) Probably some merge commit
...

管理您的提交

对于,链中的每个提交,您必须添加一个git notes,它告诉脚本应该将它推送到哪个远程分支。远程分支不需要存在。在创建提交时或在推送更改之前的任何时候添加git notes

代码语言:javascript
复制
$ git notes add -m "remote-branch: my-feature-step-3"
$ git log
commit aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3 (HEAD -> my-backup-branch)
Author: Erik Zivkovic <...>
Date:   Fri May 19 19:47:53 2020 +0200

    Feature: Step 3

Notes:
    remote-branch: my-feature-step-3

[... more commits]

准备好推送和创建/更新PRs

我建议您不要同时进行git rebase -i修复并使用脚本。执行任何更改,然后测试您的提交链,然后再推送。这就是我建议的做法。

确保链中的所有提交都有唯一的remote-branch: <branch name>行!

要完成所有这些操作,请使用git rebase -i参数调用-x "git push-to-target"

代码语言:javascript
复制
$ git rebase -i aaaaaaaa -x "git push-to-target"
[This will open your chosen git editor with a git rebase window]
pick aaaaaaa1 Feature: Step 1
exec git push-to-target
pick aaaaaaa2 Feature: Step 2
exec git push-to-target
pick aaaaaaa3 Feature: Step 3
exec git push-to-target

当然,神奇的是,git rebase在每个pick命令之后停止并运行exec命令,该命令:

  • 读取git notes消息。
  • 查找remote-branch行。
  • 强制推送(--force-with-lease)当前HEAD (指向pick)到remote-branch
  • 如果远程分支不存在,则创建该分支。否则它将被更新。

如果一切正常,您应该在git日志中看到更新的远程分支。

代码语言:javascript
复制
$ git log --oneline
aaaaaaa3 (HEAD -> my-backup-branch, origin/my-feature-step-3) Feature: Step 3
aaaaaaa2 (origin/my-feature-step-2) Feature: Step 2
aaaaaaa1 (origin/my-feature-step-1) Feature: Step 1
aaaaaaaa (origin/master) Probably some merge commit
...

拉请求

如果您没有任何拉请求,那么现在是使用您所拥有的任何服务(Github、Bitbucket、.)创建这些请求的时候了,并且将分支按顺序指向对方。

如果拉请求已经存在,现在应该更新它们并再次运行测试(如果您有CI)。

更多提交,处理评审意见等。

  • 如果您收到评论评论,只需git rebase -i并进行任何修复。
  • 如果您做了更多的特性工作,只需继续在顶部添加提交,并为每次提交在git notes中添加唯一的git notes标签即可。
  • 最后,再次使用git rebase -i <sha> -x "git push-to-target" (在本地测试您的更改之后,不用说)。

清理

当所有内容都合并时,您可能希望删除远程备份分支。

提示

  • 提示:将脚本添加到您的路径中,然后您可以将它用作git push-to-target
  • 提示:git config --global alias.ptt push-to-target
  • 提示:git rebase -i <SHA> -x "git ptt"

补充说明

注意:我已经通过电子邮件联系了开发人员,告诉他我的更改,并询问他对他们的看法,但我还没有收到答复。

脚本

脚本应该在Linux/macOS/WSL上工作。我只在macOS上测试过。

这个脚本的大部分是由William编写的,我只是让它在macOS上工作,并做了一些对我来说似乎不错的小改动。

文件:git-push-to-target

代码语言:javascript
复制
#!/bin/sh
#
# git-push-to-target: Push this commit to a branch specified in its
# commit description.
#
# Copyright (c) 2017 William Chargin. Released under the MIT license.
# Copyright (c) 2020 Erik Zivkovic.
#
# Originally https://wchargin.github.io/posts/managing-dependent-pull-requests/
#
# Usage: For a commit add a git notes line `remote-branch: branchname` then in a rebase do `exec git push-to-target`
#
# Tip: Add this file to your path, then you can use it as git push-to-target
# Tip: git config --global alias.ptt push-to-target
# Tip: git rebase -i <SHA> -x "git ptt"
#

set -eu

DIRECTIVE='remote-branch'  # any regex metacharacters should be escaped
BRANCH_PREFIX=''           # Add a branch prefix if needed

target_branch() {
    directive="$( \
        git notes show HEAD \
        | sed -n 's/^'"${DIRECTIVE}"': \([A-Za-z0-9_.-]*\)$/\1/p' \
        ; )"
    if [ -z "${directive}" ]; then
        printf >&2 'error: missing "%s" directive\n' "${DIRECTIVE}"
        return 1
    fi
    if [ "$(printf '%s\n' "${directive}" | wc -l)" -gt 1 ]; then
        printf >&2 'error: multiple "%s" directives\n' "${DIRECTIVE}"
        return 1
    fi
    printf '%s%s\n' "${BRANCH_PREFIX}" "${directive}"
}

main() {
    if [ "${1:-}" = "--query" ]; then
        target_branch
        return
    fi
    remote="${1:-origin}"
    branch="$(target_branch)"
    set -x
    git push --force-with-lease "${remote}" HEAD:refs/heads/"${branch}"
}

main "$@"
票数 0
EN

Stack Overflow用户

发布于 2022-10-09 23:52:59

我一直在考虑解决同样的问题,并找到了一些工具:

更新:我尝试过git-chain,发现它很棒。级联多分支重基1命令和多推1命令正在满足我的需要。

我看了一下git-stack,但是复杂的命令引用令人望而生畏。

spr这次不适用于我,因为它是目前唯一的工具。

我已经把git-machete添加到列表中了,还没有尝试

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61897602

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档