【问题标题】:gitpython get last commit with detached headgitpython获取最后一个带有分离头的提交
【发布时间】:2020-03-13 06:25:14
【问题描述】:

在最新的存储库中,我们执行以下操作:

git checkout HEAD~5

然后使用GitPython,我们可以得到head commit,它是分离的:

import git

repo = git.Repo('.')
head = repo.head
head_commit = head.commit
print(head.is_detached)
> True

GitPython 中有没有办法获取分支中的最后一次提交?

我在想一些类似的事情:

last = repo.active_branch.last_commit  # active_branch will throw an error when head is detached.

last = head_commit
# I dont even know if talking about child commits makes sense in git.
while last.child is not None:
    last = last.child

【问题讨论】:

    标签: git gitpython git-detached-head


    【解决方案1】:

    any 分支中的最后一次提交由 分支名称 中存储的提交哈希 ID 给出。

    就是这样——真的就是这么简单。 Git 仅提交从子到父的链接向后。所以每个分支名称​​必须存储其last提交的hash ID。

    在最新的存储库中,我们执行以下操作:

    git checkout HEAD~5
    

    完成此操作后,正如您在标题中所说,您拥有一个“分离的 HEAD”。这意味着您不再在任何分支上。 “最后一次提交”的问题变得毫无意义:HEAD 直接指向一个提交,根据定义,该提交是 当前 提交。您可以检查您喜欢的任何提交,例如,通过给 git checkout 一个原始提交哈希 ID,您将继续处于分离的 HEAD 上,但在不同的提交上。

    效果是你现在在一个匿名分支(一个没有名字的分支)上,它的last 提交是current 提交。此时创建一​​个指向该提交的新分支会导致该分支存在。它的最后一次提交是当前提交,所以现在新创建的分支上的最后一次提交就是当前提交。

    给定一系列提交,例如:

    ... <-F <-G <-H <-I   <-- br1
                       \
                        J <-K   <-- br2
    

    所有直到I 的提交都在br2 上,即使I 也是br1最后 提交,所以所有提交一直到I 都在br1。它们在两个分支上。 JK 的提交br2 上。

    如果我们删除 name br1,所有的提交仍然可以通过名称 br2 找到。 Git 通过从(所有)分支名称和其他此类名称中读取每个哈希 ID 来查找(所有)提交,然后从这些提交向后工作到它们的父级和父级的父级,依此类推。

    如果此时您 git checkout br1 并创建一个新的提交,您会得到:

                        L   <-- br1 (HEAD)
                       /
    ... <-F <-G <-H <-I
                       \
                        J <-K   <-- br2
    

    请注意,HEAD 现在已附加到分支 br1。 Commit L 是该分支的最后一次提交;通过I 的提交在两个分支中。

    如果你现在分离 HEAD 并将其移动到提交 I 你会得到:

                        L   <-- br1
                       /
    ... <-F <-G <-H <-I   <-- HEAD
                       \
                        J <-K   <-- br2
    

    练习(按顺序进行)

    1. 我会给你两个原始的提交哈希 ID,前提是第一个提交的哈希 ID 可以通过从第二个提交开始并向后走,沿着这些向后指向的箭头一次一步。例如,我可能会给你提交F 的哈希ID 和提交K 的哈希ID。你如何使用这些信息找到提交G? (考虑从提交 K 开始并遵循每个箭头,同时保留每个访问过的提交的某种日志。)

    2. 下一个提交之后提交I是什么?为了找到下一次提交,您还需要哪些其他信息?请记住,I 提交在 br1br2 上。

    【讨论】:

    • 我想我明白了。由于 git 历史是一棵树,因此一次提交有一个父级,但可能有 0 到多个子级。但是没有存储孩子的信息,只存储了父母、这棵树的叶子(每个分支)和一些其他中间指针(比如我们分离的 HEAD)。您的问题的答案是: 1. 从K 开始,我们可以迭代地获取提交的父项,将哈希压入堆栈并继续直到我们达到F 的哈希。然后G 的哈希值将在堆栈中。 2. 我们需要在这两个分支中的任何一个中的另一个提交来执行 anwser (1.) 的过程
    • 对。请注意,尽管 merge 提交有两个(或更多)父级,这使事情变得复杂:您必须沿着两个父级链接向后走。 (合并将数据结构从树更改为图——Git 中的有向无环图。对于您的特定情况,您可能无需担心合并提交。)
    猜你喜欢
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    • 1970-01-01
    相关资源
    最近更新 更多