เพราะเหตุใดสถานะ Git จึงแสดงว่าสาขามีความทันสมัยเมื่อมีการเปลี่ยนแปลงที่ต้นน้ำ


226

การเปลี่ยนแปลงมีอยู่ในสตรีมในสาขาที่ถูกติดตาม แต่เมื่อฉันพิมพ์git statusมันบ่งชี้ว่าสาขาในท้องถิ่นของฉันทันสมัย นี่เป็นพฤติกรรมใหม่ฉันเปลี่ยนการตั้งค่าหรือเป็นสิ่งที่ผิดหรือเปล่า

ขอบคุณสำหรับความช่วยเหลือ

ubuntu@host:/my/repo# git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean


ubuntu@host:/my/repo# git pull
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 11 (delta 6), reused 0 (delta 0)
Unpacking objects: 100% (11/11), done.
From bitbucket.org:my/repo
   1234567..abcdefg  master     -> origin/master
Updating 1234567..abcdefg
Fast-forward
 file1        |  1 -
 file2        | 43 +++++++++++++++++++++++++++++++++++++++++++
 file3        | 21 ++++++++++++---------
 file4        | 21 ++++++++++++---------
 4 files changed, 67 insertions(+), 19 deletions(-)
 create mode 100644 file5

คำตอบ:


274

สถานะอะไรจะบอกคุณว่าคุณอยู่เบื้องหลังเตะที่เรียกว่าorigin/master ซึ่งเป็นโทษในท้องถิ่น repo ในกรณีนี้การอ้างอิงเกิดขึ้นเพื่อติดตามสาขาในรีโมตบางอันที่เรียกoriginแต่สถานะไม่ได้บอกอะไรคุณเกี่ยวกับสาขาในรีโมต กำลังบอกคุณเกี่ยวกับการอ้างอิงซึ่งเป็นเพียงรหัสการกระทำที่เก็บไว้ในระบบไฟล์ในเครื่องของคุณ (ในกรณีนี้โดยทั่วไปจะเป็นไฟล์ที่เรียกว่า.git/refs/remotes/origin/masterrepo ในเครื่องของคุณ)

git pullดำเนินการสองอย่าง ก่อนอื่นต้องทำgit fetchเพื่อให้ทันกับคอมมิชชันใน repo ระยะไกล (ซึ่งอัพเดตorigin/masterref ใน repo ท้องถิ่นของคุณ) จากนั้นgit mergeจะรวมการคอมมิชชันเหล่านั้นในสาขาปัจจุบัน

จนกว่าคุณจะทำตามfetchขั้นตอน (ไม่ว่าจะด้วยตัวเองหรือผ่านgit pull) repo ในพื้นที่ของคุณไม่มีทางรู้ว่ามีการส่งข้อมูลเพิ่มขึ้นและgit statusดูเฉพาะการorigin/masterอ้างอิงในพื้นที่ของคุณ

เมื่อgit statusพูดถึงปัจจุบันหมายถึง "up-to-date กับสาขาที่สาขาปัจจุบันติดตาม" ซึ่งในกรณีนี้หมายถึง "up-to-date กับผู้อ้างอิงในท้องถิ่นorigin/master" นั่นเท่ากับเท่านั้น "up-to-date กับสถานะ upstream ที่ถูกดึงมาครั้งล่าสุดที่เราทำfetch" ซึ่งไม่เหมือนกับ "up-to-date กับสถานะสดล่าสุดของ upstream"

ทำไมมันถึงทำงานแบบนี้? ดีfetchขั้นตอนคือการดำเนินการเครือข่ายที่อาจเกิดขึ้นช้าและมีราคาแพง การออกแบบของ Git (และระบบควบคุมเวอร์ชันกระจายอื่น ๆ) คือการหลีกเลี่ยงการทำงานของเครือข่ายเมื่อไม่จำเป็นและเป็นรูปแบบที่แตกต่างอย่างสิ้นเชิงกับระบบไคลเอนต์ - เซิร์ฟเวอร์ทั่วไปที่หลายคนคุ้นเคย ของ "สาขาการติดตามระยะไกล" ที่ทำให้เกิดความสับสนที่นี่ไม่ได้ใช้ร่วมกันโดย DVCS ทั้งหมด) เป็นไปได้ทั้งหมดที่จะใช้ Git ออฟไลน์โดยไม่มีการเชื่อมต่อกับเซิร์ฟเวอร์ส่วนกลางและผลลัพธ์ของการgit statusสะท้อนนี้

