Đổi tên nhánh chính cho cả kho Git cục bộ và từ xa


821

Tôi có chi nhánh mastertheo dõi chi nhánh từ xa origin/master.

Tôi muốn đổi tên chúng thành master-oldcả cục bộ và từ xa. Điều này có thể không?

Đối với những người dùng khác đã theo dõi origin/master(và luôn cập nhật masterchi nhánh địa phương của họ thông qua git pull), điều gì sẽ xảy ra sau khi tôi đổi tên chi nhánh từ xa?
Họ git pullvẫn sẽ làm việc hay nó sẽ ném một lỗi mà nó không thể tìm thấy origin/masternữa?

Sau đó, xa hơn, tôi muốn tạo một masternhánh mới (cả cục bộ và từ xa). Một lần nữa, sau khi tôi làm điều này, điều gì sẽ xảy ra bây giờ nếu những người dùng khác làm gì git pull?

Tôi đoán tất cả điều này sẽ dẫn đến rất nhiều rắc rối. Có một cách sạch sẽ để có được những gì tôi muốn? Hay tôi chỉ nên để nguyên masternhư vậy và tạo một chi nhánh mới master-newvà chỉ làm việc ở đó hơn nữa?


2
Các công thức được đưa ra trong các câu trả lời được chấp nhận không áp dụng đối với một chi nhánh của tên bất kỳ, nhưng hãy cẩn thận (như đã nêu) không, do (theo mặc định) vai trò đặc biệt của tổng chi nhánh tại Git.
kynan

3
@kynan: Tôi nghĩ tôi không hiểu. Những gì hãy cẩn thận áp dụng cho chủ và không áp dụng trên các ngành khác? Nếu đó là một nhánh có tên xy và những người khác đã theo dõi nhánh đó, thì nó sẽ khác như thế nào?
Albert

4
Thông báo trước mà bạn thường không thể xóa chủ từ xa. Điều đó không áp dụng cho câu trả lời của Aristotle, vì vậy bạn có thể muốn đánh dấu đó là câu trả lời được chấp nhận. Bạn đã đúng, mọi git push -fảnh hưởng đến khả năng pulltừ bất kỳ chi nhánh theo dõi từ xa nào.
kynan

bạn có thể tạo một nhánh mới master-oldtrỏ đến cùng một cam kết như masternhánh trước đó . Sau đó, bạn có thể ghi đè lên masterchi nhánh bằng các thay đổi mới của mình bằng cách thực hiện mergevới ourschiến lược. Thực hiện hợp nhất hoạt động khi điều khiển từ xa không cho phép thay đổi không nhanh chóng. Điều đó cũng có nghĩa là những người dùng khác sẽ không phải cập nhật bắt buộc.
dnozay

1
@kynan masterchỉ đặc biệt miễn là nó là chi nhánh duy nhất hiện có. Ngay khi bạn có nhiều hơn một, tất cả các chi nhánh đều bình đẳng.
jub0bs

Câu trả lời:


615

Điều gần nhất để đổi tên là xóa và sau đó tạo lại trên điều khiển từ xa. Ví dụ:

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

Tuy nhiên điều này có rất nhiều cảnh báo. Đầu tiên, không có kiểm tra hiện tại sẽ biết về việc đổi tên - git không cố gắng theo dõi các đổi tên chi nhánh. Nếu cái mới masterchưa tồn tại, git pull sẽ báo lỗi. Nếu cái mới masterđã được tạo ra. kéo sẽ cố gắng hợp nhất mastermaster-old. Vì vậy, nói chung đó là một ý tưởng tồi trừ khi bạn có sự hợp tác của tất cả những người đã kiểm tra kho lưu trữ trước đó.

Lưu ý: Theo mặc định, các phiên bản mới hơn của git sẽ không cho phép bạn xóa nhánh chính từ xa. Bạn có thể ghi đè lên điều này bằng cách đặt receive.denyDeleteCurrentgiá trị cấu hình thành warnhoặc ignoretrên kho lưu trữ từ xa . Mặt khác, nếu bạn đã sẵn sàng để tạo một chủ mới ngay lập tức, hãy bỏ qua git push remote :masterbước này và chuyển --forcesang git push remote masterbước. Lưu ý rằng nếu bạn không thể thay đổi cấu hình của điều khiển từ xa, bạn sẽ không thể xóa hoàn toàn nhánh chính!

