Đổi tên chi nhánh từ xa trong Git


407

Nếu có một kho lưu trữ mà tôi chỉ có git://quyền truy cập (và thường chỉ cần đẩy + kéo), có cách nào để đổi tên các nhánh trong kho lưu trữ đó giống như cách tôi sẽ làm tại địa phương git branch -mkhông?


48
Câu hỏi "trùng lặp" được liên kết yêu cầu đổi tên một nhánh "cả cục bộ và từ xa". Câu hỏi này, tuy nhiên, chỉ hỏi làm thế nào để đổi tên các chi nhánh từ xa, cho phép đơn giản hóa. Đây là những gì tôi làm để đổi tên một chi nhánh trên máy chủ mà không cần phải kiểm tra và / hoặc tạo một chi nhánh địa phương : git push origin origin/old_name:refs/heads/new_name && git push origin :old_name.
sschuberth

1
@sschuberth: bạn có thể đưa ra cả hai lệnh trong một lần. Và đây thực sự nên là câu trả lời cho câu hỏi này.
Joachim Breitner

2
@JoachimBreitner Bạn nói đúng, tôi đã thực hiện tối ưu hóa đó trong kịch bản này của tôi.
sschuberth

1
@sschuberth, bạn nên đăng bình luận của bạn dưới dạng câu trả lời, vì tôi thích nó hơn những người khác bên dưới.
phatmann

Câu trả lời:


480

Bạn chỉ cần tạo một nhánh cục bộ mới với tên mong muốn, đẩy nó vào điều khiển từ xa và sau đó xóa nhánh từ xa cũ:

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

Sau đó, để xem tên chi nhánh cũ, mỗi khách hàng của kho lưu trữ sẽ phải làm:

$ git fetch origin
$ git remote prune origin

LƯU Ý: Nếu chi nhánh cũ của bạn là chi nhánh chính của bạn, bạn nên thay đổi cài đặt chi nhánh chính của mình. Mặt khác, khi bạn chạy $ git push origin :old-branch-name, bạn sẽ gặp lỗi "xóa chi nhánh hiện tại bị cấm" .


8
Chà, nếu tên cũ và tên mới giống nhau, thì điều đó có nghĩa là bạn không cần đổi tên chi nhánh, vì vậy không có điểm nào để chạy lệnh ở vị trí đầu tiên ;-)
Sylvain Defresne

9
Chắc chắn rồi. Tôi chỉ có nghĩa là nếu bạn gọi nó theo cách tự động (như là một phần chức năng của một số tập lệnh khác) thì bạn cũng có thể không làm điều đó sai nếu bạn có thể tránh nó.
Bí ẩn Dan

9
Cách của Dan: sắp xếp lại các lệnh để chúng luôn hoạt động. Cách của Earth Engine: luôn nhớ kiểm tra hoặc bạn mất dữ liệu. Tôi biết cái nào tôi sẽ chọn.
Doradus

2
Người dùng chỉ có thể chạy: git fetch origin --prune(để tìm nạp các nhánh mới một cách hiệu quả và cũng loại bỏ các tham chiếu không còn trên điều khiển từ xa).
Cá heo

2
Có thể sử dụng -dhoặc --deletethay vì :trong các phiên bản mới hơn của git.
Zitrax

285

Nếu bạn thực sự chỉ muốn đổi tên các nhánh từ xa, mà không đổi tên bất kỳ nhánh cục bộ nào cùng một lúc , bạn có thể thực hiện việc này bằng một lệnh duy nhất:

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

Tôi đã viết kịch bản này ( git-rename-remote-Branch ) cung cấp một lối tắt tiện dụng để thực hiện các thao tác trên một cách dễ dàng.

Là một hàm 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
}

Để tích hợp nhận xét của @ ksrb : Điều này về cơ bản là hai lần đẩy trong một lệnh, đầu tiên git push <remote> <remote>/<old_name>:refs/heads/<new_name>là đẩy một nhánh từ xa mới dựa trên nhánh theo dõi từ xa cũ và sau đó git push <remote> :<old_name>xóa nhánh từ xa cũ.


10
Đối với những người muốn có bí danh của lệnh đó: rename = "! F () {git push origin origin / $ 1: refs / Heads / $ 2: $ 1;}; f" có thể được sử dụng như> git đổi tên <old_name> < new_name>
Jonathan Schmidt

33
Đối với những người tò mò về lệnh này thực sự có nghĩa là gì, về cơ bản, 2 lần đẩy git push <remote>/<old_name>:refs/heads/<new_name>có nghĩa là đẩy một điều khiển từ xa mới sử dụng điều khiển từ xa cũ làm src, sau đó git push [space]:<old_name> có nghĩa là xóa điều khiển từ xa cũ
ksrb

3
Tại sao bạn cần sử dụng refs/heads/name? Bạn có thể chỉ sử dụng nametrực tiếp, thực hiện lệnh đầu tiên git push <remote> <remote>/<old_name>:<new_name>?
vẽ Noakes