การสร้างและสลับสาขา (และตรวจสอบสถานะของพวกเขา) ใน Git นั้นควรจะมีน้ำหนักเบาไม่ใช่สิ่งที่ทำให้การทำงานของเครือข่ายช้าไปสู่ระบบรวมศูนย์ ข้อสันนิษฐานในการออกแบบ Git และgit statusผลลัพธ์คือผู้ใช้เข้าใจสิ่งนี้ (ฟีเจอร์ Git มากเกินไปทำให้เข้าใจได้ถ้าคุณรู้แล้วว่า Git ทำงานอย่างไร) ด้วยการยอมรับ Git จากผู้ใช้งานจำนวนมากที่ไม่คุ้นเคยกับ DVCS ข้อสันนิษฐานนี้จึงไม่ถูกต้องเสมอไป


79
ความคิดเห็นช้า แต่ฉันวิ่งเข้าไปในสถานการณ์เดียวกัน ฉันเข้าใจว่าเหตุใด git จึงไม่มีทางรู้เกี่ยวกับการเปลี่ยนแปลงก่อนดึงข้อมูล แต่ก็ไม่ควรพูดว่า "ทันสมัย" ซึ่งก็ไม่เป็นความจริง มันควรที่จะพูดว่า "ไม่รู้ว่าเกิดอะไรขึ้นในระยะไกล"
Droidum

31
อาจจะเป็นเหตุผลที่เคร่งครัด แต่ก็ไม่สมเหตุสมผลกับมนุษย์ ทำไมคุณไม่ออกแบบให้ทำการดึงข้อมูลแล้วประกาศว่าเป็นรุ่นล่าสุดหรือไม่ หรือเปลี่ยนข้อความเพื่อบอกสิ่งที่มันทำจริง ๆ เช่น "สาขาของคุณเป็นรุ่นล่าสุดด้วย 'ที่มา / หลัก' เมื่อตรวจสอบล่าสุดที่ {timestamp}"? หรือแม้แต่แค่พูดว่า "ทำการดึงข้อมูลเพื่อค้นหาว่าสาขาของคุณทันสมัยหรือไม่"?
โคลินอาจ

25
ทำไมต้องแสดงข้อความ "สาขาของคุณทันสมัย" ฉันไม่เห็นจุดในการรู้สถานะของต้นกำเนิด / หลักและถ้ามันควรจะเป็นตัวแทนสาขาต้นแบบที่แท้จริงบนรีโมทของจุดเริ่มต้นมันก็ไม่มีความคิดอะไรเลย
whiterook6

2
@pastullo ดังนั้นสร้างนามแฝง
Jonathan Wakely

23
นี่เป็นตัวอย่างที่สมบูรณ์แบบของการใช้งานที่น่ากลัวของ Git ฉันชอบพลังและความยืดหยุ่นของมัน แต่เพียงเปลี่ยนข้อความเป็น "สาขาของคุณเป็นรุ่นล่าสุดด้วย 'ต้นกำเนิด / ต้นแบบ' ในท้องที่ จะเป็นการปรับปรุงครั้งใหญ่ ความสับสนที่นี่คือที่มาสาขาท้องถิ่น / ต้นแบบ (รูปแบบการจับคู่กับ remotes / สาขาที่คุณใช้) ซึ่งติดตามสาขาระยะไกล
matthewcummings516

35

นี่เป็นเพราะ repo ในพื้นที่ของคุณไม่ได้เช็คอินด้วยรีโมทอัปสตรีม หากต้องการให้งานนี้เป็นไปตามที่คุณคาดหวังให้ใช้git fetchแล้วเรียกใช้git statusอีกครั้ง


7

ในขณะที่สิ่งเหล่านี้เป็นคำตอบที่ใช้ได้จริงฉันตัดสินใจที่จะให้วิธีการตรวจสอบว่า repo ในพื้นที่อยู่ในแนวเดียวกันกับรีโมตโดยไม่มีการดึงหรือดึง เพื่อที่จะดูว่าฉันใช้กิ่งไม้อยู่ที่ไหน:

git remote show origin

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

  * remote origin
  Fetch URL: https://github.com/xxxx/xxxx.git
  Push  URL: https://github.com/xxxx/xxxx.git
  HEAD branch: master
  Remote branches:
    master      tracked
    no-payments tracked
  Local branches configured for 'git pull':
    master      merges with remote master
    no-payments merges with remote no-payments
  Local refs configured for 'git push':
    master      pushes to master      (local out of date)
    no-payments pushes to no-payments (local out of date)

หวังว่านี่จะช่วยใครซักคน


0