Thông báo trước này chỉ áp dụng cho chi nhánh hiện tại (thường là masterchi nhánh); bất kỳ nhánh nào khác có thể bị xóa và tạo lại như trên.


2
các nhánh chỉ là một cặp (tên, hàm băm) - không hơn, không kém. Có các reflog trên các chi nhánh, nhưng điều này không bao giờ được tiếp xúc với các máy khách từ xa.
bdonlan

122
Tôi sẽ tạo master-old trên remote trước khi xóa master trên remote. Tôi chỉ là hoang tưởng.
Adam Dymitruk

6
Câu trả lời của Aristotle dưới đây cho phép bạn thực hiện việc này mà không xóa chủ, vì vậy tôi nghĩ rằng điều đó tốt hơn.
Cầu đất sét

13
Sẽ rõ ràng và AN TOÀN nếu bạn có thể sử dụng new-branch-nameold-branch-namethay vì master/ master-old, do đó đây là một vấn đề chung.
Jaider

2
Nếu nhánh bị xóa (ở đây: master) không được các nhánh khác tham chiếu, git có thể rác thu thập tất cả các cam kết trên đó ... à .... - Một số lệnh git sứ kích hoạt bộ sưu tập rác. - Do đó: tạo tên mới trước (chỉ vào cùng một xác nhận), sau đó xóa tên cũ.
Robert Siemer

257

Giả sử bạn hiện đang trên 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. Đầu tiên tạo một master-oldnhánh trong originkho lưu trữ, dựa trên mastercam kết trong kho lưu trữ cục bộ.
  2. Tạo một nhánh cục bộ mới cho nhánh mới này origin/master-old(sẽ tự động được thiết lập đúng như một nhánh theo dõi).
  3. Bây giờ hãy trỏ địa phương của bạn mastertới bất kỳ cam kết nào bạn muốn nó trỏ tới.
  4. Cuối cùng, thay đổi lực lượng mastertrong originkho lưu trữ để phản ánh địa phương mới của bạn master.

(Nếu bạn thực hiện theo bất kỳ cách nào khác, bạn cần ít nhất một bước nữa để đảm bảo rằng nó master-oldđược thiết lập đúng để theo dõi origin/master-old. Không có giải pháp nào khác được đăng tại thời điểm viết bài này bao gồm điều đó.)


11
Đây là câu trả lời tốt hơn "câu trả lời", tôi đồng ý, nhưng với những người đến đây chỉ đổi tên một chi nhánh (không rõ ràng là chủ), bước thứ 3 không có ý nghĩa gì nhiều.
knocte

Nó hoàn toàn không có sự khác biệt cho câu trả lời cho dù bạn đang ở masterhoặc chi nhánh khác. Câu hỏi được đặt tiêu đề rất tệ, nó hỏi về một nhiệm vụ phức tạp hơn là chỉ đổi tên một chi nhánh.
Aristotle Pagaltzis

3
Điều này hóa ra là giải pháp hiệu quả với tôi. Tôi đã cố gắng để thay thế chủ bằng một chi nhánh khác. Tôi đã thực hiện một git log -1 origin / what_i_want_as_new_master để lấy $ new_master_commit cho bước 3. Sau khi đẩy (bước 4), các nhà phát triển khác sẽ kéo và nhận thông báo "chi nhánh của bạn đi trước chủ nhân bằng 295 cam kết." Để khắc phục điều này, tôi đã gửi một email cho họ biết mỗi lần chạy: git pull; kiểm tra git some_random_branch; chi nhánh git -D chủ; kéo git; git kiểm tra tổng thể; Về cơ bản, họ cần xóa chủ địa phương của họ và kéo phiên bản mới nếu không họ đang ở sai địa phương.
nairbv