6
Không, bởi vì chi nhánh từ xa <new_name>chưa tồn tại. Nếu chi nhánh không tồn tại, Git yêu cầu bạn sử dụng tên đầy đủ vì nếu <new_name>không cũng có thể đề cập đến tên thẻ.
sschuberth

3
Chúng tôi sử dụng phương pháp này trong hệ thống xây dựng của chúng tôi. Sự cảnh báo duy nhất chúng ta gặp là nếu refs/heads/<new_name> đã tồn tại. Việc xóa vẫn thành công, dẫn đến <remote>/<old_name>chỉ bị xóa. Một số kiểm tra trước khi bàn tay có thể dễ dàng tránh điều này.
Apeiron

172

Kiểm tra đầu tiên đến chi nhánh mà bạn muốn đổi tên:

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

Để xóa một nhánh cũ khỏi remote:

git push origin :old_branch

12
Khi bạn đẩy nhánh được đổi tên (new_branch) sang remote (origin), bạn cũng nên đặt ngược dòng của nó để theo dõi nhánh với tên mới (ví dụ git push -u origin new_branch) nếu không nhánh được đổi tên (new_branch) sẽ tiếp tục theo dõi gốc / old_branch. Và một khi bạn xóa old_branch từ xa, new_branch vẫn sẽ theo dõi nguồn gốc / old_branch, mặc dù bây giờ chi nhánh đó đã biến mất.
Cá heo

@DolphinDream Tôi đã chỉnh sửa câu trả lời để bao gồm thay đổi ngược dòng hữu ích của bạn.
mVChr

10

Chắc chắn rồi. Chỉ cần đổi tên chi nhánh cục bộ, đẩy chi nhánh mới và xóa một chi nhánh cũ.

Vấn đề thực sự duy nhất là những người dùng khác của kho lưu trữ sẽ không được đổi tên các nhánh theo dõi cục bộ.


1
Vì vậy, khi cố gắng xóa master, tôi đã thử $ git clone ../src $ cd src $ git chi nhánh notmaster $ git checkout notmaster $ git Branch -d master $ git push ../src: master Nhưng nó phàn nàn: Điểm đến refspec không khớp với một ref hiện có trên remote cũng không bắt đầu bằng ref / và chúng tôi không thể đoán được tiền tố dựa trên ref nguồn. lỗi: thất bại trong việc đẩy một số ref đến '../alpha/' Điều khiển từ xa thực sự có một nhánh gọi là master
kdt

2

TL; DR

"Đổi tên" một chi nhánh từ xa thực sự là một quá trình gồm 2 bước (không nhất thiết phải ra lệnh):

  • xóa các nhánh từ xa cũ ( git push [space]:<old_name>như ksrb đã giải thích );
  • đẩy vào một nhánh từ xa mới (sự khác biệt giữa một vài lệnh trả lời bên dưới).

Xóa

Tôi sử dụng TortoiseGit và khi lần đầu tiên tôi cố gắng xóa chi nhánh thông qua dòng lệnh, tôi đã nhận được điều này:

$ git push origin :in
  • gây tử vong: 'origin' dường như không phải là kho lưu trữ git

  • gây tử vong: Không thể đọc từ kho lưu trữ từ xa.

Vui lòng đảm bảo rằng bạn có quyền truy cập chính xác và kho lưu trữ tồn tại.

Điều này có thể là do cuộc thi không có khóa riêng được tải (mà TortoiseGit tự động tải vào cuộc thi ). Hơn nữa, tôi nhận thấy rằng các lệnh TortoiseGit không có originref trong đó (ví dụ git.exe push --progress "my_project" interesting_local:interesting).

Tôi cũng đang sử dụng Bitbucket và, như những người quản lý git trực tuyến dựa trên web khác (GitHub, GitLab), tôi có thể xóa chi nhánh từ xa trực tiếp thông qua giao diện của họ (trang chi nhánh):

Xóa chi nhánh Bitbucket

Tuy nhiên, trong TortoiseGit, bạn cũng có thể xóa các nhánh từ xa thông qua Duyệt tài liệu tham khảo :

Duyệt menu Tham khảo

Bằng cách nhấp chuột phải vào một chi nhánh từ xa (danh sách từ xa), tùy chọn Xóa chi nhánh từ xa hiển thị:

Rùa xóa chi nhánh từ xa

Đẩy

Sau khi xóa nhánh từ xa cũ, tôi đã đẩy trực tiếp vào nhánh từ xa mới thông qua TortoiseGit chỉ bằng cách nhập tên mới vào trường Remote: của cửa sổ Push và nhánh này được tạo tự động và hiển thị trong Bitbucket .

Tuy nhiên, nếu bạn vẫn thích làm thủ công, một điểm chưa được đề cập trong chủ đề này là -u= --set-upstream.

Từ các git pushtài liệu , -uchỉ là một bí danh --set-upstream, vì vậy các lệnh trong câu trả lời của Sylvain ( -set-upstream new-branch)Shashank ( -u origin new_branch) là tương đương, vì các tham chiếu từ xa mặc định làorigin nếu không có tham chiếu nào khác được xác định trước đó:

  • git push origin -u new_branch= git push -u new_branch từ mô tả tài liệu :

    Nếu cấu hình bị thiếu, nó mặc định là origin.

