重命名本地和远程Git存储库的master分支


820

我有master跟踪远程分支的分支origin/master

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

对于跟踪的其他用户origin/master(并且总是master通过来更新其本地分支git pull),重命名远程分支后会发生什么?
他们会git pull继续工作还是会抛出一个找不到的错误origin/master

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

我想所有这些都会带来很多麻烦。有没有一种干净的方法来得到我想要的东西?还是我应该保留master原样并创建一个新分支,master-new然后继续进行下一步工作?


2
接受的答案中给出的配方确实适用于任何名称的分支,但由于Git中master分支的默认角色(默认情况下),警告(如上所述)不适用于该分支。
kynan 2012年

3
@kynan:我想我听不懂。有哪些警告适用于母版,不适用于其他分支?如果它是一个名为xy的分支,而其他人已经跟踪了该分支,那会有什么不同?
艾伯特

4
请注意,您通常无法删除远程主机。但是,这不适用于亚里斯多德的答案,因此您可能希望将其标记为可接受的答案。您是正确的,任何git push -f因素都会影响pull从任何远程跟踪分支进行访问的能力。
kynan 2012年

您可以创建一个新分支master-old,该分支指向与先前master分支相同的提交。然后,您可以master通过mergeours策略进行操作来用新的更改覆盖分支。当遥控器不允许非快进更改时,进行合并即可。这也意味着其他用户不会强制更新。
dnozay 2014年

1
@kynan master仅是特殊的,只要它是现有的唯一分支即可。一旦拥有多个分支,所有分支机构将处于平等地位。
jub0bs 2014-09-14

Answers:


614

与重命名最接近的是删除,然后在远程上重新创建。例如:

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

但是,这有很多警告。首先,没有现成的检出会了解重命名-蹦也不会尝试跟踪分支重命名。如果新的master还不存在,则git pull将出错。如果master已创建新的。拉将尝试合并mastermaster-old。因此,除非您与先前签出了存储库的所有人进行合作,否则通常这是一个坏主意。

注意:默认情况下,较新版本的git不允许您远程删除master分支。您可以通过将receive.denyDeleteCurrent配置值设置为远程存储库warnignore远程存储库上来覆盖它。否则,如果您准备立即创建一个新的母版,则跳过该git push remote :master步骤,然后--force转到该git push remote master步骤。请注意,如果您无法更改遥控器的配置,则将无法完全删除master分支!

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


2
分支只是一个(名称,哈希)对-仅此而已。分支上有reflog,但这从未公开给远程客户端。
bdonlan

122
在删除远程主机之前,我会在远程主机上创建master-old。我只是偏执。
亚当·迪米特鲁克

6
以下亚里士多德的答案允许您在不删除母版的情况下执行此操作,因此我认为这是可取的。
粘土桥

13
如果可以使用new-branch-nameold-branch-name代替master/ master-old,这显然是安全的,因此这是一个普遍的问题。
贾德

2
如果其他分支未引用已删除的分支(此处为master),则git可能会垃圾收集该分支上的所有提交……嗯……“分支”。–一些git ceramic命令触发垃圾回收。–因此:首先创建新名称(指向相同的提交),然后删除旧名称。
罗伯·西默

257

假设您目前在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-old分支。originmaster
  2. 为此新origin/master-old分支创建一个新的本地分支(它将自动正确地设置为跟踪分支)。
  3. 现在将您的本地对象指向您master希望其指向的任何提交。
  4. 最后,masterorigin存储库中强制更改以反映您的新local master

(如果以任何其他方式执行此操作,则至少需要再执行一个步骤,以确保master-old已正确设置以进行跟踪origin/master-old。在撰写本文时,其他任何解决方案都没有。)


11
我同意,这比“答案”更好,但是对于那些来这里只是为了重命名分支(不是显式主节点)的人而言,第三步没有多大意义。
knocte 2012年

无论您在master其他分支机构上,答案都完全没有区别。这个问题被严重题目,虽然,它询问比更复杂的任务只是重命名一个分支。
亚里斯多德·帕加尔兹

3
原来这是对我有用的解决方案。我试图用另一个分支替换master。我做了一个git log -1 origin / what_i_want_as_new_master来获取步骤3的$ new_master_commit。在推送(步骤4)之后,其他开发人员会拉出并收到消息“您的分支在295次提交之前领先于master”。为了解决这个问题,我发出了一封电子邮件,通知他们每次运行:git pull; git checkout some_random_branch; git branch -D master; git pull; git checkout master; 基本上,他们需要删除其本地母版并拉出新版本,否则它们将在本地放置在错误的位置。
nairbv

您本可以轻松得多地完成此操作:假设他们已经在开,master然后他们可以git fetch && git reset --hard origin/master强制当地人master与on相同origin。我已masterstackoverflow.com/q/4084868中
Aristotle Pagaltzis 2013年

确保远程配置文件具有“ denyNonFastforwards = false”,否则您将得到“远程:错误:拒绝非快速转发的refs / heads / master(您应该先拉)”
gjcamann 2014年

159

对于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

