จะตรวจสอบได้อย่างไรว่า remote branch มีอยู่ใน remote repository หรือไม่?


106

ฉันต้องทำการผสานทรีย่อยสำหรับสาขาเฉพาะหากมีอยู่ในที่เก็บระยะไกลที่กำหนด git branch -rปัญหาคือว่าพื้นที่เก็บข้อมูลระยะไกลไม่ได้ตรวจสอบออกในประเทศดังนั้นผมจึงไม่สามารถใช้ https://github.com/project-name/project-name.gitทั้งหมดที่ฉันต้องเป็นที่อยู่ห่างไกลบางอย่างเช่นนี้ มีวิธีการแสดงรายการสาขาระยะไกลโดยใช้ที่อยู่ระยะไกลหรือไม่? ฉันไม่พบสิ่งที่เป็นประโยชน์ :(

คำตอบ:


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

ในกรณีที่branch-nameพบคุณจะได้รับผลลัพธ์ต่อไปนี้:

b523c9000c4df1afbd8371324083fef218669108        refs/heads/branch-name

มิฉะนั้นจะไม่มีการส่งเอาต์พุต

ดังนั้นการวางท่อwcจะให้คุณ1หรือ0:

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

หรือคุณสามารถตั้งค่า--exit-codeแฟล็กgit ls-remoteที่จะส่งคืนรหัสออก2ในกรณีที่ไม่พบการอ้างอิงที่ตรงกัน นี่เป็นวิธีแก้ปัญหาที่เป็นสำนวนที่สุด $?ผลที่ได้สามารถตรวจสอบได้โดยตรงในการทดสอบเปลือกหรือโดยการตรวจสอบตัวแปรสถานะ

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

7
ฉันใช้git ls-remote --heads ${REPO} ${BRANCH} | grep ${BRANCH} >/dev/nullตามด้วยif [ "$?" == "1" ] ; then echo "Branch doesn't exist"; exit; fi
sibaz

1
ฉันกำลังมองหาคำตอบที่เป็นระเบียบและแม่นยำนี้มา 2-3 ชั่วโมงแล้ว
medik

/refs/heads/branch-nameคุณจำเป็นต้องระบุชื่อสาขาเป็น มิฉะนั้นสาขาจะกลับแม้เมื่อไม่มีfoo/branch-name branch-name
เลือน

ขอแสดงความยินดีกับป้ายทอง "คำตอบที่ดี" ของคุณ :)
jmort253

4
หมายเหตุ: หากคุณไม่ต้องการระบุ URL ของ repo คุณสามารถระบุชื่อรีโมต repo แทนได้เช่นgit ls-remote --heads origin branch-name
daveruin ทุกอย่าง

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

ฉันไม่รู้เกี่ยวกับ ls-remote ด้วย ขอบคุณ!
Keen

7
ฉันจำเป็นต้องทำการทดสอบในสคริปต์ทุบตีดังนั้นฉันจึงสนใจเฉพาะรหัสทางออกเท่านั้นดังนั้นฉันจึงทำสิ่งต่อไปนี้ในโคลนในเครื่อง: git ls-remote --exit-code . origin/branch-name &> /dev/nullจากนั้นใช้$?เป็นตัวดำเนินการทดสอบ
Darren Bishop

5
@Darren เพียงแค่ใช้คำสั่งโดยตรงในเงื่อนไขเช่นเดียวกับif git ls-remote ...; then ...; fiข้อผิดพลาดน้อยกว่าการตรวจสอบ$?(ซึ่งสามารถเปลี่ยนแปลงได้โดยการบันทึกคำสั่งกับดัก ฯลฯ )
Charles Duffy

ทำไม--heads?
Steve

@JohnLinux --headsแสดงสาขาเท่านั้น ใช้--tagsเพื่อแสดงรายการแท็กเท่านั้น
rymo

19

อีกวิธีหนึ่งที่คุณสามารถใช้ในโฟลเดอร์ปัจจุบันหากเป็นgit repoเพื่อเรียกใช้

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

2
ใช้เครื่องหมายคำพูดคู่:git branch -a | egrep "remotes/origin/${YOUR_BRANCH_NAME}$"
Ivan