Bạn có thể đã làm điều đó dễ dàng hơn nhiều: giả sử họ đã sẵn sàng masterthì họ chỉ có thể làm git fetch && git reset --hard origin/masterđể buộc địa phương của họ mastergiống như trên origin. Tôi đã ghi lại điều này, cũng như trường hợp phức tạp hơn khi bạn có các cam kết cục bộ trên đầu trang mastermà bạn muốn giữ, trong stackoverflow.com/q/4084868
Aristotle Pagaltzis

Đảm bảo rằng tệp cấu hình từ xa có "denyNonFastforwards = false" hoặc bạn sẽ nhận được "remote: error: từ chối các ref /
head

160

Với Git v1.7, tôi nghĩ điều này đã thay đổi một chút. Cập nhật tham chiếu theo dõi chi nhánh địa phương của bạn lên điều khiển từ xa mới rất dễ dàng.

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
Một cách khác --set-upstreamlà như sau: Một khi bạn đã đổi tên chi nhánh của mình tại địa phương và xóa nguồn gốc, chỉ cần thực hiện: git push -u --all
sáng suốt

4
Điều này sẽ không hoạt động với nhánh chủ, vì git sẽ không cho phép bạn xóa chủ từ xa.
Alexandre Neto

4
@AlexandreNeto Trong trường hợp này, bạn có thể thực thi dòng thứ 3 trước dòng thứ 2, đặt nhánh mặc định thành new_branchvà sau đó xóa điều khiển từ xa masterbằng dòng thứ 2.
Tristan Jahier 3/2/2015

3
Bước đơn giản đáng kinh ngạc. Đây là câu trả lời hay nhất cho câu hỏi
siddhusingh

13
Để xóa các chi nhánh từ xa git push origin --delete old_branchlà dễ đọc hơn một chút.
ThomasW

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

Bạn có thể phải tự chuyển sang new-branch-nametrước khi xóaold-branch-name


Có phần nào của giải pháp này xóa tên nhánh cũ cục bộ không, hay đó là một bài tập serparate?
GreenAsJade

4
Tôi nghĩ rằng cuối cùng phải được chạy git branch -d old-branch-nameđể xóa chi nhánh cũ địa phương.
Nabi KAZ

Bạn có thể đẩy các thay đổi chỉ bằng một lệnh : git push remote-name new-branch-name :old-branch-name.
sigod

Cách này sẽ không làm bạn phức tạp lịch sử git? Bởi vì bạn đang mở một chi nhánh mới thay vì chỉ đổi tên chi nhánh hiện tại.
androidevil

1
@androider Số Chi nhánh trong git là một tài liệu tham khảo đơn giản .
sigod

29

Có nhiều cách để đổi tên chi nhánh, nhưng tôi sẽ tập trung vào vấn đề lớn hơn: "làm thế nào để cho phép khách hàng chuyển tiếp nhanh và không phải gây rối với các chi nhánh của họ tại địa phương" .

Đầu tiên là một hình ảnh nhanh chóng: đổi tên chi nhánh chính và cho phép khách hàng chuyển tiếp nhanh

Đây là một cái gì đó thực sự dễ làm; nhưng đừng lạm dụng nó. Toàn bộ ý tưởng bản lề về hợp nhất cam kết; vì chúng cho phép chuyển tiếp nhanh và liên kết lịch sử của một chi nhánh với chi nhánh khác.

đổi tên chi nhánh:

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

tạo nhánh "chính" mới:

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

tạo một cam kết hợp nhất để có một lịch sử cha-con:

# 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

và Voila.

git push origin master

Điều này hoạt động vì tạo một mergecam kết cho phép chuyển tiếp nhanh chi nhánh đến một phiên bản mới.

sử dụng thông điệp cam kết hợp lý:

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
Cảm ơn! git merge -s ours master-oldlà phần quan trọng mà các câu trả lời khác bỏ lỡ. Ngoài ra, "dễ làm" không có nghĩa là "dễ hiểu, hoặc tìm hiểu" mà dường như là trường hợp của nhiều git, nhưng tôi lạc đề.
Martin Vidner

