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.patch
或git 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.name
和user.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 的、压缩的和重复数据删除的形式存储 每个 文件的完整快照。因此,如果提交 H
、I
和 J
都共享他们的大部分文件,他们实际上是共享这些文件,即使每个文件都有自己的完整副本。 (启用此共享因为内容是只读的。)
要查看任何给定提交中的更改,Git 只需按照提交的内部向后箭头指向其父项。那个父母也有一个快照。两个提交中相同的任何文件都不会更改,并且由于 Git 正在执行重复数据删除,它可以非常快速地发现这一点。对于 更改的文件,Git 会比较它们的内容以查看更改的内容,并向您显示差异(这是按需计算的,而不是存储在提交中)。
要使分支“独立”,只需将它们全部启动得足够远。在这里,分支topic
和分支develop
都从main
上的提交H
开始。这意味着我们所做的更改,然后用于制作快照 I
或 J
,不会反映在另一个提交中,该提交以来自 H
的文件副本开始。
(稍后,如果我们去 merge 分支 develop
和 topic
,提交 H
——最好的共享提交,在 两个 分支——都非常重要。)
【讨论】:
以上是关于git log 包含另一个分支的提交,如何在分支之间分离提交的主要内容,如果未能解决你的问题,请参考以下文章