3
สิ่งนี้ไม่ดีที่สุดเนื่องจากจะส่งคืนจริงแม้ว่าคุณจะจับคู่เพียงบางส่วนของชื่อสาขาที่มีอยู่ แต่ไม่ตรงกับสาขาเป้าหมายทุกประการ ดังนั้นจึงไม่สามารถใช้อย่างปลอดภัยในสคริปต์เพื่อทดสอบว่ามีสาขาอยู่หรือไม่ก่อนที่จะตรวจสอบ ขอบคุณสำหรับการแบ่งปันเนื่องจากฉันพบว่ามีประโยชน์ แก้ไขได้ดังนี้git branch -a | grep "\b${BRANCH}$"
EntangledLoops

2
git fetchจำเป็นหากใช้git branch -aดังนั้นการอ้างอิงรีโมททั้งหมดจะถูกดึงมาก่อน ใช้git ls-remoteอย่างอื่นตามที่ผู้อื่นชี้
hIpPy

git branch -a --list '<pattern>'ยังเป็นตัวเลือก ไปที่ grep หากคุณต้องการโค้ดส่งคืนสำหรับสคริปต์ของคุณ
LOAS

16

คุณยังสามารถใช้สิ่งนี้:

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

ส่งคืนค่าคอมมิตล่าสุดและมูลค่า $? เป็น 0 มิฉะนั้นจะส่งคืน "fatal: bad sha1 reference remotes / origin / <>" และค่า $? คือ 128


1
การดำเนินการนี้จะไม่ดึงสาขาจากระยะไกลก่อนการตรวจสอบดังนั้นคุณจึงไม่ได้รับสถานะรีโมตล่าสุด
siemanko

12

คำตอบทั้งหมดที่นี่เป็นคำตอบเฉพาะของ Linux ซึ่งไม่ได้ช่วยอะไรมากนักหากคุณอยู่ในสภาพแวดล้อมที่ไม่รองรับการดำเนินการเหล่านั้นเช่นพรอมต์คำสั่งของ Windows

โชคดีที่git ls-remoteยอมรับ--exit-codeอาร์กิวเมนต์ที่ส่งกลับ 0 หรือ 2 ขึ้นอยู่กับว่าสาขานั้นมีอยู่หรือไม่ตามลำดับ ดังนั้น:

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

จะคืนค่า 0 และ

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

จะกลับมา 2.

สำหรับ PowerShell คุณสามารถใช้ความหมายการจัดการความจริงในตัว:

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

ผลตอบแทน$trueในขณะที่:

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

$falseอัตราผลตอบแทน


11

คุณสามารถทำสิ่งนี้ได้ใน Bash terminal เพียงแค่แทนที่เสียงสะท้อนด้วยคำสั่งที่คุณต้องการดำเนินการ

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

หวังว่าจะช่วยได้


1
ฉันชอบมัน. คำตอบอื่น ๆ ยังมี ls-remote สิ่งที่ฉันชอบคือ "if"
Stony

11

จากนั้นไม่จำเป็นต้องส่งชื่อที่เก็บด้วยตนเองทุกครั้ง

git ls-remote origin <branch>

แทน

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

ตัวอย่าง:

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

หรือ

git ls-remote origin uat_21dec

ทั้งสองจะให้ผลลัพธ์เดียวกัน:

ป้อนคำอธิบายภาพที่นี่

เพิ่มเติมเกี่ยวกับ Origin : Git มีแนวคิดของ "รีโมต" ซึ่งเป็นเพียง URL ไปยังสำเนาอื่น ๆ ของที่เก็บของคุณ เมื่อคุณโคลนที่เก็บอื่น Git จะสร้างรีโมตชื่อ "ต้นทาง" โดยอัตโนมัติและชี้ไปที่มัน คุณสามารถดูข้อมูลเพิ่มเติมเกี่ยวกับรีโมตได้โดยพิมพ์ git remote show origin


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

ทำงานเกือบตลอดเวลา

แต่จะไม่ทำงานหากสาขาตรงกันบางส่วนดังต่อไปนี้

$ git branch -a
creative/dev
qa/dev

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

ใช้

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

หากคุณต้องการวิธีที่เชื่อถือได้

หากคุณต้องการใช้ในสคริปต์และไม่ต้องการถือว่าoriginเป็นรีโมตเริ่มต้น

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

ควรทำงาน.

โปรดทราบว่าgit branch -a | grep ...ไม่น่าเชื่อถือเนื่องจากอาจใช้เวลาสักครู่นับตั้งแต่fetchเรียกใช้ครั้งล่าสุด


