Làm thế nào để kiểm tra xem chi nhánh từ xa có tồn tại trên một kho lưu trữ từ xa nhất định hay không?


105

Tôi cần thực hiện hợp nhất cây con cho một nhánh cụ thể, nếu nó tồn tại trên một kho lưu trữ từ xa nhất định. Vấn đề là kho lưu trữ từ xa không được kiểm tra cục bộ, vì vậy tôi không thể sử dụng git branch -r. Tất cả những gì tôi có là một địa chỉ từ xa, đại loại như thế này https://github.com/project-name/project-name.git. Có cách nào để liệt kê các chi nhánh từ xa chỉ bằng một địa chỉ từ xa không? Tôi không thể tìm thấy bất cứ điều gì hữu ích :(

Câu trả lời:


124
$ git ls-remote --heads git@github.com:user/repo.git branch-name

Trong trường hợp branch-nameđược tìm thấy, bạn sẽ nhận được kết quả sau:

b523c9000c4df1afbd8371324083fef218669108        refs/heads/branch-name

Nếu không sẽ không có đầu ra nào được gửi.

Vì vậy, đường ống nó wcsẽ cung cấp cho bạn 1hoặc 0:

$ git ls-remote --heads git@github.com:user/repo.git branch-name | wc -l

Ngoài ra, bạn có thể đặt --exit-codecờ trên git ls-remoteđó sẽ trả về mã thoát 2trong trường hợp không tìm thấy giới thiệu phù hợp. Đây là giải pháp thành ngữ nhất. Kết quả có thể được kiểm tra trực tiếp trong thử nghiệm shell hoặc bằng cách kiểm tra biến trạng thái $?.

$ git ls-remote --exit-code --heads  git@github.com:user/repo.git branch-name

7
Tôi đã sử dụng git ls-remote --heads ${REPO} ${BRANCH} | grep ${BRANCH} >/dev/nulltheo sauif [ "$?" == "1" ] ; then echo "Branch doesn't exist"; exit; fi
sibaz

1
Tôi đã tìm kiếm câu trả lời gọn gàng và chính xác này trong vài giờ, tuyệt vời.
medik

Bạn cần chỉ định tên chi nhánh là /refs/heads/branch-name. Nếu không, nhánh foo/branch-namesẽ được trả lại ngay cả khi không có branch-name.
FuzzY

Xin chúc mừng huy hiệu vàng 'Câu trả lời tuyệt vời' của bạn. :)
jmort253

4
Lưu ý: Nếu bạn không muốn phải chỉ định URL repo, bạn có thể chỉ định repo từ xa tên thay vào đó, ví dụ như:git ls-remote --heads origin branch-name
daveruinseverything

50
git ls-remote --heads https://github.com/rails/rails.git
5b3f7563ae1b4a7160fda7fe34240d40c5777dcd    refs/heads/1-2-stable
81d828a14c82b882e31612431a56f830bdc1076f    refs/heads/2-0-stable
b5d759fd2848146f7ee7a4c1b1a4be39e2f1a2bc    refs/heads/2-1-stable
c6cb5a5ab00ac9e857e5b2757d2bce6a5ad14b32    refs/heads/2-2-stable
e0774e47302a907319ed974ccf59b8b54d32bbde    refs/heads/2-3-stable
13ad87971cc16ebc5c286b484821e2cb0fc3e3b1    refs/heads/3-0-stable
3df6c73f9edb3a99f0d51d827ef13a439f31743a    refs/heads/3-1-stable
f4db3d72ea564c77d5a689b850751ce510500585    refs/heads/compressor
c5a809e29e9213102351def7e791c3a8a67d7371    refs/heads/deps_refactor
821e15e5f2d9ef2aa43918a16cbd00f40c221e95    refs/heads/encoding
8f57bf207ff4f28fa8da4544ebc573007b65439d    refs/heads/master
c796d695909c8632b4074b7af69a1ef46c68289a    refs/heads/sass-cleanup
afd7140b66e7cb32e1be58d9e44489e6bcbde0dc    refs/heads/serializers

