在Git中远程重命名分支


407

如果有一个我只能git://访问的存储库(通常只是push + pull),是否有一种方法可以像我在本地使用的一样重命名该存储库中的分支git branch -m


48
链接的“重复”问题要求“在本地和远程”重命名分支。但是,此问题仅询问如何远程重命名分支,这可以简化操作。这是我在服务器上重命名分支而不需要检出和/或创建本地分支的方法:git push origin origin/old_name:refs/heads/new_name && git push origin :old_name
sschuberth,2013年

1
@sschuberth:您可以一次性给出两个命令。这确实应该是这个问题的答案。
约阿希姆·布雷特纳

2
@JoachimBreitner是的,我已经在我的这个脚本中进行了优化。
sschuberth

1
@sschuberth,您应该发表评论作为答案,因为我比下面的其他人更喜欢它。
phatmann 2014年

Answers:


480

您只需使用所需名称创建一个新的本地分支,将其推送到您的远程服务器,然后删除旧的远程分支机构:

$ git branch new-branch-name origin/old-branch-name
$ git push origin --set-upstream new-branch-name
$ git push origin :old-branch-name

然后,要查看旧的分支名称,存储库的每个客户端都必须执行以下操作:

$ git fetch origin
$ git remote prune origin

注意:如果您的旧分支是主分支,则应更改主分支设置。否则,当您运行时 $ git push origin :old-branch-name,会出现错误“禁止删除当前分支”


8
好吧,如果新旧名称相同,则意味着您无需重命名分支,因此首先运行命令是没有意义的;-)
Sylvain Defresne 2014年

9
当然。我只是说,如果您以自动化方式(作为某些其他脚本的功能部分)调用此函数,则可以避免的话,您最好不要这样做。
神秘的丹

9
丹的方式:重新排列命令,以便它们始终有效。Earth Engine的方式:永远记得检查,否则您会丢失数据。我知道我会选哪一个。
Doradus

2
用户可以运行:(git fetch origin --prune以有效地获取新分支,并摆脱不再在远程上的引用)。
DolphinDream '16

2
可以在git的较新版本中使用-d--delete代替:
Zitrax

285

如果您确实只想远程重命名分支,而不必同时重命名任何本地分支,则可以使用一个命令执行此操作:

git push <remote> <remote>/<old_name>:refs/heads/<new_name> :<old_name>

我写了这个脚本(git-rename-remote-branch),它提供了方便的快捷方式来轻松完成上述操作。

作为bash函数:

git-rename-remote-branch(){
  if [ $# -ne 3 ]; then
    echo "Rationale : Rename a branch on the server without checking it out."
    echo "Usage     : $(basename $0) <remote> <old name> <new name>"
    echo "Example   : $(basename $0) origin master release"
    exit 1 
  fi

  git push $1 $1/$2:refs/heads/$3 :$2
}

集成@ksrb的注释:这基本上是在单个命令中进行两次推送,首先git push <remote> <remote>/<old_name>:refs/heads/<new_name>是基于旧的远程跟踪分支推送新的远程分支,然后git push <remote> :<old_name>删除旧的远程分支。


10
对于那些想要该命令别名的人:rename =“!f(){git push origin origin / $ 1:refs / heads / $ 2:$ 1;}; f”可以用作> git named <old_name> < new_name>
乔纳森·施密特

33
对于那些对这个命令实际上意味着什么感到好奇的人,实际上是两次按下命令,git push <remote>/<old_name>:refs/heads/<new_name>意味着推送一个将旧遥控器用作src的新遥控器,然后 git push [space]:<old_name>意味着删除旧遥控器
ksrb 2015年

3
为什么需要使用refs/heads/name?您不能name直接使用第一个命令git push <remote> <remote>/<old_name>:<new_name>吗?
Drew Noakes

6
否,因为远程分支<new_name>尚不存在。如果分支不存在,Git要求您使用全名,否则<new_name>也可能引用标签名。
sschuberth '16

3
我们在构建系统中使用这种方法。我们遇到的唯一警告是如果refs/heads/<new_name> 已经存在。删除仍然成功,导致<remote>/<old_name>仅被删除。事前进行一些检查可以轻松避免这种情况。
Apeiron

172

首先签出要重命名的分支:

git branch -m old_branch new_branch
git push -u origin new_branch

要从中删除旧分支remote

git push origin :old_branch

12
当您将重命名的分支(new_branch)推送到远程(起源)时,还应将其上游设置为使用新名称(例如git push -u origin new_branch)跟踪分支,否则重命名的分支(new_branch)将继续跟踪origin / old_branch。并且,一旦删除了远程old_branch,尽管分支已经消失,new_branch仍将跟踪origin / old_branch。
DolphinDream'2

@DolphinDream我编辑了答案,以包括您有用的上游更改。
mVChr

10

当然。只需在本地重命名分支,推送新分支,然后删除旧分支即可。

唯一的实际问题是,存储库的其他用户不会重命名本地跟踪分支。


1
因此,当尝试删除master时,我尝试了$ git clone ../src $ cd src $ git branch notmaster $ git checkout notmaster $ git branch -d master $ git push ../src:master但它抱怨:目的地refspec既不匹配远程服务器上的现有ref,也不以refs /开头,我们无法根据源ref猜测前缀。错误:无法将某些引用推送到'../alpha/'遥控器确实确实有一个名为master的分支
kdt 2011年

2

TL; DR

“重命名”远程分支实际上是一个两步过程(不一定有序):

  • 删除旧的远程分支(git push [space]:<old_name>ksrb所述);
  • 推送到新的远程分支(以下几个答案命令之间的区别)。

删除中

我使用TortoiseGit,当我第一次尝试通过命令行删除分支时,我得到了:

$ git push origin :in
  • 致命的:'origin'似乎不是git存储库

  • 致命:无法从远程存储库读取。

请确保您具有正确的访问权限,并且存储库存在。

这很可能是由于寻呼机没有加载私钥TortoiseGit自动将其加载到Pageant中)。此外,我注意到TortoiseGit命令中没有originref(例如git.exe push --progress "my_project" interesting_local:interesting)。

