ให้รหัสกระทำวิธีการตรวจสอบว่าสาขาปัจจุบันมีการกระทำ?


156

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



10
ดูข้อเสนอที่ซ้ำกันสำหรับวิธีค้นหาสาขาทั้งหมดที่มีการคอมมิทที่ระบุ เพื่อดูว่าปัจจุบันสาขาประกอบด้วยกระทำCgit merge-base --is-ancestorใช้คำสั่ง "ประปา" สาขาปัจจุบันมีCถ้าCเป็นบรรพบุรุษของHEADดังนั้น:if git merge-base --is-ancestor $hash HEAD; then echo I contain commit $hash; else echo I do not contain commit $hash; fi
1717

1
สวัสดีโปรดส่งคำตอบนี้เป็นคำตอบเพื่อให้สามารถเลือกได้ว่าเป็นคำตอบที่ถูกต้อง =)
Ben

1
@Ben - ฉันเพิ่มมันเป็นคำตอบของชุมชน
Zitrax

1
@Remover: ในเชลล์สคริปต์ศูนย์เป็นจริงไม่ใช่ศูนย์เป็นเท็จ: ย้อนกลับของการประชุม C /bin/trueถูกนำมาใช้อย่างสร้างสรรค์exit 0และเป็น/bin/false exit 1(หอยโมเดิร์นได้สร้างขึ้นแล้วใน.)
torek

คำตอบ:


220

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

git log | grep <commit_id>

คุณดีกว่าที่จะใช้git branchโดยตรงเพื่อค้นหาสาขาทั้งหมดที่มีให้COMMIT_IDใช้

git branch --contains $COMMIT_ID

ขั้นตอนต่อไปคือการค้นหาสาขาปัจจุบันซึ่งสามารถทำได้ตั้งแต่การgit 1.8.1ใช้

git symbolic-ref --short HEAD

และรวมเข้าด้วยกันเป็น

git branch $(git symbolic-ref --short HEAD) --contains $COMMIT_ID

แต่คำสั่งด้านบนจะไม่ส่งคืนค่าจริงหรือเท็จและมีรุ่นที่สั้นกว่าซึ่งส่งคืนรหัสทางออก 0 หากการส่งมอบอยู่ในสาขาปัจจุบันหรือรหัสออก 1 ถ้าไม่ใช่

git merge-base --is-ancestor $COMMIT_ID HEAD

รหัสออกเป็นสิ่งที่ดี แต่ตามที่คุณต้องการสตริงtrueหรือfalseเป็นคำตอบคุณต้องเพิ่มอีกเล็กน้อยแล้วรวมกับifจากทุบตีคุณจะได้รับ

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi

9
ไม่ถูกต้อง grepอาจส่งผลบวกเท็จถ้าgit logกล่าวถึง SHA กระทำด้วยเหตุผลอื่น ๆ เช่นมันกล่าวถึงในการกระทำข้อความว่าเป็นผลมาจากพอร์ตจากสาขาอื่นที่
Adam Spires

1
แก้ไขแล้ว (หรือเพิ่มตัวเลือกอื่นแทน)
JiriS

3
โปรดดูความคิดเห็นเกี่ยวกับคำถามซึ่งใช้ชุดเครื่องมือ git ในตัว stackoverflow.com/questions/43535132/…
Ben

2
ผมชอบตัวเลือกแรก แต่กฎออกมาคัดค้านของอดัม, ฉันจะเพิ่มตัวเลือกในการที่จะ--format=format:%H git log
PJSCopeland

71

รับรายการของสาขาที่มีการกระทำที่เฉพาะเจาะจง

# get all the branches where the commit exists
$ git branch --contains <commit-id>

ตรวจสอบว่าสาขามีความมุ่งมั่นที่เฉพาะเจาะจง

# output the branch-name if the commit exists in that branch
$ git branch --contains <commit-id> | grep <branch-name>

ค้นหาสาขา (พูดfeature) กับการจับคู่ที่แน่นอน

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

เช่นถ้าคุณมี 3 สาขาท้องถิ่นที่เรียกว่าfeature, feature1, feature2แล้ว

$ git branch --contains <commit-id> | grep 'feature'

# output
feature
feature1
feature2

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

# output
feature     

นอกจากนี้คุณยังสามารถค้นหาทั้งสองlocalและremoteสาขา (ใช้-a) หรือเฉพาะในremoteสาขา (ใช้-r)

# search in both 'local' & 'remote' branches  
$ git branch -a --contains <commit-id> | grep -E '(^|\s)feature$'