Tôi cũng không biết về ls-remote. Cảm ơn bạn!
Keen

7
Tôi cần phải làm một bài kiểm tra trong một kịch bản bash và do đó chỉ thực sự quan tâm đến mã lối ra, vì vậy tôi đã làm như sau trong một bản sao địa phương: git ls-remote --exit-code . origin/branch-name &> /dev/nullsau đó sử dụng $?như kiểm tra toán hạng
Darren ĐGM

5
@Darren, chỉ sử dụng lệnh trực tiếp trong một điều kiện, như vậy if git ls-remote ...; then ...; fi, ít bị lỗi hơn so với việc kiểm tra $?(có thể thay đổi bằng cách ghi các câu lệnh, bẫy, v.v.).
Charles Duffy

Tại sao --heads?
Steve

@JohnLinux chỉ --headsliệt kê các chi nhánh. chỉ sử dụng --tagsđể liệt kê các thẻ.
rymo

19

Một cách khác mà bạn có thể sử dụng trong thư mục hiện tại nếu đó là git repo để chạy

git branch -a | egrep 'remotes/origin/${YOUR_BRANCH_NAME}$'

2
Sử dụng dấu ngoặc kép:git branch -a | egrep "remotes/origin/${YOUR_BRANCH_NAME}$"
Ivan

3
Điều này không tối ưu vì nó sẽ trả về true ngay cả khi bạn chỉ khớp với một phần của tên nhánh hiện có, nhưng không khớp chính xác với nhánh mục tiêu. Vì vậy, điều này không thể được sử dụng một cách an toàn trong một tập lệnh để kiểm tra xem nhánh có tồn tại hay không trước khi kiểm tra nó. Dù sao cũng cảm ơn vì đã chia sẻ, vì tôi thấy nó hữu ích. Có thể được cố định như thế này:git branch -a | grep "\b${BRANCH}$"
EntangledLoops

2
git fetchlà bắt buộc nếu sử dụng git branch -anhư vậy tất cả các bản trích dẫn từ xa được tìm nạp trước. Sử dụng khác git ls-remotenhư được chỉ bởi những người khác.
hIpPy

git branch -a --list '<pattern>'cũng là một lựa chọn. Pipe to grep nếu bạn cần mã trả về cho tập lệnh của mình.
LOAS

17

Bạn cũng có thể sử dụng cái này:

git show-branch remotes/origin/<<remote-branch-name>>

trả về cam kết mới nhất và giá trị của $? là 0 nếu không thì trả về "death: bad sha1 reference remotes / origin / <>" và giá trị là $? là 128


Điều này sẽ không kéo các nhánh từ điều khiển từ xa trước khi kiểm tra, vì vậy bạn không nhận được trạng thái từ xa mới nhất.
siemanko

11

Sau đó, không cần phải chuyển tên kho lưu trữ theo cách thủ công mọi lúc.

git ls-remote origin <branch>

Thay vì

git ls-remote <full repo url> <branch>

Thí dụ :

git ls-remote git@bitbucket.org:landmarkgroupme/in-store-application.git  uat_21dec

HOẶC LÀ

git ls-remote origin uat_21dec

Cả hai sẽ cho đầu ra giống nhau:

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

Thông tin thêm về Nguồn gốc : Git có khái niệm "điều khiển từ xa", đơn giản là các URL đến các bản sao khác của kho lưu trữ của bạn. Khi bạn sao chép một kho lưu trữ khác, Git sẽ tự động tạo một điều khiển từ xa có tên là "origin" và trỏ đến nó. Bạn có thể xem thêm thông tin về điều khiển từ xa bằng cách nhập git remote show origin.


11

