我知道这对某些人来说可能听起来很傻,但我在一个分支中做了代码更改,并将这些更改提交给了该分支。此代码更改位于一个.Net解决方案的特定存储库中,并且此解决方案与许多其他.Net解决方案共享。我尝试用git子模块做的是把代码变更从这个仓库拉到另一个仓库的另一个分支,我正在处理另一个代码变更。有什么办法能让我把那根分支拔下来吗?
ldfqzlk81#
找到了我的笔记,由于标记的原因,无法在评论中很好地发布此内容,基本行如下:
git remote add local-origin /c/git/OTHER_REPOSITORY git pull --rebase local-origin main --allow-unrelated-histories
rxztt3cl2#
您可能需要git cherry-pick,使用它并不是特别困难;这里的设置比较棘手。您可能 * 不 * 需要git merge,不管有没有--allow-unrelated-histories。
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就可以得到:
c48035d29b4e524aed3a32f0403676f0d9128863
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 switch或git checkout:
C1
C2
git show
git diff
C3
git switch
git 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 --continue或git commit来完成。如果没有合并冲突,cherry-pick会继续运行git commit来为你完成任务,最终结果是一个普通的提交, 而不是 * merge,Git默认情况下 * 重用你现在复制的提交中的提交消息 。新的提交是不同的--它有自己的新UUID,它包含了你的名字、你的电子邮件地址、 当前 * 日期和时间等信息,以确保它的唯一性--但是它和你刚刚复制的提交“做了同样的事情”(或多或少有相同的差异)。
git cherry-pick --continue
git commit
cherry-pick
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
git fetch
$HOME/work/project23/
$HOME/work/project45/
project45
git remote add project23 $HOME/work/project23 git fetch project23
现在你的project45仓库中已经有了project23的所有提交。这会使仓库膨胀一些,但是只要你有足够的磁盘空间,就没有必要再挑剔了。现在你可以运行git cherry-pick命令了。当您完成并想要清理时,运行:
project23
git remote remove project23
这将删除 nameproject23以及对其他Git仓库的引用。Git将保留所有复制的提交一段时间,但最终会将其清除,仓库也会缩小,并且git push不会将所有提交复制到其他地方:它们只是坐在那里占据 * 那个特定克隆 * 的空间,直到Git开始清理。(If如果你想强制Git提前清理,你可以运行git gc --prune=now,但除非你的磁盘空间非常紧张,否则我不推荐你这么做。
git push
git gc --prune=now
2条答案
按热度按时间ldfqzlk81#
找到了我的笔记,由于标记的原因,无法在评论中很好地发布此内容,基本行如下:
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就可以得到:
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 switch
或git checkout
:然后你给予
git cherry-pick
一个你想复制其 effect 的提交的原始哈希ID,或者,如果你有一个分支或标签名,当解析为一个原始哈希ID时,得到了正确的提交的原始哈希ID,你可以使用那个名称,但我们在这里只使用一个原始哈希ID:Git现在找到了你在这里指定的提交(我选择了
C1
)。它 * 必须存在于你当前的仓库中 。Git使用该提交的元数据来找到该提交的父提交:必须只有一个父提交,这使得这是一个普通的提交。2 Git将提交的快照(本例中为C1
)与其父提交的快照进行比较,找出修改了什么,然后找出如何将这些修改 * 合并 * 到 * 当前提交 * 中。这种组合从技术上讲是一种合并操作--我喜欢称之为“作为动词合并”--这意味着您可能会遇到合并冲突。如果确实遇到合并冲突,您可以用通常的方法解决它们。一旦完成,您可以使用
git cherry-pick --continue
或git 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
)中:现在你的
project45
仓库中已经有了project23
的所有提交。这会使仓库膨胀一些,但是只要你有足够的磁盘空间,就没有必要再挑剔了。现在你可以运行git cherry-pick
命令了。当您完成并想要清理时,运行:
这将删除 name
project23
以及对其他Git仓库的引用。Git将保留所有复制的提交一段时间,但最终会将其清除,仓库也会缩小,并且git push
不会将所有提交复制到其他地方:它们只是坐在那里占据 * 那个特定克隆 * 的空间,直到Git开始清理。(If如果你想强制Git提前清理,你可以运行
git gc --prune=now
,但除非你的磁盘空间非常紧张,否则我不推荐你这么做。