"origin / master" หมายถึงการอ้างอิง poiting ไปยัง HEAD commit of branch "Origin / master" การอ้างอิงคือชื่อนามแฝงที่เป็นมิตรกับมนุษย์สำหรับวัตถุ Git ซึ่งโดยทั่วไปจะเป็นวัตถุที่กระทำ การอ้างอิง "ที่มา / หลัก" จะได้รับการอัปเดตเมื่อคุณgit pushไปที่รีโมตเท่านั้น ( http://git-scm.com/book/en/v2/Git-Internals-Git-References#Remotes )

จากภายในรูทของโครงการของคุณให้เรียกใช้:

cat .git/refs/remotes/origin/master

เปรียบเทียบรหัสยืนยันที่แสดงกับ:

cat .git/refs/heads/master

พวกเขาควรจะเหมือนกันและนั่นคือเหตุผลที่ Git บอกว่าmasterเป็นข้อมูลล่าสุดorigin/masterกับ

เมื่อคุณวิ่ง

git fetch origin master

ที่ดึงวัตถุ Git ใหม่ในเครื่องภายใต้โฟลเดอร์. git / objects และ Git จะอัพเดท. git / FETCH_HEAD ดังนั้นในตอนนี้มันจะชี้ไปที่การกระทำล่าสุดของสาขาที่ดึงมา

หากต้องการดูความแตกต่างระหว่างสาขาในพื้นที่ปัจจุบันของคุณและสาขาที่ดึงข้อมูลจากอัปสตรีมคุณสามารถเรียกใช้

git diff HEAD FETCH_HEAD

1
คุณไม่ควรแสดงรายการในไดเรกทอรี. git มันจะไม่ทำงานกับการอ้างอิงที่บรรจุ พฤติกรรมการดึงข้อมูลที่คุณอธิบายไว้สำหรับ git รุ่นเก่ากว่า
Andrew C

การorigin/masterอ้างอิงไม่ได้รับการอัปเดตด้วยการดึงข้อมูลเช่นเดียวกับการพุช
โจนาธาน Wakely

แก้ไข. ฉันใช้ Git 1.8.3 มาแล้ว ฉันสามารถสังเกตเห็นแน่นอนกับรุ่น 2.2.1, FETCH_HEAD ได้รับการปรับปรุงในระหว่างการดึงข้อมูลเช่นกัน เมื่อมันมาถึงข้อความ "สาขาของคุณเป็นรุ่นล่าสุดที่มี ... " หรือ "สาขาของคุณอยู่ด้านหลัง ... โดย X commits" จะแสดงเฉพาะเมื่อสาขาในพื้นที่ของคุณติดตามสาขาระยะไกลที่กำหนด สำหรับต้นแบบเพื่อติดตามต้นกำเนิด / หลักหนึ่งจะต้องรัน git branch -u origin / master จาก branch master หากไม่มีการติดตามคุณยังจำเป็นต้องเรียกใช้คอมไพล์ git
Marek Stanley

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

0

ให้ดูเป็น repo คอมไพล์ตัวอย่างเพื่อตรวจสอบว่าyour branch (master)เป็นด้วยup to dateorigin/master

ตรวจสอบว่าต้นแบบท้องถิ่นกำลังติดตามที่มา / ต้นแบบ:

$ git branch -vv
* master a357df1eb [origin/master] This is a commit message

ข้อมูลเพิ่มเติมเกี่ยวกับสาขาหลักของท้องถิ่น:

$ git show --summary
commit a357df1eb941beb5cac3601153f063dae7faf5a8 (HEAD -> master, tag: 2.8.0, origin/master, origin/HEAD)
Author: ...
Date:   Tue Dec 11 14:25:52 2018 +0100

    Another commit message

ตรวจสอบว่า Origin / Master อยู่ในการกระทำเดียวกันหรือไม่:

$ cat .git/packed-refs | grep origin/master
a357df1eb941beb5cac3601153f063dae7faf5a8 refs/remotes/origin/master

เราสามารถเห็นแฮชแบบเดียวกันได้รอบ ๆ และปลอดภัยที่จะบอกว่าสาขานั้นสอดคล้องกับรีโมตตัวหนึ่งอย่างน้อยใน repo คอมไพล์ปัจจุบัน



0

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

ท้ายที่สุดไฟล์ดังกล่าวตรงกับรูปแบบในไฟล์. gitignore


0

ในกรณีนี้ใช้ git เพิ่มและรวมไฟล์ที่ค้างอยู่ทั้งหมดแล้วใช้ git กระทำแล้วกด git

git add - รวมไฟล์ pedent ทั้งหมด

คอมไพล์กระทำ - บันทึกการกระทำ

git push - บันทึกไปยังพื้นที่เก็บข้อมูล

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