3
Tôi thích thực tế rằng không có sự xóa bỏ nào được đề cập và việc chuyển đổi cho những người làm việc với bản sao ngược dòng là "liền mạch". Cảm ơn bạn!
Piotrek

12

Tôi cho rằng bạn vẫn đang hỏi về tình huống tương tự như trong câu hỏi trước của bạn . Đó là, master-new sẽ không chứa master-old trong lịch sử của nó. * Nếu bạn gọi "master" mới, bạn sẽ có lịch sử viết lại. Không quan trọng làm thế nào bạn có được trạng thái trong đó chủ không phải là hậu duệ của vị trí chủ trước đó, đơn giản là nó ở trong trạng thái đó.

Những người dùng khác cố gắng kéo trong khi chủ không tồn tại sẽ chỉ đơn giản là các lần kéo của họ không thành công (không có ref như vậy trên điều khiển từ xa) và một khi nó tồn tại lại ở một nơi mới, các lần kéo của họ sẽ phải cố gắng hợp nhất chủ của họ với chủ từ xa mới, giống như khi bạn hợp nhất master-old và master-new trong kho lưu trữ của bạn. Với những gì bạn đang cố gắng thực hiện ở đây, việc hợp nhất sẽ có xung đột. (Nếu chúng được giải quyết và kết quả bị đẩy trở lại vào kho lưu trữ, bạn sẽ ở trạng thái thậm chí còn tồi tệ hơn - cả hai phiên bản của lịch sử ở đó.)

Để trả lời câu hỏi của bạn một cách đơn giản: bạn nên chấp nhận rằng đôi khi sẽ có những sai lầm trong lịch sử của bạn. Không sao đâu Nó xảy ra với tất cả mọi người. Có những cam kết được hoàn nguyên trong kho git.git. Điều quan trọng là một khi chúng ta xuất bản lịch sử, đó là điều ai cũng có thể tin tưởng.

* Nếu có, điều này sẽ tương đương với việc đẩy một số thay đổi lên bản gốc, và sau đó tạo một nhánh mới nơi nó từng tồn tại. Không vấn đề gì.


Phải, đó là cùng một vấn đề, chỉ là một ý tưởng làm thế nào để giải quyết nó. Nhưng ngay cả khi tôi không thực hiện việc đổi tên chi nhánh này, tôi vẫn thấy thú vị nếu có thể. Tôi nghĩ rằng các ref như "master" chỉ là các tham chiếu đến các cam kết cụ thể. Tôi thực sự không muốn thay đổi bất kỳ lịch sử. Tôi nghĩ rằng tôi sẽ chỉ điểm tham chiếu tổng thể đến một cái đầu khác. Điều này cũng có nghĩa, tôi không bao giờ có thể sử dụng tên chi nhánh một lần nữa nếu tôi đã từng sử dụng nó trước đây?
Albert

Thật vậy, các nhánh là refs - con trỏ để cam kết. Vấn đề là, chúng tôi hy vọng người đứng đầu một chi nhánh sẽ phát triển theo một cách cụ thể (cụ thể là luôn luôn chuyển tiếp nhanh). Từ quan điểm của người khác, di chuyển một chi nhánh trong repo công khai của bạn cũng giống như viết lại lịch sử của chi nhánh. Nó không còn trỏ đến một cam kết có chứa mọi thứ mà nó đã sử dụng.
Cascabel

8

Các câu trả lời được lựa chọn thất bại khi tôi thử nó. Nó ném một lỗi : refusing to delete the current branch: refs/heads/master. Tôi đoán tôi sẽ đăng những gì làm việc cho tôi:

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.

Mẹo nhỏ là kiểm tra chỗ dành sẵn ngay trước khi đẩy nó vào kho lưu trữ từ xa. Phần còn lại là tự giải thích, xóa nhánh chủ và đẩy nó vào kho lưu trữ từ xa sẽ hoạt động ngay bây giờ. Trích từ đây .


Nó sẽ thất bại trên git đẩy remote: master nếu điều này được kiểm tra ở phía xa - bạn sẽ thấy "remote: error:" là tiền tố trong các dòng nhật ký lỗi.
rafalmag

2

