git log 包含另一个分支的提交,如何在分支之间分离提交

Posted

技术标签:

【中文标题】git log 包含另一个分支的提交,如何在分支之间分离提交【英文标题】:git log contain commit for another branch, how to separate commit beween branch 【发布时间】:2021-11-06 14:52:44 【问题描述】:

如何分离分支之间的变化? 例如:

    我创建了名为 BRANCH-1 的新分支,进行了更改并提交了更改 我创建了名为 BRANCH-2 的新分支,进行了更改,然后提交了更改。 我创建了名为 BRANCH-3 的新分支,进行了更改并提交了更改。

我的问题是,BRANCH-2 包含来自 BRANCH-1 的提交和更改

和 BRANCH-3 包含来自 BRANCH-1 和 BRANCH-2 的提交和更改

如何在每个分支上分离更改和提交?

谢谢

【问题讨论】:

如果我对创建每个分支的树做出一些假设,我可能会尝试类似git diff BRANCH-1..BRANCH-2 > b2-changes.patch 的方法来获得仅包含 BRANCH-2 更改的补丁,然后类似地@ 987654322@ 仅获取 BRANCH-3 更改。使用那些包含我想要的补丁文件,只需将每个分支都设置为所需的补丁前状态,然后在相应的分支上执行git apply b2-changes.patchgit apply b3-changes.patch 【参考方案1】:

这些提交实际上是在这些分支的所有上。

考虑以下问题。我们从一个名为main 的分支开始。名称 main 定位一个特定的提交,具有一个特定的哈希 ID H。 (真正的哈希 ID 是一些看起来很丑的东西,因此使用大写字母作为替代。)

提交H 包含两件事:

源快照——在最新提交中出现的每个文件的完整副本;和 一些元数据,其中包含提交人的姓名和电子邮件地址等内容。

提交H 中的元数据包含一些较早 提交的哈希ID。我们说H 指向较早的提交,而名称main 指向提交H

            <-H   <--main

散列 ID inside H 本身就是其他提交的,所以让我们画出那个提交,我们称之为G

        <-G <-H   <--main

当然,较早的提交 G 指向一些更早的提交 F

... <-F <-G <-H   <--main

等等。最终我们用完了“早期”提交,因为我们击中了第一个。有点懒得画箭头了,这给了我们一个更完整的画面:

A--B--C--D--E--F--G--H   <-- main (HEAD)

HEAD 这个名字告诉我们我们做了一个git checkout main

现在让我们添加一个新的分支名称,例如develop。 Git 要求 分支名称包含一些有效的现有提交的哈希 ID。我们应该使用哪些提交?最明显的候选是当前和最新的提交,H

A--B--C--D--E--F--G--H   <-- develop, main (HEAD)

如果我们现在检查develop,特殊名称HEAD 会记住分支名称当前分支,移动:

A--B--C--D--E--F--G--H   <-- develop (HEAD), main

我们仍在使用提交H。我们只是通过名称develop 使用它

提交在哪个分支上?很明显,所有提交都在两个分支上

当我们进行 new 提交时,Git 会:

将所有源文件打包为一个新快照; 添加一些元数据,使用来自user.nameuser.email 的正确名称和电子邮件地址(这些不可能是谎言:它们一定是对的!),“现在”作为日期和时间,以及以此类推。

Git 将从我们或 -m 参数获取日志消息,并将使用 当前提交 作为新提交将向后指向的位置:

                       I
                      /
A--B--C--D--E--F--G--H   <-- main

因为我们是on branch develop,正如git status 所说,Git 会将new 提交I 的哈希ID 存储到HEAD 所附加的名称中,develop ,像这样:

                       I   <-- develop (HEAD)
                      /
A--B--C--D--E--F--G--H   <-- main

分支develop 上有哪些提交? 全部,和以前一样。 only 提交I 不是在develop 上。 所有提交都在develop。只是通过H 的提交在main

如果我们现在git checkout main,Git 会:

删除所有伴随提交I的文件; 提取所有提交H的文件;和 将HEAD 附加到main

结果是:

                       I   <-- develop
                      /
A--B--C--D--E--F--G--H   <-- main (HEAD)

除了HEAD 的附加位置外,存储库中的提交和分支没有任何变化;但我们的工作树(和 Git 的索引或 暂存区)现在已更新以再次匹配提交 H

如果我们现在创建另一个新的分支名称topic,并切换到它,我们会得到:

                       I   <-- develop
                      /
A--B--C--D--E--F--G--H   <-- main, topic (HEAD)

如果我们现在再次新提交,我们会得到:

                       I   <-- develop
                      /
A--B--C--D--E--F--G--H   <-- main
                      \
                       J   <-- topic (HEAD)

这就是 Git 中分支的全部意义所在:它们是查找提交的方法

提交才是最重要的。每个提交都以特殊的、只读的、仅 Git 的、压缩的和重复数据删除的形式存储 每个 文件的完整快照。因此,如果提交 HIJ 都共享他们的大部分文件,他们实际上是共享这些文件,即使每个文件都有自己的完整副本。 (启用此共享因为内容是只读的。)

要查看任何给定提交中的更改,Git 只需按照提交的内部向后箭头指向其父项。那个父母也有一个快照。两个提交中相同的任何文件都不会更改,并且由于 Git 正在执行重复数据删除,它可以非常快速地发现这一点。对于 更改的文件,Git 会比较它们的内容以查看更改的内容,并向您显示差异(这是按需计算的,而不是存储在提交中)。

要使分支“独立”,只需将它们全部启动得足够远。在这里,分支topic 和分支develop 都从main 上的提交H 开始。这意味着我们所做的更改,然后用于制作快照 IJ,不会反映在另一个提交中,该提交以来自 H 的文件副本开始。

(稍后,如果我们去 merge 分支 developtopic,提交 H——最好的共享提交,在 两个 分支——都非常重要。)

【讨论】:

以上是关于git log 包含另一个分支的提交,如何在分支之间分离提交的主要内容,如果未能解决你的问题,请参考以下文章

如何将一个git的master分支提交添加到另一个git中?

如何将本地未提交的更改合并到另一个 Git 分支?

如何将多个提交合并到另一个分支上作为单个压缩提交?

如何运行 git log 以仅查看特定分支的更改?

git把一个分支上的某个提交合并到另一个分支

git高级用法之cheery-pick