我也使用Bitbucket,作为其他基于Web的在线git管理器(GitHub,GitLab),我能够直接通过其界面(分支页面)删除远程分支:

删除分支Bitbucket

但是,在TortoiseGit中,您也可以通过浏览参考删除远程分支:

浏览参考菜单

通过右键单击远程分支(远程列表),将显示“ 删除远程分支”选项:

TortoiseGit远程分支删除

推动

删除旧的远程分支后,我只需通过在Push窗口的Remote:字段中输入新名称,即可通过TortoiseGit直接推入新的远程分支,并且该分支是自动创建的,并且在Bitbucket中可见。

但是,如果您仍然喜欢手动进行操作,则此线程中尚未提及的一点是-u= --set-upstream

git pushdocs开始-u它只是的别名--set-upstream,因此Sylvain(-set-upstream new-branchShashank(-u origin new_branch的答案中的命令是等效的,因为如果以前没有定义其他引用,则远程引用默认为origin

  • git push origin -u new_branch= git push -u new_branch 来自文档说明

    如果缺少配置,则默认为origin

最后,我没有手动键入或使用此处其他答案所建议的任何命令,因此也许这对于类似情况的其他人可能很有用。


问题是您的遥控器没有被呼叫origin。通过运行命令获取远程名称时,必须对其进行命名git remote。Git的工作原理ssh意味着您使用的是公钥和私钥。我假设Autoload Putty keysTortoiseGit只是自动加载所需的键,以便您使用远程引用进行任何操作。最后一件事是,git push -u它不是用于推送到远程分支的别名,它是用于推送到在本地创建的远程分支的别名,并且其远程引用还没有此分支
juanecabellob

1
@juancab -u--set-upstream“” 的别名,“如果缺少配置,则默认为origin ”。SylvainShashank使用它来推动新创建的远程分支。在关键的问题可能是由于选美没有加载它,当我试图git push origin :in在外壳上。因此,我不理解您的不满,我只是在其他答案中指出了我的和未解决的细节,对它们进行了解释并解决了。
CPHPython

您是在说错话,而这个答案中的大部分与问题本身无关。如果您指出什么对您有用,我鼓励您将答案限制在它对您有用的范围内,如果您真的想给出一个解释,请更好地告知自己。顺便说一句:-u是您的别名,--set-upstream但不是推送到远程分支的别名。要推送到远程分支,您非常需要git push <remote>,如果还不在远程分支,则添加git push -u <remote>。因此,-u用于在远程中创建分支的引用。
juanecabellob

1
@juancab也许您认为错了,主要是别名短语或单词选择。我对答案进行了结构调整并重新措辞,以便对我发现的重命名远程分支的解决方案提供完整的说明。
CPHPython

我会再改一下。现在更有意义,但仍然太长。我将更具体地解决该问题,即指出对于TortoiseGit用户而言,建议的解决方案将无法正常工作。您讲的是一个故事,令人困惑,并且使用户避免阅读。我将用一个命题来编辑你的答案。
juanecabellob

1

我不知道为什么,但是@Sylvain Defresne的答案对我不起作用。

git branch new-branch-name origin/old-branch-name
git push origin --set-upstream new-branch-name
git push origin :old-branch-name

我必须取消设置上游,然后才能再次设置流。以下是我的操作方法。

git checkout -b new-branch-name
git branch --unset-upstream
git push origin new-branch-name -u
git branch origin :old-branch-name

0

我不知道这是对还是错,但是我将分支的“旧名称”推到了分支的“新名称”,然后用以下两行完全删除了旧分支:

git push origin old_branch:new_branch
git push origin :old_branch

据我所知,这正是所有其他答案的结果。您的回答更加简洁。
清晰的

-1

您可以基于旧名称分支创建一个新分支。就像这样,然后删除旧分支,结束!!!在此处输入图片说明


那是GitHub,而不是Git。;)
Bouncner

-4

除了已经给出的答案之外,这是一个版本,该版本首先检查新分支是否已存在(因此您可以在脚本中安全地使用它)

if git ls-remote --heads "$remote" \
    | cut -f2 \
    | sed 's:refs/heads/::' \
    | grep -q ^"$newname"$; then
    echo "Error: $newname already exists"
    exit 1
fi
git push "$oldname" "$remote/$oldname:refs/heads/$newname" ":$oldname"

(检查来自此答案


我会用git show-ref --quiet --verify -- refs/heads/$new_name代替ls-remote | cut | sed | grep
安迪
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.