Cuối cùng, tôi đã không nhập hoặc sử dụng bất kỳ lệnh nào được đề xuất bởi các câu trả lời khác ở đây, vì vậy có lẽ điều này có thể hữu ích cho những người khác trong tình huống tương tự.


vấn đề là điều khiển từ xa của bạn không được gọi origin. Bạn phải đặt tên cho điều khiển từ xa khi bạn nhận được nó từ việc chạy lệnh git remote. Git hoạt động với sshnhững gì ngụ ý rằng bạn đang sử dụng khóa chung + khóa riêng. Tôi giả định rằng Autoload Putty keysTortoiseGit chỉ tự động tải các khóa cần thiết để bạn có thể làm bất cứ điều gì với tham chiếu từ xa của bạn. Điều cuối cùng là đó git push -ukhông phải là bí danh để đẩy vào một nhánh từ xa, nó là bí danh để đẩy vào một nhánh từ xa được tạo cục bộ và tham chiếu từ xa của nó chưa có nhánh này .
juanecabellob

1
@juancab -ulà một bí danh --set-upstreamvà "nếu cấu hình bị thiếu, nó mặc định làorigin ". SylvainShashank sử dụng điều này để đẩy vào một nhánh từ xa mới được tạo . Các chủ chốt vấn đề có thể là do cuộc thi không có nó nạp khi tôi đã cố gắng git push origin :intrên vỏ. Vì vậy, tôi không hiểu downvote của bạn, tôi chỉ chỉ ra các chi tiết của tôi và không được giải quyết trong các câu trả lời khác, giải thích chúng và giải quyết chúng.
CPHPython

Bạn đang nêu những điều sai và phần lớn câu trả lời này không liên quan đến chính câu hỏi. Nếu bạn đang chỉ ra những gì đã làm cho bạn, tôi khuyến khích bạn giới hạn câu trả lời cho những gì nó đã làm và nếu bạn thực sự muốn đưa ra một lời giải thích, xin vui lòng thông báo cho mình tốt hơn. Btw: -ulà một bí danh cho --set-upstreamnhưng đó không phải là bí danh để đẩy vào một chi nhánh từ xa như bạn đã nói. Để đẩy vào một chi nhánh từ xa mà bạn cần git push <remote>, và nếu nó chưa ở trong điều khiển từ xa, bạn thêm vào git push -u <remote>. Do đó, -uđược sử dụng để tạo một tham chiếu của nhánh trong điều khiển từ xa.
juanecabellob

1
@juancab có lẽ những gì bạn cho là sai chủ yếu là cụm từ bí danh hoặc lựa chọn từ. Tôi cấu trúc lại câu trả lời của mình và đọc lại nó để đưa ra lời giải thích đầy đủ về (các) giải pháp mà tôi tìm thấy để đổi tên một chi nhánh từ xa.
CPHPython

Tôi sẽ viết lại nó hơn nữa. Nó có ý nghĩa hơn bây giờ, nhưng nó vẫn còn quá dài. Tôi sẽ nói cụ thể hơn về vấn đề này, tức là nói rằng đối với người dùng TortoiseGit, các giải pháp được đề xuất sẽ không hoạt động. Bạn đang kể một câu chuyện và điều đó gây nhầm lẫn và khiến người dùng tránh đọc. Tôi sẽ chỉnh sửa câu trả lời của bạn với một đề xuất.
juanecabellob

1

Tôi không biết tại sao nhưng câu trả lời của @Sylvain Defresne không phù hợp với tôi.

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

Tôi phải bỏ đặt ngược dòng và sau đó tôi có thể đặt lại luồng. Sau đây là cách tôi đã làm nó.

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

0

Tôi không biết điều này đúng hay sai, nhưng tôi đã đẩy "tên cũ" của chi nhánh sang "tên mới" của chi nhánh, sau đó xóa hoàn toàn chi nhánh cũ bằng hai dòng sau:

git push origin old_branch:new_branch
git push origin :old_branch

Theo như tôi có thể nói, đây chính xác là những gì tất cả các câu trả lời khác làm. Câu trả lời của bạn chỉ là ngắn gọn hơn.
Rõ ràng

-1

Bạn có thể tạo một nhánh mới dựa trên nhánh tên cũ. Chỉ cần như thế này, sau đó xóa chi nhánh cũ, hơn !!!nhập mô tả hình ảnh ở đây


Đó là GitHub, không phải Git. ;)
Bouncner

-4

Thêm vào các câu trả lời đã được đưa ra, đây là phiên bản đầu tiên kiểm tra xem nhánh mới đã tồn tại chưa (vì vậy bạn có thể sử dụng nó một cách an toàn trong tập lệnh)

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"

(kiểm tra là từ câu trả lời này )


Tôi đã sử dụng git show-ref --quiet --verify -- refs/heads/$new_namethay vì ls-remote | cut | sed | grep.
Andy
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.