【问题标题】:Rename master branch for both local and remote Git repositories重命名本地和远程 Git 存储库的主分支
【发布时间】:2010-12-04 08:24:17
【问题描述】:

我有分支master,它跟踪远程分支origin/master

我想在本地和远程将它们重命名为master-old。这可能吗?

对于跟踪 origin/master 的其他用户(并且总是通过 git pull 更新其本地 master 分支),我重命名远程分支后会发生什么?
他们的git pull 是否仍然有效,还是会抛出一个无法再找到origin/master 的错误?

然后,进一步,我想创建一个新的master 分支(本地和远程)。同样,在我这样做之后,如果其他用户现在这样做git pull,会发生什么?

我想这一切都会带来很多麻烦。有没有一种干净的方法可以得到我想要的东西?还是我应该保留master 并创建一个新分支master-new 并继续在那里工作?

【问题讨论】:

  • 接受的答案中给出的配方确实适用于任何名称的分支,但由于 master Git 中的分支。
  • @kynan:我想我不明白。哪些注意事项适用于 master 而不适用于其他分支?如果它是一个名为 xy 的分支,并且其他人已经跟踪了该分支,那会有什么不同?
  • 警告您不能正常删除远程主机。不过,这不适用于亚里士多德的答案,因此您可能希望将其标记为已接受的答案。你是对的,任何git push -f 都会影响从任何远程跟踪分支pull 的能力。
  • 您可以创建一个新分支master-old,它指向与之前的master 分支相同的提交。然后,您可以使用ours 策略执行merge,用您的新更改覆盖master 分支。当远程不允许非快进更改时,执行合并工作。这也意味着其他用户不会强制更新。
  • @kynan master 仅在它是唯一现有的分支时才特别。只要你有多个分支,所有分支都处于平等地位。

标签: git git-branch git-pull


【解决方案1】:

有很多方法可以重命名分支,但我将关注更大的问题:“如何让客户快速前进,而不必在本地弄乱他们的分支”

先来一张图片:

这实际上很容易做到;但不要滥用它。 整个想法取决于合并提交;因为它们允许快进,并将一个分支的历史与另一个链接。

重命名分支:

# rename the branch "master" to "master-old"
# this works even if you are on branch "master"
git branch -m master master-old

创建新的“master”分支:

# create master from new starting point
git branch master <new-master-start-point>

创建合并提交以拥有父子历史记录:

# now we've got to fix the new branch...
git checkout master

# ... by doing a merge commit that obsoletes
# "master-old" hence the "ours" strategy.
git merge -s ours master-old

瞧。

git push origin master

这是可行的,因为创建merge 提交允许快进分支到新修订。

使用合理的合并提交消息:

renamed branch "master" to "master-old" and use commit ba2f9cc as new "master"
-- this is done by doing a merge commit with "ours" strategy which obsoletes
   the branch.

these are the steps I did:

git branch -m master master-old
git branch master ba2f9cc
git checkout master
git merge -s ours master-old

【讨论】:

  • 谢谢! git merge -s ours master-old 是其他答案错过的关键部分。另外,“容易做”并不意味着“容易理解或发现”,这似乎是大部分 git 的情况,但我离题了。
  • 我喜欢这样一个事实,即没有提到任何删除,并且那些使用上游克隆的人的过渡是“无缝的”。谢谢!
  • 如果 master 有你不想要 master-new 的更改,这是否有效?
【解决方案2】:

转到 github.com 或其他任何地方,单击分支,然后重命名它。然后在本地运行这些:

git branch -m <old-branch-name> <new-branch-name>
git fetch origin
git branch -u origin/<new-branch-name> <new-branch-name>

