如何检测 git 提交是否是其他提交的父级?

发布于 2024-09-14 03:03:20 字数 657 浏览 9 评论 0原文

我正在编写一个脚本,进行一些细微的更改,然后将它们提交到 git。因为这些都是微不足道的更改,所以只要我能逃脱惩罚,我就想执行 git commit --amend ,特别是当修改不会“搞乱”任何其他分支的历史记录时。如果修改会弄乱另一个分支,我想做一个标准的 git commit 来代替。

例如,如果我的分支看起来像这样(Git GUI 中的“可视化所有分支历史记录”):

* [experimental branch] Added feature.
* [master branch] Trivial change from script
* ...

并且我在主分支上运行此脚本,那么我不想进行修改,因为我会替换实验分支的部分历史。从技术上讲,这实际上不会破坏任何东西——原始提交仍然是实验历史的一部分,并且仍然会被引用,因此它不会被垃圾收集——但是在当我以后想要重新设置基础或合并时,两个不同的分支会让生活变得困难,所以这是我想避免的情况。

如何让我的脚本自动检测提交是否有任何分支?

如果简化假设有帮助,我总是在 master 上运行这个脚本,并且我只使用 git 作为本地存储库——我不会在任何地方推送或拉取更改。

该脚本是用 Ruby 编写的,因此我可以使用 git 命令行,也可以使用 git 的 Ruby 绑定——无论哪一种都可以使此任务变得更容易。

I'm writing a script that makes some trivial changes and then commits them to git. Because these are trivial changes, I want to do git commit --amend whenever I can get away with it -- specifically, when an amend won't "mess up" any other branches' history. If an amend would mess up another branch, I want to do a standard git commit instead.

For example, if my branches looked like this (a la "Visualize all branch history" in Git GUI):

* [experimental branch] Added feature.
* [master branch] Trivial change from script
* ...

and I'm running this script on the master branch, then I don't want to do an amend, because I would be replacing part of the experimental branch's history. Technically, this won't actually break anything -- the original commit will still be part of experimental's history, and will still be referenced so it won't get garbage collected -- but having nearly-but-not-quite-identical commits in two different branches makes life difficult when I later want to rebase or merge, so it's a situation I want to avoid.

How can I make my script automatically detect whether a commit has anything branched from it?

If simplifying assumptions help, I always run this script on the head of master, and I only use git as a local repository -- I don't push or pull changes anywhere.

This script is in Ruby, so I can either shell out to the git command line, or I can use Ruby bindings for git -- whichever would make this task easier.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

能怎样 2024-09-21 03:03:20

只需运行 gitbranch --contains HEAD 即可获取“包含”此提交的分支列表。如果列表为空,则该提交应该可以安全地进行修改。您可能还需要包含 -a 标志来列出本地和远程分支。

或者,您可以将 git rev-parse HEAD 的输出与 git merge-base HEAD other-branch 进行比较。如果这些提交 ID 相同,则当前提交位于 other-branch 的提交历史记录中。

Just run git branch --contains HEAD to get a list of branches that "contain" this commit. If the list is empty, that commit should be safe for ammending. You also might want to include the -a flag to list local AND remote branches.

Alternatively, you could compare the output of git rev-parse HEAD with git merge-base HEAD other-branch. If these commit IDs are identical, the current commit is in other-branch's commit history.

﹏雨一样淡蓝的深情 2024-09-21 03:03:20

提交图是单向的:给定一个提交,您知道它的所有祖先,但不知道它的任何子项。您必须从端点开始并回溯,直到到达所需的提交为止。

使用 git rev-list [some commit] --children (HEAD 是默认值):

$ git rev-list HEAD --children
6edbee61c87fb063700751815f0ad53907d0b7a4
aee452860ecd772b8bdcd27227e6a72e6f4435fd 6edbee61c87fb063700751815f0ad53907d0b7a4
ef8a1487b03256a489d135e76d1f0b01872f2349 aee452860ecd772b8bdcd27227e6a72e6f4435fd
6910dc5833f6cd26133e32bef40ed54cf9337017 ef8a1487b03256a489d135e76d1f0b01872f2349
bbef0da56efe048f70293bd20bad0cb37b5e84f0 6910dc5833f6cd26133e32bef40ed54cf9337017
[...]

左侧列是按时间倒序排列的提交 SHA-1 列表。该提交右侧的任何内容都是该提交的子项 (--children)。顶部提交是 HEAD,因此没有子提交。

因此,如果您在此列表中 grep 查找 SHA-1 并且它的右侧有任何内容,则它至少有一个子项:

$ git rev-list --children | grep '^6910'
6910dc5833f6cd26133e32bef40ed54cf9337017 ef8a1487b03256a489d135e76d1f0b01872f2349

在上面的示例中,commit 6910... 有一个子项,<代码>ef8a...。

The commit graph is one-way: given a commit, you know all of its ancestors, but not any of its children. You'll have to start at the endpoints and backtrack until you get to the commit(s) that you want.

Use git rev-list [some commit] --children (HEAD is the default):

$ git rev-list HEAD --children
6edbee61c87fb063700751815f0ad53907d0b7a4
aee452860ecd772b8bdcd27227e6a72e6f4435fd 6edbee61c87fb063700751815f0ad53907d0b7a4
ef8a1487b03256a489d135e76d1f0b01872f2349 aee452860ecd772b8bdcd27227e6a72e6f4435fd
6910dc5833f6cd26133e32bef40ed54cf9337017 ef8a1487b03256a489d135e76d1f0b01872f2349
bbef0da56efe048f70293bd20bad0cb37b5e84f0 6910dc5833f6cd26133e32bef40ed54cf9337017
[...]

The left-hand column is a list of commit SHA-1s in reverse chronological order. Anything to that commit's right are the children (--children) of that commit. The top commit is HEAD and thus has no children.

Thus, if you grep for your SHA-1 in this list and it has anything to its right, it has at least one child:

$ git rev-list --children | grep '^6910'
6910dc5833f6cd26133e32bef40ed54cf9337017 ef8a1487b03256a489d135e76d1f0b01872f2349

In the above example, commit 6910... has a child, ef8a....

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文