มีวิธีใดบ้างที่จะทราบได้ว่าการคอมมิชชันใดที่มาจากการกำหนดค่าแฮชSHA-1 ?
คะแนนโบนัสหากคุณสามารถบอกวิธีการทำสิ่งนี้ให้สำเร็จโดยใช้ Ruby Grit
มีวิธีใดบ้างที่จะทราบได้ว่าการคอมมิชชันใดที่มาจากการกำหนดค่าแฮชSHA-1 ?
คะแนนโบนัสหากคุณสามารถบอกวิธีการทำสิ่งนี้ให้สำเร็จโดยใช้ Ruby Grit
คำตอบ:
แม้ว่า Dav จะถูกต้องว่าข้อมูลไม่ได้ถูกจัดเก็บโดยตรง แต่ก็ไม่ได้หมายความว่าคุณจะไม่สามารถหาข้อมูลได้ นี่คือบางสิ่งที่คุณสามารถทำได้
git branch -a --contains <commit>
นี้จะบอกคุณทุกสาขาที่มีความมุ่งมั่นในประวัติศาสตร์ของพวกเขา เห็นได้ชัดว่ามีประโยชน์น้อยกว่าถ้าคอมมิชชันถูกรวมเข้าด้วยกันแล้ว
หากคุณกำลังทำงานในพื้นที่เก็บข้อมูลที่สร้างการคอมมิทคุณสามารถค้นหา reflogs สำหรับบรรทัดการคอมมิทนั้น การ reflogs ที่มีอายุมากกว่า 90 วันนั้นจะถูกตัดโดย git-gc ดังนั้นหากการกระทำของคุณเก่าเกินไปคุณจะไม่พบมัน ที่กล่าวว่าคุณสามารถทำสิ่งนี้:
git reflog show --all | grep a871742
เพื่อค้นหากระทำ a871742 โปรดทราบว่าคุณต้องใช้ตัวย่อ 7 หลักแรกของการกระทำ ผลลัพธ์ควรเป็นดังนี้:
a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite
แสดงให้เห็นว่าการกระทำที่เกิดขึ้นกับสาขา "เสร็จสมบูรณ์" เอาต์พุตเริ่มต้นแสดงแฮชคอมมิชชันแบบย่อดังนั้นโปรดอย่าค้นหาแฮชแบบเต็มไม่เช่นนั้นคุณจะไม่พบสิ่งใด
git reflog show
จริงๆแล้วเป็นเพียงนามแฝงสำหรับgit log -g --abbrev-commit --pretty=oneline
ดังนั้นหากคุณต้องการที่จะเล่นซอฟท์แวร์ในรูปแบบเอาต์พุตเพื่อให้สิ่งต่าง ๆ พร้อมใช้งานสำหรับ grep นั่นคือจุดเริ่มต้นของคุณ!
หากคุณไม่ได้ทำงานในพื้นที่เก็บข้อมูลที่มีการคอมมิทการกระทำที่ดีที่สุดที่คุณสามารถทำได้ในกรณีนี้คือการตรวจสอบ reflogs และค้นหาว่าคอมมิทถูกแนะนำให้รู้จักกับพื้นที่เก็บข้อมูลของคุณเป็นครั้งแรก ด้วยโชคใด ๆ คุณดึงสาขาที่มันมุ่งมั่นที่จะ มันซับซ้อนกว่านี้เล็กน้อยเนื่องจากคุณไม่สามารถเดินทั้งแผนผังการส่งข้อมูลและ reflogs พร้อมกันได้ คุณต้องการแยกเอาต์พุต reflog ตรวจสอบแต่ละแฮชเพื่อดูว่ามีการคอมมิทที่ต้องการหรือไม่
สิ่งนี้ขึ้นอยู่กับเวิร์กโฟลว์ แต่ด้วยขั้นตอนการทำงานที่ดีเราจะทำคอมมิชชันในสาขาการพัฒนาซึ่งจะรวมเข้าด้วยกันคุณสามารถทำสิ่งนี้ได้:
git log --merges <commit>..
เพื่อดูการรวมการกระทำที่มีความมุ่งมั่นให้เป็นบรรพบุรุษ (ถ้าคอมมิชชันถูกรวมเพียงครั้งเดียวอันแรกควรจะเป็นการผสานคุณมิฉะนั้นคุณจะต้องตรวจสอบไม่กี่ฉันคิดว่า.) การคอมมิชชันการผสานข้อความควรประกอบด้วยชื่อสาขาที่ถูกผสาน
หากคุณต้องการที่จะเชื่อมั่นในการทำเช่นนี้คุณอาจต้องการใช้--no-ff
ตัวเลือกgit merge
เพื่อบังคับให้รวมการสร้างการกระทำแม้ในกรณีที่ส่งต่ออย่างรวดเร็ว (อย่ากระตือรือร้นมากเกินไปซึ่งอาจทำให้สับสนถ้าใช้มากเกินไป) คำตอบของ VonC สำหรับคำถามที่เกี่ยวข้องช่วยอธิบายรายละเอียดในหัวข้อนี้อย่างเป็นประโยชน์
git describe
เพียงพอแล้วสำหรับแท็ก (หมายเหตุประกอบ) สามารถดูได้อย่างมีนัยสำคัญยิ่งกว่าสาขา
--no-ff
ตัวเลือกเพื่อให้แน่ใจว่ามีการรวมการกระทำอยู่เสมอดังนั้นคุณจึงสามารถติดตามเส้นทางของการส่งที่กำหนดเมื่อรวมเข้ากับข้อมูลหลัก
-a
ตั้งค่าสถานะในคำสั่งแรกเช่นgit branch -a --contains <commit>
-r
การใช้งาน
merge --no-ff
เพื่อบันทึกชื่อสาขาเมื่อคุณรวม แต่มิฉะนั้นให้คิดว่าชื่อสาขาเป็นป้ายกำกับสั้น ๆ ชั่วคราวและยอมรับคำอธิบายเป็นชื่อถาวร "เราใช้ชื่อย่ออะไรในการพัฒนานี้" ไม่ควรเป็นคำถามที่สำคัญอย่างเช่น "สิ่งนี้กระทำไปอย่างไร"
คำสั่งง่ายๆนี้ใช้งานได้อย่างมีเสน่ห์:
git name-rev <SHA>
ตัวอย่างเช่น (โดยที่test-branchคือชื่อสาขา):
git name-rev 651ad3a
251ad3a remotes/origin/test-branch
แม้จะใช้งานได้กับสถานการณ์ที่ซับซ้อนเช่น:
origin/branchA/
/branchB
/commit<SHA1>
/commit<SHA2>
นี่คือgit name-rev commit<SHA2>
ผลตอบแทนที่branchB
git name-rev --name-only <SHA>
มีประโยชน์มากขึ้นสำหรับการได้รับชื่อสาขาเท่านั้น คำถามของฉัน ... มันสามารถส่งคืนมากกว่าหนึ่งสาขาในทุกสถานการณ์ได้หรือไม่?
อัปเดตธันวาคม 2556:
git-what-branch
(สคริปต์ Perl ดูด้านล่าง) ดูเหมือนจะไม่ได้รับการบำรุงรักษาอีกต่อไปgit-when-merged
เป็นทางเลือกที่เขียนด้วย Python ซึ่งทำงานได้ดีมากสำหรับฉัน
มันขึ้นอยู่กับ " ค้นหาผสานการกระทำซึ่งรวมถึงการกระทำที่เฉพาะเจาะจง "
git when-merged [OPTIONS] COMMIT [BRANCH...]
ค้นหาว่าเมื่อใดที่คอมมิชชันถูกรวมเข้าไปในสาขาหนึ่งสาขา
ค้นหาการคอมมิชชันที่นำCOMMIT
เข้ามาในสาขาที่ระบุโดยเฉพาะให้มองหาการคอมมิชชันที่เก่าที่สุดในประวัติผู้ปกครองคนแรกของ
BRANCH
ที่มีการCOMMIT
เป็นบรรพบุรุษ
คำตอบเดิมกันยายน 2010:
Sebastien Doucheเพิ่งtwitted (16 นาทีก่อนคำตอบ SO นี้):
git-what-branch : ค้นพบว่าสาขาใดที่คอมมิชชันเปิดอยู่หรือจะไปยังสาขาที่กำหนด
นี่คือสคริปต์ PerlจากSeth Robertsonที่น่าสนใจมาก:
สรุป
git-what-branch [--allref] [--all] [--topo-order | --date-order ]
[--quiet] [--reference-branch=branchname] [--reference=reference]
<commit-hash/tag>...
ภาพรวม
แจ้งให้เราทราบ (โดยค่าเริ่มต้น) เส้นทางที่เป็นสาเหตุที่เร็วที่สุดของการคอมมิทและการรวมเพื่อทำให้การคอมมิชชันที่ร้องขอนั้นเข้าสู่สาขาที่มีชื่อ หากกระทำได้โดยตรงในสาขาที่มีชื่อนั่นคือเส้นทางที่เร็วที่สุด
โดยเส้นทางสาเหตุที่เก่าที่สุดเราหมายถึงเส้นทางที่รวมเข้าไปในสาขาที่มีชื่อเร็วที่สุดโดยการกระทำเวลา (เว้นแต่
--topo-order
จะมีการระบุ)ประสิทธิภาพ
หากสาขาจำนวนมาก (เช่นหลายร้อย) มีการกระทำระบบอาจใช้เวลานาน (สำหรับการส่งข้อมูลแบบพิเศษในทรี Linux ใช้เวลา 8 วินาทีในการสำรวจสาขา แต่มีผู้สมัครมากกว่า 200 สาขา) เพื่อติดตามเส้นทาง แต่ละกระทำ
การเลือกวิชาที่--reference-branch --reference tag
จะสอบจะเร็วกว่าเป็นร้อยเท่า (ถ้าคุณมีสาขาที่สมัครหลายร้อยสาขา)ตัวอย่าง
# git-what-branch --all 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4
1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto master using the following minimal temporal path:
v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May 5 08:59:37 2005)
v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Tue May 3 18:27:24 2005)
v2.6.12-rc3-461-g84e48b6 is on master
v2.6.12-rc3-461-g84e48b6 is on v2.6.12-n
[...]
โปรแกรมนี้ไม่ได้คำนึงถึงผลกระทบของการหยิบความสนใจ แต่เพียงอย่างเดียวที่รวมเข้าด้วยกัน
git-what-branch
ดูเหมือนจะไม่ได้รับการบำรุงรักษาอีกต่อไป git-when-ผสานเป็นทางเลือกที่เขียนใน Python ที่ทำงานได้ดีสำหรับฉัน
ตัวอย่างเช่นในการค้นหาการc0118fa
กระทำนั้นมาจากredesign_interactions
:
* ccfd449 (HEAD -> develop) Require to return undef if no digits found
* 93dd5ff Merge pull request #4 from KES777/clean_api
|\
| * 39d82d1 Fix tc0118faests for debugging debugger internals
| * ed67179 Move &push_frame out of core
| * 2fd84b5 Do not lose info about call point
| * 3ab09a2 Improve debugger output: Show info about emitted events
| * a435005 Merge branch 'redesign_interactions' into clean_api
| |\
| | * a06cc29 Code comments
| | * d5d6266 Remove copy/paste code
| | * c0118fa Allow command to choose how continue interaction
| | * 19cb534 Emit &interact event
คุณควรเรียกใช้:
git log c0118fa..HEAD --ancestry-path --merges
และเลื่อนลงไปพบว่าที่ผ่านมาผสานกระทำ ซึ่งเป็น:
commit a435005445a6752dfe788b8d994e155b3cd9778f
Merge: 0953cac a06cc29
Author: Eugen Konkov
Date: Sat Oct 1 00:54:18 2016 +0300
Merge branch 'redesign_interactions' into clean_api
ปรับปรุง
หรือเพียงแค่คำสั่งเดียว:
git log c0118fa..HEAD --ancestry-path --merges --oneline --color | tail -n 1
git merge -m"Any String Here"
จะปิดบังข้อมูลสาขาและแหล่งข้อมูลเป้าหมาย
Merge: f6b70fa d58bdcb
ไม่มีการผสานมักจะมีข้อมูลเกี่ยวกับสาขาที่ผสาน: คุณสามารถตั้งชื่อการรวมการกระทำของคุณตามที่คุณต้องการ ฉันจะไม่มีปัญหา
git branch --contains <ref>
เป็นคำสั่ง "เครื่องเคลือบ" ที่ชัดเจนที่สุดในการทำเช่นนี้ หากคุณต้องการทำสิ่งที่คล้ายกับคำสั่ง "ประปา" เท่านั้น:
COMMIT=$(git rev-parse <ref>) # expands hash if needed
for BRANCH in $(git for-each-ref --format "%(refname)" refs/heads); do
if $(git rev-list $BRANCH | fgrep -q $COMMIT); then
echo $BRANCH
fi
done
(ทางแยกจากคำตอบ SO นี้ )
khichar.anil ครอบคลุมส่วนใหญ่ในคำตอบของเขา
ฉันแค่เพิ่มการตั้งค่าสถานะที่จะลบแท็กออกจากรายการชื่อการแก้ไข สิ่งนี้ทำให้เรา:
git name-rev --name-only --exclude=tags/* $SHA
ตัวเลือกของชายยากจนคือการใช้เครื่องมือtig
1เปิดHEAD
ค้นหาการมอบหมายแล้วตามสายตาจากการส่งข้อมูลสำรองจนกระทั่งเห็นการรวมการกระทำ ข้อความการผสานเริ่มต้นควรระบุว่าจะรวมสาขาใดเข้ากับที่ :)
1 Tig เป็นอินเตอร์เฟสโหมดข้อความที่อิง ncurses สำหรับ Git มันทำหน้าที่เป็นเบราว์เซอร์พื้นที่เก็บข้อมูล Git เป็นส่วนใหญ่ แต่มันยังสามารถช่วยในการเปลี่ยนสถานะการคอมมิทที่ระดับ chunk และทำหน้าที่เป็นเพจเจอร์สำหรับเอาต์พุตจากคำสั่ง Git ต่างๆ
เป็นการทดลองฉันทำเบ็ด post-commit ที่เก็บข้อมูลเกี่ยวกับสาขาที่เช็กเอาต์ปัจจุบันใน metadata ที่ส่งข้อมูล ฉันยังแก้ไข gitk เล็กน้อยเพื่อแสดงข้อมูลนั้น
คุณสามารถตรวจสอบได้ที่นี่: https://github.com/pajp/branch-info-commits
ฉันจัดการกับปัญหาเดียวกัน ( ไปป์ไลน์แบบหลายสาขาของJenkins ) - มีเพียงการส่งข้อมูลและพยายามค้นหาชื่อสาขาที่การกระทำนี้มาจากเดิม จะต้องใช้งานได้สำหรับสาขาระยะไกลไม่สามารถใช้สำเนาภายในเครื่องได้
นี่คือสิ่งที่ฉันทำงานกับ:
git rev-parse HEAD | xargs git name-rev
คุณสามารถเลือกที่จะเอาท์พุทเอาท์พุท:
git rev-parse HEAD | xargs git name-rev | cut -d' ' -f2 | sed 's/remotes\/origin\///g'
ฉันคิดว่าบางคนควรประสบปัญหาเดียวกันกับที่ไม่สามารถหาสาขาได้แม้ว่ามันจะมีอยู่ในสาขาเดียว
คุณควรดึงทั้งหมดก่อน:
git pull --all
จากนั้นทำการค้นหาสาขา:
git name-rev <SHA>
หรือ:
git branch --contains <SHA>
หาก OP พยายามที่จะตรวจสอบประวัติที่ถูก traversed โดยสาขาเมื่อมีการสร้างการกระทำเฉพาะ ("ค้นหาสิ่งที่การคอมมิชชันมาจากการกำหนดค่าแฮช SHA-1") โดยไม่มีการอ้างอิงใด ๆ บันทึกในฐานข้อมูลวัตถุ Gitที่แสดงสิ่งที่สาขาที่ถูกผูกไว้กับสิ่งที่กระทำประวัติศาสตร์
(ฉันโพสต์สิ่งนี้เป็นคำตอบในการตอบกลับความคิดเห็น)
หวังว่าสคริปต์นี้จะแสดงจุดของฉัน:
rm -rf /tmp/r1 /tmp/r2; mkdir /tmp/r1; cd /tmp/r1
git init; git config user.name n; git config user.email e@x.io
git commit -m"empty" --allow-empty; git branch -m b1; git branch b2
git checkout b1; touch f1; git add f1; git commit -m"Add f1"
git checkout b2; touch f2; git add f2; git commit -m"Add f2"
git merge -m"merge branches" b1; git checkout b1; git merge b2
git clone /tmp/r1 /tmp/r2; cd /tmp/r2; git fetch origin b2:b2
set -x;
cd /tmp/r1; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
cd /tmp/r2; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
เอาท์พุทแสดงให้เห็นถึงการขาดวิธีการใด ๆ ที่จะรู้ว่าการกระทำที่มี 'เพิ่ม f1' มาจากสาขา b1 หรือ b2 จากระยะไกลโคลน / tmp / r2
(บรรทัดสุดท้ายของผลลัพธ์ที่นี่)
+ cd /tmp/r1
+ git log --oneline --graph --decorate
* f0c707d (HEAD, b2, b1) merge branches
|\
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: merge b2: Fast-forward
086c9ce b1@{1}: commit: Add f1
18feb84 b1@{2}: Branch: renamed refs/heads/master to refs/heads/b1
18feb84 b1@{3}: commit (initial): empty
+ git reflog b2
f0c707d b2@{0}: merge b1: Merge made by the 'recursive' strategy.
80c10e5 b2@{1}: commit: Add f2
18feb84 b2@{2}: branch: Created from b1
+ cd /tmp/r2
+ git log --oneline --graph --decorate
* f0c707d (HEAD, origin/b2, origin/b1, origin/HEAD, b2, b1) merge branches
|\
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: clone: from /tmp/r1
+ git reflog b2
f0c707d b2@{0}: fetch origin b2:b2: storing head
git log 80c10e5..HEAD --ancestry-path --merges --oneline --color | tail -n 1
และgit log 086c9ce..HEAD --ancestry-path --merges --oneline --color | tail -n 1
คำสั่งสำหรับทั้งสองกรณีคืออะไร
$ git log HEAD^1..HEAD --ancestry-path --merges --oneline --color | tail -n 1
ซึ่งให้ผลตอบแทน376142d merge branches
และ$ git log HEAD^2..HEAD --ancestry-path --merges --oneline --color | tail -n 1
ผลตอบแทนใด376142d merge branches
- ซึ่งแสดงให้เห็นถึงการรวมสรุปการกระทำซึ่ง (ขณะที่ฉันกำลังอ้างสิทธิ์) ซึ่งสามารถเขียนทับได้เมื่อมีการสร้างการผสานอาจทำให้ประวัติสาขาของการรวมสับสน
ใช้ด้านล่างหากคุณสนใจเกี่ยวกับสถานะการออกจากเชลล์:
branch-current
- ชื่อสาขาปัจจุบันbranch-names
- ชื่อสาขาสะอาด (หนึ่งต่อบรรทัด)branch-name
- ตรวจสอบให้แน่ใจว่าส่งคืนสาขาเดียวเท่านั้น branch-names
ทั้งสองbranch-name
และbranch-names
ยอมรับการคอมมิชชันเป็นอาร์กิวเมนต์และเป็นค่าเริ่มต้น HEAD
หากไม่มีการกำหนด
branch-current = "symbolic-ref --short HEAD" # https://stackoverflow.com/a/19585361/5353461
branch-names = !"[ -z \"$1\" ] && git branch-current 2>/dev/null || git branch --format='%(refname:short)' --contains \"${1:-HEAD}\" #" # https://stackoverflow.com/a/19585361/5353461
branch-name = !"br=$(git branch-names \"$1\") && case \"$br\" in *$'\\n'*) printf \"Multiple branches:\\n%s\" \"$br\">&2; exit 1;; esac; echo \"$br\" #"
% git branch-name eae13ea
master
% echo $?
0
0
ค่าออกไปเป็น% git branch-name 4bc6188
Multiple branches:
attempt-extract
master%
% echo $?
1
1
ค่าออกไปเป็นเนื่องจากสถานะออกจึงสามารถสร้างได้อย่างปลอดภัย ตัวอย่างเช่นเพื่อให้รีโมตใช้สำหรับดึงข้อมูล:
remote-fetch = !"branch=$(git branch-name \"$1\") && git config branch.\"$branch\".remote || echo origin #"
วิธีค้นหาสาขาท้องถิ่น:
grep -lR YOUR_COMMIT .git/refs/heads | sed 's/.git\/refs\/heads\///g'
วิธีค้นหาสาขาระยะไกล:
grep -lR $commit .git/refs/remotes | sed 's/.git\/refs\/remotes\///g'
นอกเหนือจากการค้นหาต้นไม้ทั้งหมดจนกว่าคุณจะพบแฮชที่ตรงกันไม่ใช่