# search in 'remote' branches  
$ git branch -r --contains <commit-id> | grep -E '(^|\s)feature$'

1
grepที่นี่นอกจากนี้ยังอาจส่งผลบวกเท็จถ้ามีสาขาอื่น ๆ ที่มีการกระทำที่มีชื่อยังมี<branch-name>เป็นสตริงย่อย
Adam Spires

1
ใช่ @ AdamSpiers อัปเดตคำตอบด้วยการจับคู่ชื่อสาขาอย่างแม่นยำโดยgrep -E '(^|\s)branchname$'
Sajib Khan

1
ตามความคิดเห็นเกี่ยวกับคำถามที่เกี่ยวข้องจะมีประโยชน์ในการเพิ่มตัวเลือก-r("ระยะไกล") หรือ-a("ทั้งหมด") git branchเพื่อค้นหาสาขาที่อาจไม่สามารถจำลองแบบได้ในการทำสำเนาโลคอลท้องถิ่น
sxc731

สิ่งนี้ไม่ได้ผลสำหรับฉันฉันต้องการ git branch --all --contains <commit-id>
Arthur Tacca

7

แยกความคิดเห็นโดย @torek เป็นคำตอบ:

ดูข้อเสนอที่ซ้ำกันสำหรับวิธีค้นหาสาขาทั้งหมดที่มีการคอมมิทที่ระบุ

เพื่อดูว่าปัจจุบันสาขาประกอบด้วยกระทำ C, git merge-base --is-ancestorใช้คำสั่ง สาขาปัจจุบันมี C ถ้า C เป็นบรรพบุรุษของ HEAD ดังนั้น:

if git merge-base --is-ancestor $hash HEAD; then
    echo I contain commit $hash
else
    echo I do not contain commit $hash
fi

(หมายเหตุด้าน: ในเชลล์สคริปต์คำสั่งที่ออกจากศูนย์คือ "จริง" ในขณะที่คำสั่งที่ออกจากศูนย์ไม่ใช่ "เท็จ")


4

ในการแสดงรายการสาขาท้องถิ่นที่มีคอมมิท:

git branch --contains <commit-id>

และเพื่อแสดงรายการทุกสาขารวมถึงรีโมตเท่านั้นที่มี commit:

git branch -a --contains <commit-id>

ในทำนองเดียวกันเพื่อตรวจสอบว่ากระทำอยู่ในสาขาเฉพาะ:

git log <branch> | grep <commit_id>

และถ้าสาขาไม่มีชื่อสาขานำหน้าด้วย origin/


โหวตให้กับคำพูด-aของ ขอบคุณสำหรับคำแนะนำ!
Thorkil Værge

3

ใช่อีกทางเลือกหนึ่ง:

git rev-list <branch name> | grep `git rev-parse <commit>`

มันใช้งานได้ดีที่สุดสำหรับฉันเพราะมันจะทำงานบนกิ่งไม้ที่อยู่ในพื้นที่ห่างไกลที่เก็บไว้ในเครื่องเช่นremotes/origin/masterซึ่งgit branch --containsจะไม่ทำงาน

นี่ครอบคลุมมากกว่าคำถามของ OP เกี่ยวกับ "สาขาปัจจุบัน" แต่ฉันพบว่ามันโง่ที่จะถามรุ่น "สาขาใด ๆ " ของคำถามนี้ดังนั้นฉันตัดสินใจที่จะโพสต์ที่นี่ต่อไป


1
git branch --contains <commit-id> --points-at <target branch name>

มันจะส่งคืนชื่อสาขาเป้าหมายหากรหัสการยอมรับมีอยู่ในสาขานั้น มิฉะนั้นคำสั่งจะล้มเหลว


ไม่ ...error: malformed object name 'branch-name'
bbodenmiller

1
คุณอาจได้รับข้อผิดพลาดนั้นใน 2 กรณี 1. เมื่อ <branch name> ที่ระบุไม่มีการกำหนด <commit id> ที่ได้รับ 2. การเช็คเอาต์ <branch name> ไม่ใช่ <branch name>
DreamUth

0

เนื่องจากคำถามนี้มีคำตอบสคริปต์ที่ดีฉันจึงเพิ่มรายการโปรดของฉัน

อันนี้จะแสดงให้คุณเห็นสำหรับการ$nกระทำครั้งสุดท้าย$brที่สาขามีแต่ละ:

br=mybranch
n=10
git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'

อันนี้คล้ายกัน แต่จะเหมือนกันสำหรับรายการสาขา:

br="mybranch yourbranch herbranch"
n=4
for br in $brs; do git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'; done
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.