10
替代方法--set-upstream如下:将分支机构在本地重命名并在原点上删除后,只需执行以下操作: git push -u --all
lucifurious

4
这不适用于master分支,因为git不允许您删除远程master。
Alexandre Neto 2014年

4
@AlexandreNeto在这种情况下,您可以在第二行之前执行第三行,将默认分支设置为new_branch,然后最终master使用第二行删除遥控器。
Tristan Jahier 2015年

3
简单的步骤。这是该问题的最佳答案
siddhusingh 2015年

13
删除远程分支git push origin --delete old_branch更具可读性。
ThomasW

35
git checkout -b new-branch-name
git push remote-name new-branch-name :old-branch-name

您可能需要手动切换到new-branch-name才能删除old-branch-name


此解决方案的任何部分都会删除本地的old-branch-name,还是那很分散的练习?
GreenAsJade 2013年

4
我认为最后必须运行git branch -d old-branch-name以删除本地旧分支。
纳比·卡兹

您只能通过一个命令来推送更改:git push remote-name new-branch-name :old-branch-name
2014年

这样您就不会使git历史复杂化吗?因为您要打开一个新分支,而只需重命名当前分支即可。
androidevil

1
@androider号。git中的分支是一个简单的引用
Sigod 2014年

29

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

首先快速看一下: 重命名主分支并允许客户快速前进

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

重命名分支:

# 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

3
谢谢!git merge -s ours master-old是其他答案错过的关键要素。另外,“容易做”并不意味着“容易理解或发现”,这在很多git中都是如此,但我离题了。
Martin Vidner

3
我喜欢这样的事实:没有提到删除,对于上游克隆的过渡是“无缝的”。谢谢!
Piotrek '16

12

我假设您仍在询问与上一个问题相同的情况。也就是说,“ master-new”将在其历史记录中不包含“ master-old”。*如果您将master-new称为“ master”,则实际上将重写历史记录。不要紧,怎么你进入,其中主不主的前面位置的后裔,只是它是在该州的状态。

其他在主服务器不存在时尝试进行拉取的用户只会使其拉取失败(在远程上没有此类引用),一旦再次存在于新位置,他们的拉取将不得不尝试将其主服务器与新的远程主服务器合并,就像您在存储库中合并了master-new和master-new一样。鉴于您要在此处执行的操作,合并将产生冲突。(如果解决了这些问题,并且将结果推回到了存储库中,那么您将处于更加糟糕的状态-那里的两个版本的历史记录。)

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

*如果这样做的话,这等效于将一些更改推送到master上,然后在以前的位置创建一个新分支。没问题。


是的,这是同样的问题,只是解决问题的一个主意。但是,即使我不进行分支重命名,如果有可能,我也很有趣。我认为诸如“ master”这样的引用仅是对特定提交的引用。我真的不想更改任何历史记录。我以为我只是将主要参考指向另一个负责人。这也意味着,如果我以前从未使用过分支名称,我将永远无法使用它?
艾伯特

确实,分支是引用-指向提交的指针。问题是,我们希望分支的负责人以特定的方式发展(即始终快进)。从其他人的角度来看,在公共回购中移动分支与重写分支的历史记录相同。它不再指向包含以前使用过的所有内容的提交。
卡斯卡贝尔

8

选择答案时,我尝试失败了。引发错误: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        # checkout 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.

诀窍是在将其推送到远程存储库之前先签出到占位符。其余内容不言自明,删除master分支并将其推送到远程存储库现在应该可以工作。从这里摘录。


如果在远程方面进行了检查,它将在git push remote:master上失败-您将在错误日志行中看到“ remote:error:”作为前缀。
rafalmag 2015年

2

好。我的2美分。如何在服务器上登录,转到git目录并重命名裸存储库中的分支,该如何做?这不具有与重新上载同一分支相关的所有问题。实际上,“客户端”将自动识别修改后的名称并更改其远程引用。之后(或之前),您也可以修改分支的本地名称。


8
我忘记了登录github服务器的凭据。任何有证书的人:-P
Daniel Fisher lennybacon

1

关于什么:

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

搞乱了分支跟踪-用户可能必须在本地修复其分支?
dnozay

1

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

使用-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>

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


1

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

如果您在分支机构,则可以轻松执行以下操作:

git branch -m <branch>

否则,您需要执行以下操作:

git branch -m <your_old_branch> <your_new_branch>

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

git push origin <your_old_branch>

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

git push --set-upstream origin <your_new_branch>

我还创建了下面的图像,以在真实的命令行中显示步骤,只需按照以下步骤操作,您就可以了:

在此处输入图片说明


0

您可以执行以下操作:

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

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


0

可以将以下内容保存到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自定义操作中一起使用。


-1

我相信关键是要意识到您正在执行双重重命名:masterto master-oldmaster-newto master

根据所有其他答案,我对此进行了综合:

doublerename master-new master master-old

我们首先必须定义doublerenameBash函数:

# 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


-5
git update-ref newref oldref
git update-ref -d oldref newref

2
这似乎对我不起作用,我得到:git update-ref trunk trunk2致命:trunk2:无效的SHA1
Gregg Lind 2010年
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.