Git 格式-补丁和分支冲突

问题描述 投票:0回答:3

我需要从一个存储库 (

repo-a
) 创建补丁并将它们合并到另一个存储库 (
repo-b
)。这些补丁需要包含提交本身,所以我发现
git format-patch
git am
是完美的选择。

我们在

repo-a
中使用多个分支,有时,文件会
added
来自两个不同的分支并合并到
main

git am
不喜欢这样..这是问题的完整示例;

mkdir repo-a; cd repo-a

git init

touch randomfile
git add randomfile
git commit -m "Adding an initial file"

git checkout -b anotherbranch
touch a-file
git add a-file
git commit -m "Adding a-file from anotherbranch"

git checkout main
touch a-file
git add a-file
git commit -m "Adding a-file from main"

git merge anotherbranch

git format-patch -o patches HEAD~2
# patches/0001-Adding-a-file-from-anotherbranch.patch
# patches/0002-Adding-a-file-from-main.patch

cd ..
mkdir repo-b; cd repo-b
git init
cp -r ../repo-a/patches ./

git am patches/*
# Applying: Adding a-file from anotherbranch
# applying to an empty history
# Applying: Adding a-file from main
# error: a-file: already exists in index
# Patch failed at 0002 Adding a-file from main
# hint: Use 'git am --show-current-patch=diff' to see the failed patch
# When you have resolved this problem, run "git am --continue".
# If you prefer to skip this patch, run "git am --skip" instead.
# To restore the original branch and stop patching, run "git am --abort".

以上失败,因为

git
已经拥有该文件。通常情况下,git 会很高兴并按其应有的方式添加补丁..

有没有办法做到这一点,并保留 git 提交?我不想创建一个大补丁,我也想要提交。

我已阅读https://git-scm.com/docs/git-format-patch在此处输入链接描述。我也尝试过一些随机选项(如

--find-copies-harder
),但没有任何运气。

一些附加信息:

  • rebo-b 是由 repo-a 使用
    cp -r
    rm -rf .git and-some-other-files
    和新的
    git init
    制成的。
    • rebo-b 是主要仓库,rebo-a 只是一个精简版本。
    • 所有这一切的主要目标是让某人能够在 repo-b 上工作,但他们无法访问 rebo-b 中的所有内容。将 repo-b 复制到 repo-a 后,我做了很多文件删除操作,但只是删除。
git version-control
3个回答
2
投票

git format-patch
非常适合提取提交的线性历史记录,但不适用于合并:

描述
准备每个非合并提交及其“补丁”...

[...]
注意事项
请注意,格式补丁将从输出中省略合并提交,即使它们是请求范围的一部分。

  • 正如您在示例中看到的:

anotherbranch
main
上的每个提交创建一个补丁,但没有为合并提交创建补丁,并且如果您检查这些 pacthe,它们不包含表明它们具有相同父级的信息。

这些信息不足以通过合并自动重建历史记录。


可能有多种策略可以将提交从

repo-a
移植到
repo-b
,同时保留分支和合并,但我们需要更多的上下文来为您提供更准确的答案。

例如:一种方法可能是将

repo-a
添加为
repo-b
中的遥控器,并使用
git rebase -r
-r
--rebase-merges
的缩写)或
git filter-repo
的某些子命令来移植完整的历史记录块.


如果您想从 repo-a 中删除文件,但可以显示剩余文件的历史记录,则可以使用

git filter-repo
repo-a
转换为精简版本。好处是该命令以可重复的方式创建提交,因此新提交的历史记录将与之前的提取相匹配。


1
投票

我找到了一种按照我想要的方式做到这一点的方法。

git remote add otherrepo ../otherrepo
git fetch otherrepo

# If you want to fetch lfs objects as well
git lfs fetch --all otherrepo

# -X subtree: Or you will get a lot of merge-conflicts, some of them with empty lines.
# --signoff: To add signoff on the merge-commit (not the merged commits)
# --allow-unrelated-histories: This is the main trick!
git merge -X subtree --signoff --allow-unrelated-histories otherrepo/main

整个历史和一切都按其应有的方式进行。合并提交包含合并的内容,历史记录、图表、作者和一切看起来都不错。


0
投票
git merge anotherbranch

我宁愿rebase目标分支顶部的分支(在主分支之上),然后在新分支HEAD和主分支之间打补丁(而不是

HEAD~2

git switch anotherbranch
git rebase main
git format-patch -o patches main
© www.soinside.com 2019 - 2024. All rights reserved.