【讨论】:

    【解决方案3】:

    可以将以下内容保存到 shell 脚本中来完成这项工作:

    例如:

    remote="origin"
    
    if [ "$#" -eq 0 ] # if there are no arguments, just quit
    then
        echo "Usage: $0 oldName newName or $0 newName" >&2
        exit 1
    elif
        [ "$#" -eq 1 ] # if only one argument is given, rename current branch
    then
        oldBranchName="$(git branch | grep \* | cut -d ' ' -f2)" #save current branch name
        newBranchName=$1
    else
        oldBranchName=$1
        newBranchName=$2
    fi
    
    git branch -m $oldBranchName $newBranchName
    
    git push $remote :$oldBranchName # Delete old branch on remote
    git push --set-upstream $remote $newBranchName # Add new branch name on remote and track it
    

    请注意这里默认的远程名称“origin”是硬编码的。您可以扩展脚本以使其可配置!

    然后,此脚本可以与 Bash 别名、Git 别名或在例如 Sourcetree 自定义操作中一起使用。

    【讨论】:

      【解决方案4】:

      这是我所知道的最简单和最“可读”的方式:

      使用 -m '移动'本地分支

      git branch -m my_old_branch_name my_new_branch_name
      

      将“已移动”分支推送到远程,使用 -u 设置“上游”

      git push origin -u my_new_branch_name
      

      设置“上游”实质上是将本地分支“连接”到远程分支,以便获取、拉取和推送等操作。

      从远程删除旧分支

      git push origin -D <old_name>
      

      您的本地分支机构已经消失,因为您在第一步中“移动”了它。

      【讨论】:

        【解决方案5】:

        好的,在本地远程上重命名一个分支非常简单!...

        如果你在分支上,你可以轻松做到:

        git branch -m &lt;branch&gt;

        如果没有,你需要这样做:

        git branch -m &lt;your_old_branch&gt; &lt;your_new_branch&gt;

        然后,像这样将删除推送到远程:

        git push origin &lt;your_old_branch&gt;

        现在你已经完成了。

        如果您在尝试推送时遇到上游错误,只需执行以下操作:

        git push --set-upstream origin &lt;your_new_branch&gt;

        我还创建了下面的图像以显示真实命令行上的步骤。只需按照步骤操作即可:

        【讨论】:

        • 您的推送删除建议无效,我需要运行: git push origin --delete
        【解决方案6】:

        selected answer 在我尝试时失败了。它会引发错误:refusing to delete the current branch: refs/heads/master。我想我会发布适合我的:

        git checkout master             # If not in master already
        
        git branch placeholder          # Create placeholder branch
        git checkout placeholder        # Check out to placeholder
        git push remote placeholder     # Push placeholder to remote repository
        
        git branch -d master            # Remove master in local repository
        git push remote :master         # Remove master from remote repository.
        

        诀窍是在将占位符推送到远程存储库之前检查占位符。其余的不言自明;删除主分支并将其推送到远程存储库现在应该可以工作了。摘自here

        【讨论】:

        • 如果在远程端进行检查,它将在 git push remote :master 上失败 - 您将在错误日志行中看到“remote:error:”作为前缀。
        【解决方案7】:

        登录服务器,进入Git目录,在裸仓库重命名分支。

        这并不存在与重新上传同一分支相关的所有问题。实际上,“客户端”会自动识别修改后的名称并更改其远程引用。

        之后(或之前)您还可以修改分支的本地名称。

        【讨论】:

        • 我忘记了登录 github 服务器的凭据。任何有凭据的人:-P
        【解决方案8】:

        最接近重命名的是删除然后在遥控器上重新创建。例如:

        git branch -m master master-old
        git push remote :master         # Delete master
        git push remote master-old      # Create master-old on remote
        
        git checkout -b master some-ref # Create a new local master
        git push remote master          # Create master on remote
        

        但是,这有很多警告。首先,现有的结帐不会知道重命名 - Git 确实 尝试跟踪分支重命名。如果新的master 还不存在,git pull 会报错。如果已创建新的master。拉取将尝试合并mastermaster-old。所以这通常是个坏主意,除非您得到之前签出存储库的每个人的合作。

        注意:较新版本的 Git 默认不允许远程删除 master 分支。您可以通过在remote 存储库上将receive.denyDeleteCurrent 配置值设置为warnignore 来覆盖它。否则,如果您准备好立即创建新的主节点,请跳过git push remote :master 步骤,并将--force 传递给git push remote master 步骤。请注意,如果您无法更改远程的配置,您将无法完全删除 master 分支!

        此警告仅适用于当前分支(通常是master 分支);任何其他分支都可以像上面那样删除和重新创建。

        【讨论】:

        • 分支只是一个(名称,哈希)对 - 不多也不少。分支上有 reflog,但这永远不会暴露给远程客户端。
        • 在删除远程主机之前,我会在远程主机上创建旧主机。我只是偏执。
        • 亚里士多德在下面的回答允许你在不删除主人的情况下做到这一点,所以我认为这更可取。
        • 如果您可以使用new-branch-nameold-branch-name 而不是master/master-old,这将是明确且安全的,因此这是一个普遍的问题。
        • 如果删除的分支(这里:master)没有被其他分支引用,git 可能会垃圾收集那个......好吧......“分支”上的所有提交。 – 一些 git瓷器命令触发垃圾收集。 – 因此:先创建新名称(指向同一个提交),然后删除旧名称。
        【解决方案9】:

        您可以执行以下操作:

        git -m master master-old #rename current master
        git checkout -b master   #create a new branch master
        git push -f origin master #force push to master
        

        但是,如果其他人共享此存储库,则强制推送是一个坏主意。强制推送将导致他们的修订历史与新的冲突。

        【讨论】:

          【解决方案10】:

          我相信关键是意识到您正在执行 double 重命名:mastermaster-old 以及 master-newmaster

          从我总结的所有其他答案中:

          doublerename master-new master master-old
          

          我们首先要定义doublerename Bash 函数:

          # doublerename NEW CURRENT OLD
          #   - arguments are branch names
          #   - see COMMIT_MESSAGE below
          #   - the result is pushed to origin, with upstream tracking info updated
          doublerename() {
            local NEW=$1
            local CUR=$2
            local OLD=$3
            local COMMIT_MESSAGE="Double rename: $NEW -> $CUR -> $OLD.
          
          This commit replaces the contents of '$CUR' with the contents of '$NEW'.
          The old contents of '$CUR' now lives in '$OLD'.
          The name '$NEW' will be deleted.
          
          This way the public history of '$CUR' is not rewritten and clients do not have
          to perform a Rebase Recovery.
          "
          
            git branch --move $CUR $OLD
            git branch --move $NEW $CUR
          
            git checkout $CUR
            git merge -s ours $OLD -m $COMMIT_MESSAGE
          
            git push --set-upstream --atomic origin $OLD $CUR :$NEW
          }
          

          这类似于更改历史记录的git rebase,因为分支内容完全不同,但不同之处在于客户端仍然可以安全地使用git pull master 快进。

          【讨论】:

            【解决方案11】:
            git update-ref newref oldref
            git update-ref -d oldref newref
            

            【讨论】:

            • 这似乎对我不起作用,我得到: git update-ref trunk trunk2 fatal: trunk2: not a valid SHA1
            • 解释一下。
            【解决方案12】:
            git checkout -b new-branch-name
            git push remote-name new-branch-name :old-branch-name
            

            在删除old-branch-name之前,您可能需要手动切换到new-branch-name

            【讨论】:

            • 此解决方案的任何部分是否删除了本地旧分支名称,或者这是一个单独的练习?
            • 我认为最后必须运行git branch -d old-branch-name 删除本地旧分支。
            • 您只能通过一个命令推送更改:git push remote-name new-branch-name :old-branch-name
            • 这种方式不会让你的 git 历史复杂化吗?因为您正在打开一个新分支,而不是重命名当前分支。
            • @androider No. git 中的分支是a simple references
            【解决方案13】:

            在 Git v1.7 中,我认为这已经略有改变。更新本地分支对新远程的跟踪引用现在非常容易。

            git branch -m old_branch new_branch         # Rename branch locally    
            git push origin :old_branch                 # Delete the old branch    
            git push --set-upstream origin new_branch   # Push the new branch, set local branch to track the new remote
            

            【讨论】:

            • --set-upstream 的替代方法如下:在本地重命名分支并在源上删除后,只需执行以下操作:git push -u --all
            • 这不适用于 master 分支,因为 git 不允许您删除远程 master。
            • @AlexandreNeto 在这种情况下,您可以在第 2 行之前执行第 3 行,将默认分支设置为 new_branch,然后最终使用第 2 行删除远程 master
            • 非常简单的步骤。这是问题的最佳答案
            • 删除远程分支git push origin --delete old_branch 可读性稍强。
            【解决方案14】:

            假设你目前在master:

            git push origin master:master-old        # 1
            git branch master-old origin/master-old  # 2
            git reset --hard $new_master_commit      # 3
            git push -f origin                       # 4
            
            1. 首先基于本地存储库中的master 提交,在origin 存储库中创建一个master-old 分支。
            2. 为这个新的origin/master-old 分支创建一个新的本地分支(将自动正确设置为跟踪分支)。
            3. 现在将您的本地 master 指向您希望它指向的任何提交。
            4. 最后,强制更改 origin 存储库中的 master 以反映新的本地 master

            (如果您以任何其他方式执行此操作,则至少需要一个步骤以确保正确设置 master-old 以跟踪 origin/master-old。在撰写本文时发布的其他解决方案均不包括.)

            【讨论】:

            • 这比“答案”更好,我同意,但对于来这里只是重命名分支的人(不是明确的 master),第三步没有多大意义。跨度>
            • 无论您是在master 还是其他分支上,答案都绝对没有区别。这个问题的标题很糟糕,它询问的任务比只是重命名一个分支更复杂。
            • 事实证明这是对我有用的解决方案。我试图用另一个分支替换 master 。我做了一个 git log -1 origin/what_i_want_as_new_master 来获取第 3 步的 $new_master_commit。在推送(第 4 步)之后,其他开发人员会拉取并获取消息“你的分支比 master 领先 295 次提交。”为了解决这个问题,我发送了一封电子邮件,让他们知道每次运行: git pull; git checkout some_random_branch; git 分支 -D 主;混帐拉; git结帐大师;基本上,他们需要删除本地 master 并拉取新版本,否则他们在本地错误的地方。
            • 您可以更轻松地做到这一点:假设他们已经在 master 上,那么他们可以通过 git fetch &amp;&amp; git reset --hard origin/master 强制他们的本地 master 与 @ 上的相同987654338@。我已经记录了这一点,以及更复杂的情况,即您在 stackoverflow.com/q/4084868 中想要保留的 master 之上的本地提交
            • 确保远程配置文件有“denyNonFastforwards = false”,否则你会得到“remote: error:denying non-fast-forward refs/heads/master(你应该先拉)”跨度>
            【解决方案15】:

            怎么样:

            git checkout old-branch-name
            git push remote-name new-branch-name
            git push remote-name :old-branch-name
            git branch -m new-branch-name
            

            【讨论】:

            • 搞砸了分支跟踪 - 用户可能不得不在本地修复他们的分支?
            • 解释一下。
            【解决方案16】:

            我假设您仍在询问与previous question 相同的情况。也就是说,master-new 在其历史记录中不会包含 master-old。* 如果您将 master-new 称为“master”,您将有效地重写历史记录。 如何进入一个 master 不是 master 先前位置的后代的状态并不重要,只是它处于那个状态。

            其他用户在 master 不存在时尝试拉取只会导致他们的拉取失败(远程上没有这样的 ref),并且一旦它再次存在于新位置,他们的拉取将不得不尝试将他们的 master 与新的远程master,就像你在你的存储库中合并了master-old和master-new一样。鉴于您在这里尝试执行的操作,合并会产生冲突。 (如果它们被解决,并且结果被推回存储库,您将处于更糟糕的状态 - 两个版本的历史都存在。)

            简单地回答您的问题:您应该接受有时会在您的历史记录中出现错误的事实。这没关系。它发生在每个人身上。 git.git 存储库中有还原的提交。重要的是,一旦我们发布历史,这是每个人都可以信任的。

            *如果是这样,这相当于将一些更改推送到 master,然后在原来的位置创建一个新分支。没问题。

            【讨论】:

            • 是的,这是同一个问题,只是一个想法如何解决它。但即使我不做这个分支重命名,如果可能的话,我很有趣。我认为像“master”这样的引用只是对特定提交的引用。我真的不想改变任何历史。我想我只是将主参考指向另一个头。这也意味着,如果我以前使用过分支名称,我将永远无法再次使用它?
            • 确实,分支是 refs - 指向提交的指针。问题是,我们希望分支的负责人以特定的方式发展(即,总是快进)。从其他人的角度来看,在您的公共仓库中移动一个分支与重写该分支的历史是一样的。它不再指向包含以前所有内容的提交。
            猜你喜欢
            • 2015-08-15
            相关资源
            最近更新 更多