สำหรับฉันนี่เป็นคำตอบที่ยอมรับรวมกับคำตอบจาก Amitesh (ชื่อระยะไกลแบบสั้น) รวมกับคำตอบจาก James Cache ( grep -x "$branch"เหมือนกันgrep ^"$branch"$) แม้ว่าในสคริปต์ฉันชอบสวิตช์แบบยาว: --line-regexp. wc -lนอกจากนี้ยังมีความจำเป็นที่จะไม่ทำ การใส่เอาต์พุตว่างใน Bash จะif [ -z ] ประเมินว่าเป็นจริงได้อย่างมีประสิทธิภาพดังนั้นจึงหมายความว่าไม่มีสาขา ซึ่งช่วยให้คุณประหยัดได้ไม่กี่มิลลิวินาที
Amedee Van Gasse

1

คุณสามารถเพิ่มที่เก็บที่คุณมีเป็นรีโมตโดยใช้git remote add something https://github.com/project-name/project-name.gitแล้วทำgit remote show somethingเพื่อรับข้อมูลทั้งหมดเกี่ยวกับรีโมต สิ่งนี้ต้องใช้การเชื่อมต่อเครือข่ายและมีประโยชน์สำหรับการใช้งานของมนุษย์

หรือทำgit fetch something. สิ่งนี้จะดึงข้อมูลสาขาทั้งหมดบนรีโมตที่เรียกsomethingและเก็บไว้ในที่เก็บในเครื่องของคุณ จากนั้นคุณสามารถรวมเข้ากับสาขาในพื้นที่ของคุณได้ตามต้องการ ฉันแนะนำเส้นทางนี้เนื่องจากในที่สุดคุณตัดสินใจว่าคุณต้องรวมนี่คือสิ่งที่คุณต้องทำ

OT: การที่คุณใช้ "เช็คเอาต์ในเครื่อง" แสดงว่าคุณกำลังเข้าใกล้สิ่งนี้จากมุมมองของระบบควบคุมเวอร์ชันส่วนกลาง นั่นมักจะเป็นทางตันเมื่อคุณจัดการกับคอมไพล์ โดยใช้คำเช่น "ชำระเงิน" เป็นต้นซึ่งแตกต่างจากระบบเก่า


ขอบคุณสำหรับคำอธิบาย ฉันยังไม่คุ้นเคยกับคอมไพล์และมันต้องใช้วิธีคิดที่แตกต่างออกไป
Keen

1

คุณสามารถลอง

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

ในที่นี้@{u}หมายถึง remote / upstream และ@{0}หมายถึง local HEAD ปัจจุบัน (ที่มี git เวอร์ชันใหม่กว่า@{0}สามารถย่อให้สั้นลงได้@) หากรีโมตไม่มีอยู่แสดงว่าเกิดข้อผิดพลาด

ด้วย git 2.16.2 (ฉันไม่แน่ใจว่าเวอร์ชันใดเป็นรุ่นแรกที่มีฟังก์ชันนี้ตัวอย่างเช่น git 1.7.1 ไม่มี) คุณสามารถทำได้

git checkout

หากมีสาขาระยะไกลจะมีเอาต์พุตบางอย่างเช่น

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

มิฉะนั้นจะไม่มีเอาต์พุต


1

จะส่งคืนสาขาทั้งหมด (ระยะไกลหรือภายใน) ที่มีแบบสอบถามในชื่อ

git branch --all | grep <query>


0

หากชื่อสาขาของคุณเฉพาะเจาะจงมากคุณอาจไม่จำเป็นต้องใช้ grep สำหรับการจับคู่ชื่อสาขาง่ายๆ:

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

ซึ่งใช้ได้กับ

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

เราใช้รหัสปัญหาเฉพาะเป็นชื่อสาขาและใช้งานได้ดี


0

ฉันเพิ่งลองสิ่งนี้:

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

สิ่งนี้จะส่งคืน 1 หากพบ branch "your-branch" และเป็น 0


0

ฉันกำลังรวมคำตอบด้านบนไว้ในสคริปต์:

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

สคริปต์นี้จะได้รับ 4 สาขาจากบิตบัคเก็ตระยะไกลและส่งไปยัง github ระยะไกลจากนั้นจะส่งแท็กทั้งหมดไปที่ github ฉันใช้สิ่งนี้ในงานของเจนกินส์นั่นคือเหตุผลที่คุณไม่เห็นสิ่งใดเลยgit fetchหรือgit pullที่ทำไปแล้วในการกำหนดค่าที่เก็บงานของเจนกินส์

ฉันมักจะชอบตัวเลือกแบบยาวในสคริปต์ ฉันสามารถรวมgit branchและgit checkoutใช้git checkout -Bไฟล์.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.