Tốt 2 xu của tôi. Làm thế nào về đăng nhập tại máy chủ, đi đến thư mục git và đổi tên chi nhánh trong kho lưu trữ trần. Điều này không có tất cả các vấn đề liên quan đến việc tải lại cùng một nhánh. Trên thực tế, 'khách hàng' sẽ tự động nhận ra tên đã sửa đổi và thay đổi tham chiếu từ xa của họ. Sau đó (hoặc trước đó), bạn cũng có thể sửa đổi tên địa phương của chi nhánh.


8
Tôi đã quên thông tin đăng nhập để đăng nhập vào máy chủ github. Bất cứ ai có thông tin xác thực ngoài kia :-P
Daniel Fisher lennybacon 23/07/13

1

Thế còn:

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

gây rối với theo dõi chi nhánh - người dùng có thể phải sửa chi nhánh của họ tại địa phương?
dnozay

1

Đây là cách đơn giản nhất và dễ đọc nhất mà tôi biết:

'Di chuyển' chi nhánh địa phương bằng cách sử dụng -m

git branch -m my_old_branch_name my_new_branch_name

Đẩy nhánh 'di chuyển' sang điều khiển từ xa, đặt 'ngược dòng' bằng cách sử dụng -u

git push origin -u my_new_branch_name

(thiết lập 'ngược dòng' về cơ bản 'kết nối' chi nhánh địa phương của bạn với điều khiển từ xa, để những thứ như tìm nạp, kéo và đẩy sẽ hoạt động)

Xóa chi nhánh cũ khỏi điều khiển từ xa

git push origin -D <old_name>

(chi nhánh địa phương của bạn đã biến mất, vì bạn đã 'di chuyển' nó trong bước 1)


1

OK , đổi tên một chi nhánh cả cục bộ và trên điều khiển từ xa khá dễ dàng! ...

Nếu bạn ở chi nhánh, bạn có thể dễ dàng thực hiện:

git branch -m <branch>

hoặc nếu không, bạn cần phải làm:

git branch -m <your_old_branch> <your_new_branch>

Sau đó, đẩy xóa đến điều khiển từ xa như thế này:

git push origin <your_old_branch>

Bây giờ bạn đã hoàn thành, nếu bạn gặp lỗi ngược dòng trong khi bạn cố gắng đẩy, chỉ cần làm:

git push --set-upstream origin <your_new_branch>

Tôi cũng tạo hình ảnh bên dưới để hiển thị các bước trong dòng lệnh thực sự, chỉ cần làm theo các bước và bạn sẽ ổn:

nhập mô tả hình ảnh ở đây


0

Bạn có thể làm như sau:

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

Nhưng lực đẩy là một ý tưởng tồi nếu người khác đang chia sẻ kho lưu trữ này. Lực đẩy sẽ khiến lịch sử sửa đổi của họ xung đột với cái mới.


0

Sau đây có thể được lưu vào tập lệnh shell để thực hiện công việc:

Ví dụ:

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

Xin lưu ý rằng ở đây tên gốc "mặc định" được mã hóa cứng, bạn có thể mở rộng tập lệnh để thực hiện nếu có thể định cấu hình!

Sau đó, tập lệnh này có thể được sử dụng với các bí danh bash, bí danh git hoặc trong, ví dụ, các hành động tùy chỉnh sourcetree.


-1

Tôi tin rằng chìa khóa là nhận ra rằng bạn đang thực hiện đổi tên kép : masterđến master-oldvà cũng master-newthành master.

Từ tất cả các câu trả lời khác tôi đã tổng hợp này:

doublerename master-new master master-old

nơi đầu tiên chúng ta phải xác định doublerenamehàm 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
}

Điều này tương tự như thay đổi lịch sử git rebaseở chỗ nội dung chi nhánh khá khác nhau, nhưng nó khác ở chỗ khách hàng vẫn có thể chuyển tiếp nhanh một cách an toàn git pull master.


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

2
Điều này dường như không hiệu quả với tôi, tôi nhận được: git update-ref trunk trunk2 fatal: trunk2: không phải là SHA1 hợp lệ
Gregg Lind
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.