Tất cả các câu trả lời ở đây đều dành riêng cho hệ vỏ Linux, điều này không giúp ích nhiều nếu bạn đang ở trong một môi trường không hỗ trợ các loại hoạt động đó - ví dụ: dấu nhắc lệnh của Windows.

May mắn thay, git ls-remotechấp nhận một --exit-codeđối số trả về 0 hoặc 2 tùy thuộc vào việc nhánh có tồn tại hay không. Vì thế:

git ls-remote --exit-code --heads origin <branch-that-exists-in-origin>

sẽ trả về 0 và

git ls-remote --exit-code --heads origin <branch-that-only-exists-locally>

sẽ trả về 2.

Đối với PowerShell, bạn có thể chỉ cần sử dụng ngữ nghĩa xử lý truthiness được tích hợp sẵn:

if (git ls-remote --heads origin <branch-that-exists-in-origin>) { $true } else { $false }

sản lượng $true, trong khi:

if (git ls-remote --heads origin <branch-that-only-exists-locally>) { $true } else { $false }

lợi tức $false.


10

Bạn có thể làm điều gì đó như thế này trong thiết bị đầu cuối Bash. Chỉ cần thay thế tiếng vọng bằng các lệnh bạn muốn thực hiện.

if git ls-remote https://username:password@github.com/project-name/project-name.git | grep -sw "remote_branch_name" 2>&1>/dev/null; then echo "IT EXISTS..START MERGE" ; else echo "NOT FOUND" ; fi

Hy vọng nó giúp.


1
Tôi thích nó. những câu trả lời khác cũng có ls-remote, những gì tôi thích là "nếu".
Stony

6
$ git ls-remote --heads origin <branch> | wc -l

hoạt động hầu hết thời gian.

Nhưng sẽ không hoạt động nếu nhánh khớp một phần như bên dưới,

$ git branch -a
creative/dev
qa/dev

$ git ls-remote --heads origin dev | wc -l
2

Sử dụng

git ls-remote --heads origin <branch> | \
    cut -d$'\t' -f2 | \
    sed 's,refs/heads/,,' | \
    grep ^<branch>$ | wc -l

nếu bạn muốn một cách đáng tin cậy.

Nếu bạn muốn sử dụng trong script và không muốn coi originlà điều khiển từ xa mặc định thì

git ls-remote --heads $(git remote | head -1) "$branch" | \
    cut -d$'\t' -f2 | \
    sed 's,refs/heads/,,' | \
    grep ^"$branch"$ | wc -l

nên làm việc.

Lưu ý rằng điều đó git branch -a | grep ...không đáng tin cậy vì nó có thể mất một thời gian kể từ lần cuối cùng fetchđược chạy.


Đối với tôi, đây là câu trả lời được chấp nhận, kết hợp với câu trả lời từ Amitesh (tên viết tắt từ xa), kết hợp với câu trả lời từ James Cache ( grep -x "$branch"giống hệt với grep ^"$branch"$). Mặc dù trong kịch bản tôi thích dài hình thức chuyển mạch: --line-regexp. Ngoài ra, không cần phải làm wc -l. Đặt đầu ra trống trong Bash if [ -z ] đánh giá hiệu quả là đúng, vì vậy nó có nghĩa là nhánh không tồn tại. Điều đó giúp bạn tiết kiệm vài mili giây.
Amedee Van Gasse

1

Bạn có thể thêm kho lưu trữ bạn có làm điều khiển từ xa git remote add something https://github.com/project-name/project-name.gitvà sau đó thực hiện thao tác a git remote show somethingđể nhận tất cả thông tin về điều khiển từ xa. Điều này yêu cầu kết nối mạng và hữu ích cho con người.

Ngoài ra, hãy làm một git fetch something. Điều này sẽ tìm nạp tất cả các nhánh trên điều khiển từ xa được gọi somethingvà giữ chúng trong kho lưu trữ cục bộ của bạn. Sau đó, bạn có thể hợp nhất chúng vào chi nhánh địa phương của mình tùy ý. Tôi khuyên bạn nên sử dụng con đường này vì nếu cuối cùng bạn quyết định rằng bạn phải hợp nhất, đây là những gì bạn cần làm.

