GIT如何将变更从一个存储库的分支拉到另一个存储库的分支

lymgl2op  于 2022-12-17  发布在  Git
关注(0)|答案(2)|浏览(142)

我知道这对某些人来说可能听起来很傻,但我在一个分支中做了代码更改,并将这些更改提交给了该分支。此代码更改位于一个.Net解决方案的特定存储库中,并且此解决方案与许多其他.Net解决方案共享。
我尝试用git子模块做的是把代码变更从这个仓库拉到另一个仓库的另一个分支,我正在处理另一个代码变更。
有什么办法能让我把那根分支拔下来吗?

ldfqzlk8

ldfqzlk81#

找到了我的笔记,由于标记的原因,无法在评论中很好地发布此内容,基本行如下:

git remote add local-origin /c/git/OTHER_REPOSITORY
git pull --rebase local-origin main --allow-unrelated-histories
rxztt3cl

rxztt3cl2#

您可能需要git cherry-pick,使用它并不是特别困难;这里的设置比较棘手。您可能 * 不 * 需要git merge,不管有没有--allow-unrelated-histories

背景:提交

重要的是要认识到Git不是关于分支的,在某种意义上甚至不是关于 * 文件 * 的。相反,Git是关于 * 提交 * 的--这意味着你需要了解很多关于提交的知识:一个是什么,一个为你做了什么,以及提交与其他提交之间的关系。
任何Git仓库中的每个提交都是 * 编号的 ,有一个看起来很大很难看的随机 * 哈希ID(形式上是一个 * 对象ID
或OID),比如c48035d29b4e524aed3a32f0403676f0d9128863,这个ID实际上就是提交的True Name(另请参见TV Tropes):* 任何 * 具有 * 此特定提交 * 的 * Git仓库都将其存储在 * 此UUID * 下。1
每个提交都存储了一些元数据,包括作者的名字和电子邮件地址以及一些日期和时间戳。(或 parent)提交散列ID-仅是原始数字,但由于这些是那些提交的真实名称,这让Git可以找到那些提交。并且间接地,每个提交保存了一个 * 每个源文件的完整快照 *,其形式与提交者提交该提交时相同。
这样做的结果是,只要给定哈希ID,Git就可以得到:

    • 此 * 提交的完整快照(如果有);以及
  • 此提交的 parent 提交的完整快照,条件类似。

Git通过 * 比较 * 两个快照来找出“改变了什么”。一次提交存储的是一个快照,而不是一组更改。需要 * 两次 * 提交才能“看到”任何更改。
1目前任何Git对象的OID都只是对象数据的SHA-1。一旦Git更广泛地支持SHA-256,提交将有 * 两个 *“真实名称”,这将是很尴尬的。目前还不清楚最终将如何处理。

这对你意味着什么

我正在尝试做的......是将代码更改从这个存储库拉到另一个存储库的另一个分支中
两个仓库 * 可以 * 完全共享提交:如果仓库A有提交c48035d29b4e524aed3a32f0403676f0d9128863--我们简称为“commitx 1 m5n1x“--并且独立仓库B*也有提交C1,那么根据真实名称的法则,这是 * 相同的提交 *。并且--至少通常,在没有 * 浅克隆 * 的情况下--如果你有一些提交,你就有了提交的父提交(s),以及父节点的父节点,等等,一直回溯到第一次提交。
所以如果你想复制某个提交C2的修改,并且你已经提交了C2,你可以让Git把提交C2转换成“在提交C2中修改了什么“。git show命令完成这个操作,并显示修改了什么。前缀为C2元数据中提交的一般信息。git diff命令可用于获取快照中的差异:你可以将C2与它的(第一个也可能是唯一的)父节点进行比较,其他Git命令也可以做同样的事情。
一旦你有了C2和其父提交之间的 * 差异 *,你就可以将这个相同的差异 * 应用到第三次提交C3上。你可以手动完成这个操作,这往往会非常繁琐。或者你可以让Git为你做,使用git cherry-pick
cherry-pick命令的工作原理非常简单:你 * checkout * 你想作为起点的提交,通常使用git switchgit checkout

git switch somebranch

然后你给予git cherry-pick一个你想复制其 effect 的提交的原始哈希ID,或者,如果你有一个分支或标签名,当解析为一个原始哈希ID时,得到了正确的提交的原始哈希ID,你可以使用那个名称,但我们在这里只使用一个原始哈希ID:

git cherry-pick c48035d29b4e524aed3a32f0403676f0d9128863

Git现在找到了你在这里指定的提交(我选择了C1)。它 * 必须存在于你当前的仓库中 。Git使用该提交的元数据来找到该提交的父提交:必须只有一个父提交,这使得这是一个普通的提交。2 Git将提交的快照(本例中为C1)与其父提交的快照进行比较,找出修改了什么,然后找出如何将这些修改 * 合并 * 到 * 当前提交 * 中。
这种组合从技术上讲是一种合并操作--我喜欢称之为“作为动词合并”--这意味着您可能会遇到合并冲突。如果确实遇到合并冲突,您可以用通常的方法解决它们。一旦完成,您可以使用git cherry-pick --continuegit commit来完成。如果没有合并冲突,cherry-pick会继续运行git commit来为你完成任务,最终结果是一个普通的提交,
而不是 * merge,Git默认情况下 * 重用你现在复制的提交中的提交消息
新的提交是不同的--它有自己的新UUID,它包含了你的名字、你的电子邮件地址、
当前 * 日期和时间等信息,以确保它的唯一性--但是它和你刚刚复制的提交“做了同样的事情”(或多或少有相同的差异)。

2你可以选择一个 *root提交 * a-没有父提交的提交a-Git会把每个文件都称为“新添加的”。如果你有理由选择一个 *merge提交 *-a有多个父提交的提交,你可以告诉git cherry-pick * 哪个父提交 * 假装是唯一的父提交,这样它就可以得到一个合适的diff值。但是一般来说,你只能选择一个“普通的”(单亲)提交。

搭扣

从此存储库到...另一个存储库
如果这两个仓库不是彼此的克隆,或者在过去不是,很有可能不仅是你的新提交 * 不在 * 两个仓库中(你只把它添加到了一个仓库中),而且它的 * 父 * 提交也不在两个仓库中(它一开始就不在那里)。
对于git cherry-pick,这是一个show-stopper(意思是3).你 * 必须 * 把你想要复制的提交 * 和它的父提交 * 都放到你自己的仓库中,才能使用git cherry-pick.
幸运的是,这是微不足道的:只需使用git remote add将包含你所关心的两个提交的仓库 * add* 到你现有的克隆中,然后使用该远程操作运行git fetch,例如,假设你所做的提交在$HOME/work/project23/中,而你想选择$HOME/work/project45/中的仓库,那么你现在就在第二个仓库(project45)中:

git remote add project23 $HOME/work/project23
git fetch project23

现在你的project45仓库中已经有了project23的所有提交。这会使仓库膨胀一些,但是只要你有足够的磁盘空间,就没有必要再挑剔了。现在你可以运行git cherry-pick命令了。
当您完成并想要清理时,运行:

git remote remove project23

这将删除 nameproject23以及对其他Git仓库的引用。Git将保留所有复制的提交一段时间,但最终会将其清除,仓库也会缩小,并且git push不会将所有提交复制到其他地方:它们只是坐在那里占据 * 那个特定克隆 * 的空间,直到Git开始清理。
(If如果你想强制Git提前清理,你可以运行git gc --prune=now,但除非你的磁盘空间非常紧张,否则我不推荐你这么做。

相关问题