ฉันเริ่มเล่นกับ Git และเจอกับคำว่า "upstream" และ "downstream" ฉันเคยเห็นสิ่งเหล่านี้มาก่อน แต่ไม่เคยเข้าใจพวกเขาอย่างเต็มที่ คำเหล่านี้มีความหมายอย่างไรในบริบทของ SCM ( เครื่องมือการจัดการการกำหนดค่าซอฟต์แวร์ ) และซอร์สโค้ด
ฉันเริ่มเล่นกับ Git และเจอกับคำว่า "upstream" และ "downstream" ฉันเคยเห็นสิ่งเหล่านี้มาก่อน แต่ไม่เคยเข้าใจพวกเขาอย่างเต็มที่ คำเหล่านี้มีความหมายอย่างไรในบริบทของ SCM ( เครื่องมือการจัดการการกำหนดค่าซอฟต์แวร์ ) และซอร์สโค้ด
คำตอบ:
ในแง่ของการควบคุมแหล่งที่มาคุณกำลัง " ดาวน์สตรีม " เมื่อคุณคัดลอก (โคลน, เช็คเอาต์และอื่น ๆ ) จากที่เก็บ ข้อมูลไหล "ลง" ถึงคุณ
เมื่อคุณทำการเปลี่ยนแปลงคุณมักจะต้องการส่งกลับ " อัปสตรีม " เพื่อให้พวกเขาลงในพื้นที่เก็บข้อมูลนั้นเพื่อให้ทุกคนที่ดึงจากแหล่งเดียวกันนั้นทำงานกับการเปลี่ยนแปลงเดียวกันทั้งหมด นี่เป็นปัญหาทางสังคมส่วนใหญ่ว่าทุกคนสามารถประสานงานของพวกเขาได้มากกว่าความต้องการด้านเทคนิคของการควบคุมแหล่งที่มา คุณต้องการรับการเปลี่ยนแปลงในโครงการหลักดังนั้นคุณจึงไม่ได้ติดตามสายการพัฒนาที่หลากหลาย
บางครั้งคุณจะอ่านเกี่ยวกับแพ็คเกจหรือผู้จัดการประจำ (คนไม่ใช่เครื่องมือ) พูดคุยเกี่ยวกับการส่งการเปลี่ยนแปลงเพื่อ "อัปสตรีม" นั่นหมายถึงพวกเขาต้องปรับแหล่งต้นฉบับเพื่อให้สามารถสร้างแพ็คเกจสำหรับระบบของพวกเขาได้ พวกเขาไม่ต้องการทำการเปลี่ยนแปลงเหล่านั้นดังนั้นหากพวกเขาส่ง "อัปสตรีม" ไปยังแหล่งดั้งเดิมพวกเขาไม่ควรต้องจัดการกับปัญหาเดียวกันในรีลีสถัดไป
-u
เช่นgit push --set-upstream origin master
ถ้ามันไม่ได้เป็นความต้องการทางเทคนิค ? เราสามารถpush -u origin
หรือไม่ใช้push origin
ดังนั้นจึงเป็นความต้องการด้านเทคโนโลยี แต่ความแตกต่างคืออะไร
เมื่อคุณอ่านในgit tag
man page :
สิ่งสำคัญอย่างหนึ่งของ git คือการแจกจ่ายและการกระจายส่วนใหญ่หมายความว่าไม่มี "upstream" หรือ "downstream" ในระบบ
ที่เพียงแค่หมายความว่าไม่มีแน่นอน repo ต้นน้ำหรือปลายน้ำ repo
แนวคิดเหล่านั้นสัมพันธ์กันเสมอระหว่างสอง repos และขึ้นอยู่กับการไหลของข้อมูล:
หาก "yourRepo" ได้ประกาศว่า "otherRepo" เป็นรีโมตให้ทำดังนี้:
หมายเหตุ "จาก" และ "สำหรับ": คุณไม่ได้เป็นเพียง "ดาวน์สตรีม" แต่เป็น "ดาวน์สตรีมจาก / สำหรับ " ดังนั้นจึงเป็นแง่มุมที่สัมพันธ์กัน
การบิด DVCS (ระบบการควบคุมเวอร์ชันแจกจ่าย) คือ: คุณไม่รู้ว่าจริงๆแล้วคือ downstream ข้าง repo ของคุณเองเมื่อเทียบกับ repos ระยะไกลที่คุณประกาศ
โดยทั่วไป:
ในแง่ของ " การไหลของข้อมูล " repo ของคุณอยู่ที่ด้านล่าง ("downstream") ของการไหลที่มาจาก repos upstream ("pull from") และกลับไปที่ repos upstream (เดียวกันหรืออื่น ๆ ) ("push to" )
คุณสามารถดูภาพประกอบในgit-rebase
man pageพร้อมกับย่อหน้า "การกู้คืนจากการอัปเดตจาก UPSTREAM":
หมายความว่าคุณกำลังดึงจาก repo "อัปสตรีม" ที่รีบูตเกิดขึ้นและคุณ (repo "ดาวน์สตรีม") ติดอยู่กับผลลัพธ์ (ซ้ำจำนวนมากคอมมิชชันเนื่องจากสาขาที่รีบูท upstream up สร้างคอมมิชชันของสาขาเดียวกันกับคุณ มีในท้องถิ่น)
นั่นเป็นสิ่งที่ไม่ดีเพราะสำหรับ repo "upstream" หนึ่งอาจมีrepos ดาวน์สตรีมจำนวนมาก (เช่น repos ที่ดึงจาก upstream ด้วย repased branch) พวกเขาทั้งหมดมีศักยภาพที่จะจัดการกับคอมมิชชันที่ซ้ำกัน
อีกครั้งเมื่อมีการเปรียบเทียบ "การไหลของข้อมูล" ใน DVCS คำสั่งที่ไม่ถูกต้องคำสั่งเดียว "อัปสตรีม" สามารถมี " ผลกระเพื่อม " ได้
หมายเหตุ: สิ่งนี้ไม่ จำกัด เฉพาะข้อมูล
นอกจากนี้ยังใช้กับพารามิเตอร์เช่นคำสั่ง git (เช่นคำสั่ง "Porcelain") มักจะเรียกคำสั่ง git อื่น ๆ ภายใน (คำสั่ง "plumbing") ดูrev-parse
หน้าคน :
คำสั่งคอมไพล์ porcelainish หลายคนใช้ส่วนผสมของธง (เช่นพารามิเตอร์ที่ขึ้นต้นด้วยเส้นประ '
-
') และพารามิเตอร์หมายสำหรับอ้างอิงgit rev-list
คำสั่งพวกเขาใช้ภายในและธงและพารามิเตอร์สำหรับคำสั่งอื่น ๆgit rev-list
ที่พวกเขาใช้น้ำจาก คำสั่งนี้ใช้เพื่อแยกความแตกต่างระหว่างพวกเขา
คำต้นน้ำยังมีความหมายที่ชัดเจนบางอย่างที่มากับชุดเครื่องมือ GIT โดยเฉพาะอย่างยิ่งที่เกี่ยวข้องกับการติดตาม
ตัวอย่างเช่น :
$git rev-list --count --left-right "@{upstream}"...HEAD >4 12
จะพิมพ์ (มูลค่าแคชสุดท้ายของ) จำนวนการกระทำที่อยู่เบื้องหลัง (ซ้าย) และข้างหน้า (ขวา) ของสาขาการทำงานปัจจุบันของคุณเทียบกับ ( ถ้ามี ) ในปัจจุบันการติดตามสาขาระยะไกลสำหรับสาขาท้องถิ่นนี้ มันจะพิมพ์ข้อความผิดพลาดเป็นอย่างอื่น:
>error: No upstream branch found for ''
origin
(repo ที่แยกจากกันบน gitHub) และupstream
(repo บน GitHub คุณแยกจาก) เหล่านี้เป็นเพียงชื่อที่ใช้แทนกันได้เฉพาะ 'git @ ... ' url เท่านั้นที่ระบุได้การ
.git/config
อ่านของคุณ:[remote "origin"] fetch = +refs/heads/*:refs/remotes/origin/* url = git@github.com:myusername/reponame.git [remote "upstream"] fetch = +refs/heads/*:refs/remotes/upstream/* url = git@github.com:authorname/reponame.git
มันคือ'สาขา' (ถ้ามี) ใน'รีโมตที่กล่าวว่า'ซึ่งกำลังติดตาม'สาขาปัจจุบัน'ใน'คลังเก็บในพื้นที่ของคุณ'
เป็นสาขาที่คุณดึง / ดึงจากเมื่อใดก็ตามที่คุณออก
git fetch
/git pull
โดยไม่มีข้อโต้แย้ง
สมมติว่าต้องการตั้งค่าที่มาสาขาย่อย / ต้นแบบจากระยะไกลให้เป็นสาขาการติดตามสำหรับสาขาต้นแบบท้องถิ่นที่คุณเช็คเอาต์ เพียงแค่ปัญหา:
$ git branch --set-upstream master origin/master > Branch master set up to track remote branch master from origin.
สิ่งนี้จะเพิ่ม 2 พารามิเตอร์ใน
.git/config
:[branch "master"] remote = origin merge = refs/heads/master
ตอนนี้ลอง (ให้ระยะไกล 'upstream' มีสาขา 'dev')
$ git branch --set-upstream master upstream/dev > Branch master set up to track remote branch dev from upstream.
.git/config
ตอนนี้อ่าน:[branch "master"] remote = upstream merge = refs/heads/dev
-u --set-upstream
สำหรับทุกสาขาที่เป็นข้อมูลล่าสุดหรือถูกผลักสำเร็จให้เพิ่มการอ้างอิงupstream (การติดตาม) ที่ใช้โดยคำสั่ง git-pull (1) และอาร์กิวเมนต์อื่นที่ไม่ใช้อาร์กิวเมนต์ สำหรับข้อมูลเพิ่มเติมดู
branch.<name>.merge
ใน git-config (1)branch.<name>.merge
กำหนดร่วมกับ
branch.<name>.remote
ที่ต้นน้ำสาขาสาขาที่กำหนด มันบอก git fetch / git pull / git rebase ว่าจะรวมสาขาใดบ้างและสามารถส่งผลต่อ git push ได้ (ดู push.default) \ (... )branch.<name>.remote
เมื่ออยู่ใน branch <name> มันจะบอก git fetch และ git push ซึ่งรีโมตที่จะดึงข้อมูลจาก / push to มันเป็นค่าเริ่มต้นที่จะกำเนิดหากไม่มีการกำหนดค่าระยะไกล ต้นกำเนิดยังใช้ถ้าคุณไม่ได้อยู่ในสาขาใด ๆ
ลองดูที่git-config(1)
หน้าคู่มือ
git config --global push.default upstream git config --global push.default tracking (deprecated)
นี่คือเพื่อป้องกันการกดไปยังกิ่งที่ไม่ได้ตั้งใจซึ่งคุณยังไม่พร้อมที่จะผลัก
git branch --help
ณ วันที่ 2018:As this option had confusing syntax, it is no longer supported. Please use --track or --set-upstream-to instead.
นั่นเป็นคำศัพท์ที่ไม่เป็นทางการ
เท่าที่ Git เกี่ยวข้องพื้นที่เก็บข้อมูลอื่น ๆ ทั้งหมดก็แค่รีโมตเท่านั้น
โดยทั่วไปการอัปสตรีมเป็นที่ที่คุณลอกแบบ (ต้นกำเนิด) ดาวน์สตรีมคือโครงการใด ๆ ที่รวมงานของคุณเข้ากับงานอื่น
ข้อกำหนดไม่ได้ จำกัด อยู่ที่ที่เก็บ Git
ตัวอย่างเช่น Ubuntu เป็นอนุพันธ์ของเดเบียนดังนั้น Debian จึงเป็นอัพสตรีมสำหรับ Ubuntu
นั่นคืออนิจจาการใช้ "ต้นน้ำ" อีกครั้งที่คำตอบอื่น ๆ ที่นี่ไม่ได้รับคือกล่าวถึงความสัมพันธ์พ่อแม่และลูกของคอมมิชชันภายใน repo Scott Chacon ในหนังสือ Pro Gitโดยเฉพาะอย่างยิ่งมีแนวโน้มนี้และผลลัพธ์จะโชคร้าย อย่าเลียนแบบวิธีการพูดนี้
ตัวอย่างเช่นเขาพูดถึงการรวมที่เกิดขึ้นอย่างรวดเร็วว่าสิ่งนี้เกิดขึ้นเพราะ
คอมมิชชันที่ชี้ไปตามสาขาที่คุณรวมเข้าไปนั้นเป็นข้อมูลต้นน้ำโดยตรงของการส่งข้อมูลที่คุณกำลังดำเนินอยู่
เขาต้องการที่จะบอกว่าการกระทำ B เป็นลูกคนเดียวของลูกคนเดียวของ ... ของลูกคนเดียวของการกระทำดังนั้นเพื่อรวม B เป็น A มันก็เพียงพอที่จะย้ายผู้อ้างอิงไปยังจุดที่จะกระทำ B. ทำไมทิศทางนี้ ควรเรียกว่า "อัปสตรีม" แทนที่จะเป็น "ดาวน์สตรีม" หรือทำไมรูปทรงเรขาคณิตของกราฟเส้นตรงที่บริสุทธิ์เช่นนี้ควรจะอธิบายว่า "อัปสตรีมโดยตรง" นั้นไม่มีความชัดเจนอย่างสมบูรณ์และอาจไม่มีเหตุผล (หน้าคนgit-merge
ที่ทำงานได้ดีกว่าการอธิบายความสัมพันธ์นี้เมื่อกล่าวว่า "หัวหน้าสาขาปัจจุบันเป็นบรรพบุรุษของการกระทำที่มีชื่อ" นั่นคือสิ่งที่ Chacon ควรพูด)
อันที่จริง Chacon ตัวเองดูเหมือนจะใช้ "ดาวน์สตรีม" ในภายหลังเพื่อหมายถึงสิ่งเดียวกันอย่างแน่นอนเมื่อเขาพูดถึงการเขียนใหม่เด็กทุกคนกระทำการกระทำที่ถูกลบ:
คุณต้องเขียนดาวน์สตรีมทั้งหมดที่กระทำต่อเนื่องจาก 6df76 เพื่อลบไฟล์นี้อย่างสมบูรณ์จากประวัติ Git ของคุณ
โดยทั่วไปดูเหมือนว่าเขาจะไม่ได้มีความคิดที่ชัดเจนใด ๆ สิ่งที่เขาหมายถึงโดย "ต้นน้ำ" และ "ปลายน้ำ" เมื่อพูดถึงประวัติศาสตร์ของความมุ่งมั่นในช่วงเวลา การใช้งานนี้เป็นทางการแล้วและไม่ควรได้รับการสนับสนุนเนื่องจากเป็นเพียงความสับสน
เป็นที่ชัดเจนอย่างสมบูรณ์ว่าทุกการกระทำ (ยกเว้นหนึ่ง) มีอย่างน้อยหนึ่งผู้ปกครองและผู้ปกครองของพ่อแม่เป็นบรรพบุรุษ และในอีกทางหนึ่งมีลูกและลูกหลาน นั่นเป็นคำศัพท์ที่ได้รับการยอมรับและอธิบายทิศทางของกราฟอย่างไม่น่าสงสัยดังนั้นจึงเป็นวิธีที่จะพูดเมื่อคุณต้องการอธิบายถึงความสัมพันธ์ที่มีต่อกันภายในเรขาคณิตกราฟของ repo อย่าใช้ "upstream" หรือ "downstream" อย่างหลวม ๆ ในสถานการณ์นี้
[หมายเหตุเพิ่มเติม: ฉันกำลังคิดถึงความสัมพันธ์ระหว่างประโยค Chacon แรกที่ฉันอ้างถึงข้างต้นและgit-merge
หน้าคนและมันเกิดขึ้นกับฉันว่าอดีตอาจขึ้นอยู่กับความเข้าใจผิดของหลัง หน้า man จะอธิบายสถานการณ์ที่การใช้ "upstream" นั้นถูกต้องตามกฎหมาย: การส่งต่ออย่างรวดเร็วมักเกิดขึ้นเมื่อ "คุณกำลังติดตามพื้นที่เก็บข้อมูล upstream คุณไม่ได้ทำการเปลี่ยนแปลงในเครื่องและตอนนี้คุณต้องการอัปเดตใหม่ การแก้ไขต้นน้ำ " ดังนั้น Chacon อาจใช้ "upstream" เพราะเขาเห็นที่นี่ในหน้าคน แต่ในหน้าคนมีที่เก็บระยะไกล; ไม่มีที่เก็บข้อมูลระยะไกลในตัวอย่างที่อ้างถึงของ Chacon เกี่ยวกับการส่งต่ออย่างรวดเร็วเพียงไม่กี่สาขาที่สร้างขึ้นภายในเครื่อง]
<branch>
จะเรียกว่าเป็น
git-rebase
เอกสารเพราะฉันสับสนโดยสิ้นเชิงว่าเหตุใดผู้ตัดสินจะถูกเรียกว่า "อัปสตรีม" ที่นั่น (อันที่จริงฉันสงสัยตัวเองมากเพราะฉันไม่เคยเห็นคำศัพท์นี้มาก่อน) ขอบคุณ @outis & @matt สำหรับการล้างสิ่งต่าง ๆ !
โดยทั่วไป
สิ่งนี้ใช้กับระบบที่มีลักษณะคล้ายต้นไม้ทั้งหมดรวมถึงระบบควบคุมแหล่งที่มา