OT: Việc bạn sử dụng "đã thanh toán cục bộ" cho thấy rằng bạn đang tiếp cận điều này từ quan điểm hệ thống kiểm soát phiên bản tập trung. Đó thường là một ngõ cụt khi bạn xử lý git. Nó sử dụng các từ như "thanh toán", v.v. khác với cách các hệ thống cũ đã làm.


Cảm ơn vì những lời giải thích. Tôi vẫn chưa quen với git, và nó đòi hỏi cách suy nghĩ khác.
Keen

1

Bạn co thể thử

git diff --quiet @{u} @{0}

Ở đây @{u}đề cập đến điều khiển từ xa / ngược dòng và @{0}đề cập đến HEAD cục bộ hiện tại (với phiên bản git mới hơn, @{0}có thể được rút gọn là @). Nếu điều khiển từ xa không tồn tại, nó sẽ bị lỗi.

Với git 2.16.2 (tôi không chắc phiên bản nào là phiên bản đầu tiên có chức năng này, ví dụ: git 1.7.1 không có), bạn có thể

git checkout

Nếu một nhánh từ xa tồn tại, sẽ có một số đầu ra, như

Your branch is up to date with 'origin/master'

Nếu không thì không có đầu ra.


1

Sẽ trả về tất cả các nhánh (từ xa hoặc cục bộ) có chứa truy vấn trong tên.

git branch --all | grep <query>


0

Nếu tên chi nhánh của bạn rất cụ thể, bạn có thể không cần sử dụng grep để đối sánh tên chi nhánh đơn giản:

git ls-remote --heads $(git remote | head -1) "*${BRANCH_NAME}*" | \
    cut -d$'\t' -f2 | \
    sed 's,refs/heads/,,' | \
    wc -l

cái nào làm việc cho

BRANCH=master
BRANCH=mas
BRANCH=NonExistingBranch (returns 0)
BRANCH=ISSUE-123

Chúng tôi sử dụng id vấn đề duy nhất làm tên chi nhánh và nó hoạt động tốt.


0

Tôi vừa thử cái này:

git ls-remote --heads 2>/dev/null|awk -F 'refs/heads/' '{print $2}'|grep -x "your-branch"|wc -l

Điều này sẽ trả về 1 nếu nhánh "your-branch" được tìm thấy và 0 nếu không.


0

Tôi đang kết hợp một số câu trả lời ở trên trong một tập lệnh:

BRANCHES=(develop master 7.0 7.0-master)
ORIGIN=bitbucket
REMOTE=github

for BRANCH in "${BRANCHES[@]}"; do
  BRANCH=$(git ls-remote --heads "${ORIGIN}" "${BRANCH}" \
      | cut --delimiter=$'\t' --fields=2 \
      | sed 's,refs/heads/,,' \
      | grep --line-regexp "${BRANCH}")
  if [ -n "${BRANCH}" ]
  then
    git branch --force "${BRANCH}" "${ORIGIN}"/"${BRANCH}"
    git checkout "${BRANCH}"
    git push "${REMOTE}" "${BRANCH}"
  fi
done

git push github --tags

Tập lệnh này sẽ lấy 4 nhánh từ một bitbucket từ xa và đẩy chúng đến một github từ xa, sau đó sẽ đẩy tất cả các thẻ vào github. Tôi đang sử dụng điều này trong công việc Jenkins, đó là lý do tại sao bạn không thấy bất kỳ git fetchhoặc git pull, điều đó đã được thực hiện trong cấu hình kho công việc Jenkins.

Tôi thường thích các tùy chọn dạng dài trong tập lệnh. Tôi có thể đã kết hợp git branchgit checkoutbằng cách sử dụng git checkout -B.

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.