【问题标题】:GIT how to merge master into branch cloned with -single-branchGIT如何将master合并到使用-single-branch克隆的分支中
【发布时间】:2017-11-07 08:49:10
【问题描述】:

我有一个 git 存储库,其中 master 是应用程序的当前版本,每个客户都有自己的分支和自己的自定义设置。

我已使用 --single-branch 将每个客户分支分别克隆到一个目录中

我的目标是将 master 合并到我的分支中。我已经使用以下命令克隆了 repo:

git clone {{REPO_URL}} --single-branch my-branch --branch my-branch

然后我尝试了:

git fetch origin -- master

git merge master

然后我得到这个

merge: master - 不是我们可以合并的东西

我知道我可以通过克隆整个存储库来解决这个问题,但是有没有办法解决这个问题?

【问题讨论】:

    标签: git merge version-control


    【解决方案1】:

    您只需将 url 添加为本地存储库中的另一个远程。

    详细命令如下:

    # In local my-branch
    git remote add upstream <repo URL> -f
    git merge upstream/master
    

    现在您的本地 my-branch 包含来自 master 分支的更改。


    更新:只为master分支添加远程,可以使用命令:

    git remote add upstream <repo URL> -t master -f
    

    如果您已经将远程 upstream 添加到所有分支,您可以通过以下方式进行更改:

    git remote rm upstream
    git remote add upstream <repo URL> -t master -f
    

    【讨论】:

    • 这可行,但它会拉动所有分支,这是我想要避免的事情。回购中有这么多数据,我不想有整个回购的很多副本。这就是首先使用 --single-branch 的原因。是否可以只为 master 添加上游?
    • @Firze 是的,这是可能的。 -t branchname 可以做到这一点。您可以在我的回答中找到详细信息。
    【解决方案2】:

    TL;DR

    你必须:

    • FETCH_HEAD合并,或
    • git fetch refspec 中指定目标引用名称,或
    • 调整remote.origin.fetch 设置

    或这些项目的某种组合。例如,根据使用的组合,您可能希望获取到 refs/remotes/origin/master 并运行 git merge origin/master

    说明

    关键在于refspecs。 refspec 是第二简单的形式,是一对由冒号分隔的 references,例如 refs/heads/master:refs/heads/master。在某些情况下,引用可以缩写,例如,master:master。左边的名字是source,右边的名字是destination(Git 文档缩写为)。

    那么,考虑一下你的命令:

    git fetch origin -- master
    

    -- 在这里毫无意义。)git fetch 命令将origin 视为存储库的名称(因此它查找与origin 关联的URL,以及与@ 关联的fetch = refspecs 987654335@),然后将 master 视为 refspec,与任何先前定义的 fetch refspec 结合并部分覆盖。

    当您进行--single-branch 克隆时:

    git clone {{REPO_URL}} --single-branch --branch my-branch
    

    这会更改与新克隆关联的fetch refspec。 (注意:额外的 my-branch 参数最终被视为目录名称。)运行:

    git config --list --local
    

    将向您展示,以及其他项目:

    remote.origin.url=... whatever the URL expanded to...
    remote.origin.fetch=+refs/heads/my-branch:refs/remotes/origin/my-branch
    

    这告诉你的 Git,当它通过 origin 联系另一个 Git 时,默认操作是获取他们的分支 my-branch,并将结果复制到您的远程跟踪名称origin/my-branch

    当您在没有其他参数的情况下运行 git fetch origin 时,您的 Git 会执行此默认操作。

    如果没有--single-branch,Git 会使用默认的 refspec,fetch=+refs/heads/*:refs/remotes/origin/*。这将指示 Git 获取 所有 分支(所有 refs/heads/ 名称),并将它们复制到您自己的存储库中的远程跟踪名称。

    当你给git fetch origin 附加参数时,它们是refspecs,就像fetch 设置一样。例如,你可以这样写:

    git fetch origin +refs/heads/normalbranch:refs/strangeref
    

    这将指导您的 Git 将他们的(本地的,非常正常的)分支 normalbranch 复制到您自己的存储库中名为 refs/strangeref 的本地引用。

    现在,我在上面说过一对名称是 second 最简单的 refspec 形式。您使用的是最简单的:一个名称,master。没有冒号;没有第二个名字。这仍然是一个有效的 refspec,但它的含义git fetchgit push 中是不同的。既然我们只关心git fetch,那么让我们关注see what it means there,即:

      指定要获取哪些 refs 以及要更新哪些本地 refs。 ...
      参数的格式是可选的加号 +,后跟源 ,后跟冒号 `:`,后跟目标 ref 为空时,可以省略冒号。 ...
      获取匹配的远程ref,如果不是空字符串,则匹配它的本地ref使用快进。 ...

    由于您没有: 和目标,因此 部分为空,并且没有本地引用被快进。 (前导加号 + 会告诉 Git 强制更新本地引用,即使快进会失败,但您首先会忽略本地引用,因此 + 强制标志不会影响任何内容。 )

    这意味着git fetch 带来的提交仅记录在与 Git 版本 1.5 向后兼容的旧 FETCH_HEAD 文件中。所以你必须 git merge FETCH_HEAD 来合并 ID 保存在 FETCH_HEAD 中的提交——另一个 Git 的 master 分支的提示提交。

    其他选择

    如果您在命令行上提供不存在的目标 refspec:

    git fetch origin master:refs/heads/tmpbranch
    

    (在这种情况下会创建一个名为 tmpbranch 的新本地分支),然后您可以将其作为参数提供给 git merge

    git merge tmpbranch
    

    然后删除它:

    git branch -D tmpbranch
    

    以便您为下一次做好准备(没有 tmpbranchgit fetch 可能失败)。

    或者,您可以使用 force-flag 强制创建或更新您自己的 master 分支:

    git fetch origin +master:master
    

    (这依赖于 Git 将 master 转换为 refs/heads/master 的自动限定 - 如果您正在编写脚本,最好明确地拼出它;自动限定适用于懒惰的人,而不是计算机)。然后你可以git merge master

    请注意,如果您已创建并正在使用它,这将覆盖您自己的本地 master。因此,您可能希望使用远程跟踪名称:

    git fetch origin +master:refs/remotes/origin/master
    

    之后您将运行git merge origin/master

    最后,您可以指示您的 Git 始终默认获取其他 Git 的 master

    git config --add remotes.origin.fetch '+refs/heads/master:refs/remotes/origin/master'
    

    现在你可以运行了:

    git fetch origin
    git merge origin/master
    

    现在从 origin 获取,因为有两个 remote.origin.fetch 设置,获取 both 的其他 Git 分支,mybranch master,将获取的哈希 ID 放入您的远程跟踪名称 refs/remotes/origin/mybranchrefs/remotes/origin/master

    (将此与默认 refspec +refs/heads/*:refs/remotes/origin/* 进行比较,后者告诉您的 Git 获取 所有 分支并创建或更新名称与另一个 Git 中的分支名称匹配的远程跟踪名称。 )

    【讨论】:

    • TLDR:git fetch origin +master:refs/remotes/origin/master。阅读上面的内容和原因。感谢@torek 提供的所有详细信息!
    【解决方案3】:

    我克隆了一个分支,深度为 1(单次提交):

    git clone --depth 1 --single-branch branch_to_merge
    

    现在我想将它合并到一个新的分支“destn_branch”中,但没有在我的本地克隆它,所以我不得不先再次获取分支......

    git fetch --depth 1 origin destn_branch:destn_branch
    

    (我不应该做深度1,但我别无选择:(,提交太多>_>)

    现在我可以

    git checkout destn_branch
    git merge branch_to_merge
    

    但是 git 说“你疯了吗,那两个分支是不相关的”(那是“不寻常的历史”的东西,我忘记了文字)

    所以我通过以更深的深度重新运行上述命令来提升 git,以便它们共享一个共同的历史提交,并且 git 可以理解它可以从那里链接 2 个分支...... 所以,我重新运行了以下命令并且它起作用了:

    // fetch 3 latest commits of branch_to_merge
    git checkout branch_to_merge
    git fetch --depth 3
    
    // fetch 4 latest commits of destn_branch - this way one of the fetched commits is the same as in other branch's fetched commit
    git fetch --depth 4 origin destn_branch:destn_branch
    
    // now do a normal merge
    git checkout destn_branch
    git merge branch_to_merge
    

    还骂我小气,老是做depth-1单克隆pull-_-,现在谁审慎了>_>

    【讨论】:

      猜你喜欢
      • 2013-07-16
      • 1970-01-01
      • 2016-04-30
      • 2013-06-27
      • 2021-06-06
      • 2013-01-14
      • 2016-09-20
      • 2021-10-18
      相关资源
      最近更新 更多