ฉันจะใช้คอมไพล์ไฟล์ที่ไม่ได้ติดตามได้หรือไม่?


270

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

git diff --cached

?

คำตอบ:


267

ด้วยเวอร์ชัน git ที่ผ่านมาคุณสามารถgit add -Nไฟล์ (หรือ--intent-to-add) ซึ่งเพิ่ม blob ความยาวเป็นศูนย์ให้กับดัชนีที่ตำแหน่งนั้น ผลที่สุดคือตอนนี้ไฟล์ "untracked" ของคุณกลายเป็นการดัดแปลงเพื่อเพิ่มเนื้อหาทั้งหมดไปยังไฟล์ที่มีความยาวเป็นศูนย์และที่แสดงในเอาต์พุต "git diff"

git diff

echo "this is a new file" > new.txt
git diff

git add -N new.txt
git diff
diff --git a/new.txt b/new.txt
index e69de29..3b2aed8 100644
--- a/new.txt
+++ b/new.txt
@@ -0,0 +1 @@
+this is a new file

น่าเศร้าที่คุณไม่สามารถทำได้git stashในขณะที่คุณมี--intent-to-addไฟล์ที่ค้างอยู่เช่นนี้ แม้ว่าคุณต้องการซ่อนคุณเพียงแค่เพิ่มไฟล์ใหม่แล้วซ่อนไฟล์เหล่านั้น หรือคุณสามารถใช้วิธีแก้ปัญหาการจำลอง:

git update-index --add --cacheinfo \
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt

(ตั้งค่านามแฝงคือเพื่อนของคุณที่นี่)


ปรากฎว่าสำเนา Git ของฉันยังไม่เพียงพอที่จะเพิ่ม -N แต่สิ่งนี้ตอบคำถามของฉัน
Andrew Grimm

1
คุณสามารถเลียนแบบ "GIT เพิ่ม new.txt -N" กับ "คอมไพล์ปรับปรุงดัชนี --add --cacheinfo 100,644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt" (ไม่ว่าฉันจัดการที่จะนำนี้ในคำตอบที่ผิด?)
araqnid

เพิ่มคุณสมบัติใน 1.6.1: github.com/git/git/blob/master/Documentation/RelNotes/1.6.1.txt
MarcH

1
ถ้าคุณมีไฟล์ใหม่จำนวนมากมีวิธีง่าย ๆ ในการเพิ่มไฟล์ทั้งหมดแล้วแตกต่างกันหรือไม่?
Vic

1
@Vicgit add -N .
Nathan

92

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

git diff --no-index tracked_file untracked_file

3
ใช้งานได้หรือไม่หากคุณมีไฟล์ที่ไม่ได้ติดตามมากกว่าหนึ่งไฟล์ที่คุณสร้างตั้งแต่การส่งครั้งล่าสุด
Andrew Grimm

12
ใช่คำตอบที่สมบูรณ์แบบ! ฉันสามารถใช้git diff --no-index untracked_file_1 untracked_file_2เพื่อให้ได้git diffสีไวยากรณ์และอื่น ๆ ใน diffs ... สวยงาม
โคลินดีเบนเน็ตต์

40
ฉันไม่เข้าใจว่าทำไมคุณเปรียบเทียบไฟล์ที่ถูกติดตามกับไฟล์ที่ไม่ได้ติดตามซึ่งไม่เกี่ยวข้อง หากคุณต้องการรับเอาท์พุท diff สำหรับไฟล์ที่ไม่ได้ติดตามคุณสามารถใช้/dev/nullแทน: git diff --no-index -- /dev/null <untracked_file>.

4
หรือเพียงแค่cat untracked_file_1หรือบางทีprintf '\e[1;32m%s\e[0m\n' "$(cat untracked_file_1)"ถ้าคุณต้องการผลผลิตสีเขียว :) (แม้ว่าจะเป็นเรื่องที่ร้ายแรงกว่านี้โปรดทราบว่าการแทนที่คำสั่งจะลบบรรทัดใหม่ต่อท้ายออกจากไฟล์ของคุณ)
Wildcard

8
นี่ควรเป็นคำตอบที่ยอมรับได้ - มันไม่จำเป็นต้องเปลี่ยนดัชนีของคอมไพล์ ซึ่งตามที่ผู้เขียนต้นฉบับบอกว่ามีข้อเสีย
DIMMSum

38

สำหรับการ gitting แบบโต้ตอบแบบวันต่อวันของฉัน (ที่ฉันแตกต้นไม้ทำงานกับหัวตลอดเวลาและต้องการที่จะมีไฟล์ที่ไม่ได้ติดตามรวมอยู่ใน diff) add -N/--intent-to-addใช้ไม่ได้เพราะมันแตก git stashแบ่ง

ดังนั้นนี่คือการgit diffทดแทนของฉัน มันไม่ได้เป็นโซลูชั่นที่สะอาดเป็นพิเศษ แต่เนื่องจากฉันใช้เพียงแบบโต้ตอบเท่านั้นฉันจึงตกลงกับแฮ็ค:

d() {
    if test "$#" = 0; then
        (
            git diff --color
            git ls-files --others --exclude-standard |
                while read -r i; do git diff --color -- /dev/null "$i"; done
        ) | `git config --get core.pager`
    else
        git diff "$@"
    fi
}

การพิมพ์dจะรวมไฟล์ที่ไม่ได้ติดตามในส่วนต่าง (ซึ่งเป็นสิ่งที่ฉันสนใจในเวิร์กโฟลว์ของฉัน) และd args...จะทำงานเหมือนปกติgit diffจะทำตัวเหมือนปกติ

หมายเหตุ:

  • เรากำลังใช้ความจริงที่นี่ซึ่งgit diffเป็นเพียงส่วนบุคคลที่แตกต่างกันตัดแบ่งดังนั้นจึงเป็นไปไม่ได้ที่จะบอกdเอาต์พุตจาก "diff จริง" - ยกเว้นความจริงที่ว่าไฟล์ที่ไม่ได้ติดตามทั้งหมดถูกเรียงลำดับล่าสุด
  • ปัญหาเดียวของฟังก์ชั่นนี้คือเอาท์พุทเป็นสีเมื่อเปลี่ยนเส้นทาง; แต่ฉันไม่สามารถใส่ใจที่จะเพิ่มตรรกะสำหรับสิ่งนั้นได้
  • git diffฉันไม่สามารถหาวิธีที่จะได้รับไฟล์ที่ไม่ได้ติดตามรวมโดยเพียงแค่การรวบรวมรายการอาร์กิวเมนต์เนียนสำหรับ หากมีคนคิดวิธีการทำเช่นนี้หรืออาจมีการเพิ่มgitสถานที่ในอนาคตโปรดฝากข้อความไว้ที่นี่!

4
กระแทกแดกดันของฉันgit update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txtวิธีแก้ปัญหาผมแนะนำสำหรับ GITS เก่าไม่ทำงานร่วมกับgit stashสมมติว่าคุณมีอยู่แล้ว e69de29bb ในฐานข้อมูลของคุณเช่นโดยพยายามที่จะใช้add -Nก่อนหน้านี้ เห็นได้ชัดว่ามันไม่เทียบเท่าgit add -Nในบางวิธี: tbh ฉันไม่แน่ใจว่าอย่างไร
araqnid

2
คุณกำลังทำการเปรียบเทียบสตริงแทนที่จะตรวจสอบความเท่าเทียมกันของตัวเลขด้วยtestคำสั่งของคุณ ไม่ควรส่งผลกระทบต่อสิ่งใด แต่test "$#" -eq 0มีความแม่นยำมากกว่าสิ่งที่ตั้งใจไว้
Wildcard

1
ใช่ดูเหมือนว่าคุณจะต้องทำมันเป็นคู่ ... แต่สามารถปลอมมันเป็นไฟล์เดียวlessดังนั้นคุณไม่จำเป็นต้องกดqแต่ละไฟล์และมันให้ความรู้สึกเหมือนgit diffกันโดยการลบเลขหน้าต่อไฟล์ ( -P) เพิ่มเข้าไปอีกหลังจากนั้น ( | less), รักษาสี ( --color=always) และตีความมันเป็นสี ( less -rหรือless -R) ดังนั้นทั้งหมด:do git -P diff --color=always -- /dev/null "$i"; done | less -r
hyperpallium

ในกรณีที่คุณต้องการที่จะใส่ใจในอนาคตtest -t 1(เช่นif [ -t 1 ]; then color_arg=--color; fiหรือบางสิ่งบางอย่าง) เป็นวิธีที่เชลล์จะตรวจสอบว่าเอาต์พุตของมันเป็นเทอร์มินัลซึ่งเป็นวิธีที่มีประโยชน์ในการตัดสินใจเลือกสี และxargsอาจให้วิธีกำจัดขณะลูป คุณจะยังคงต้องการ-n 1มันดังนั้นมันจะยังคงเปิดใช้งานได้หลายครั้งและยังคงต้องเป็นแบบคู่กัน แต่ ... มันจะกำจัดwhileและreadดังนั้นอาจจะดีกว่า! ฉันปล่อยให้ผู้อ่าน
ลินเดส

28

ไม่ใช่จุด 100% แต่ถ้าด้วยเหตุผลบางอย่างคุณไม่ต้องการเพิ่มไฟล์ของคุณไปยังดัชนีตามคำแนะนำที่ยอมรับโดยคำตอบที่ยอมรับนี่คือตัวเลือกอื่น:

หากไฟล์นั้นไม่ได้ติดตามอย่างเห็นได้ชัด diff คือไฟล์ทั้งหมดดังนั้นคุณสามารถดูไฟล์เหล่านั้นได้โดยใช้น้อย:

less $(git ls-files --others --exclude-standard)

นำทางระหว่างพวกเขาด้วย:nและ:pสำหรับถัดไปและก่อนหน้า ..

อัปเดตจากความคิดเห็น:หากคุณต้องการรูปแบบแพตช์คุณสามารถรวมเข้ากับgit diff:

git ls-files --others --exclude-standard | xargs -n 1 git --no-pager diff /dev/null | less

คุณยังสามารถเปลี่ยนทิศทางเอาต์พุตไปยังไฟล์หรือใช้คำสั่ง diff อื่นในกรณีนี้


6
คุณสามารถเรียกใช้git diff /dev/null <untracked_tile>และรับแพตช์ในรูปแบบแพทช์ได้มากกว่า "เพียงแค่" ไฟล์
SimSimY

2
คำตอบนี้รวมกับ git diff เป็นคำตอบที่สมบูรณ์แบบ
iwind

22
git add -A
git diff HEAD

สร้างแพตช์หากจำเป็นและจากนั้น:

git reset HEAD

สิ่งนี้มีความเป็นไปได้ที่จะสูญเสียงานก่อน (ก่อน) โดยการเพิ่มทุกอย่าง โดยเฉพาะอย่างยิ่งกรณีที่มีการใช้git add -pบ่อยมาก (ซึ่งโดยทั่วไปฉันแนะนำโดยวิธีการ) ... นี้จะให้วิธีการทำสิ่งพื้นฐานเพียงแค่ ... ควรสังเกตว่ามันมีศักยภาพสำหรับด้านที่ไม่พึงประสงค์ ผลกระทบ
ลินเดส

13

สิ่งนี้ใช้ได้กับฉัน:

git add my_file.txt
git diff --cached my_file.txt
git reset my_file.txt

ขั้นตอนสุดท้ายเป็นทางเลือกมันจะปล่อยให้ไฟล์อยู่ในสถานะก่อนหน้า (ไม่ได้ติดตาม)

มีประโยชน์ถ้าคุณกำลังสร้างแพตช์ด้วย:

  git diff --cached my_file.txt > my_file-patch.patch

ความจำเพาะของคู่เพิ่ม / รีเซ็ตนี้เป็นความแตกต่างที่ดีกับวิธีปืนลูกซองของstackoverflow.com/a/50486906/313756 ... ขอบคุณสำหรับสิ่งนั้น
ลินเดส

9

การเปลี่ยนแปลงทำงานเมื่อ staged และ non-staged ด้วยคำสั่งนี้ ไฟล์ใหม่จะทำงานเมื่อฉาก:

$ git diff HEAD

หากไฟล์เหล่านี้ไม่ถูกจัดฉากคุณจะเห็นความแตกต่างของไฟล์เท่านั้น


26
HEADเป็นค่าเริ่มต้นดังนั้นนี่เป็นสิ่งเดียวกับgit diffที่ไม่สามารถแก้ปัญหาได้
Iulian Onofrei

4
สิ่งนี้ต้องการgit addจากไฟล์ที่ไม่ได้ติดตามทุกไฟล์
SilvioQ

หากคุณแก้ไขคำตอบนี้เพื่อให้เป็นคำตอบgit addที่ง่ายที่สุดถ้ากรณีการใช้งานของคุณคือการตรวจสอบสิ่งที่คุณเพิ่งเพิ่ม / ต้องการเพิ่ม
KCD

8

สำหรับหนึ่งไฟล์:

git diff --no-index /dev/null new_file

สำหรับไฟล์ใหม่ทั้งหมด:

for next in $( git ls-files --others --exclude-standard ) ; do git --no-pager diff --no-index /dev/null $next; done;

เป็นนามแฝง:

alias gdnew="for next in \$( git ls-files --others --exclude-standard ) ; do git --no-pager diff --no-index /dev/null \$next; done;"

สำหรับไฟล์ที่ถูกแก้ไขและใหม่ทั้งหมดจะรวมกันเป็นคำสั่งเดียว:

{ git --no-pager diff; gdnew }

2

โดยปกติเมื่อฉันทำงานกับทีมที่ตั้งระยะไกลเป็นสิ่งสำคัญสำหรับฉันที่ฉันมีความรู้ก่อนว่าการเปลี่ยนแปลงที่ทำโดยทีมอื่นในไฟล์เดียวกันก่อนที่ฉันจะทำตามขั้นตอนคอมไพล์ untrack -> ฉาก -> กระทำเพื่อที่ฉันเขียนสคริปต์ทุบตี ช่วยฉันหลีกเลี่ยงการแก้ไขข้อขัดแย้งผสานกับทีมระยะไกลหรือสร้างสาขาในพื้นที่ใหม่และเปรียบเทียบและผสานกับสาขาหลัก

#set -x 
branchname=`git branch | grep -F '*' |  awk '{print $2}'`
echo $branchname
git fetch origin ${branchname}
for file in `git status | grep "modified" | awk "{print $2}" `
do
echo "PLEASE CHECK OUT GIT DIFF FOR "$file 
git difftool FETCH_HEAD $file ;
done

ในสคริปต์ข้างต้นฉันดึงสาขาหลักระยะไกล (ไม่จำเป็นต้องสาขาหลักของมัน) เพื่อ FETCH_HEAD พวกเขาทำรายการของไฟล์ที่แก้ไขของฉันเท่านั้นและเปรียบเทียบไฟล์ที่แก้ไขไปยังคอมไพล์โฟล

ที่นี่มี difftool รองรับโดย git ฉันกำหนดค่า 'Meld Diff Viewer' สำหรับการเปรียบเทียบ GUI ที่ดี


-9

สมมติว่าคุณไม่มีข้อผูกพันในท้องถิ่น

git diff origin/master

8
คำถามจะถามถึงgit diffคำสั่งที่มีไฟล์ที่ไม่ได้ติดตาม คำสั่งนี้ไม่รวมพวกเขา นอกจากนี้ไม่ว่าจะมีความมุ่งมั่นในท้องถิ่นหรือไม่ก็ไม่มีอะไรเกี่ยวข้องกับคำถาม
toon81

JFTR ฉันgit merge --squash mybranchและgit diff masterแสดงให้ฉันเห็นการเปลี่ยนแปลงในไฟล์ที่ไม่ได้ติดตาม
muammar

2
นั่นเป็นไปไม่ได้ คุณดูเหมือนจะสับสนเกี่ยวกับความหมายของคำว่า "ไม่ได้ติดตาม" ไม่ได้ติดตามไม่ได้หมายความว่าไฟล์จะถูกติดตามในสาขาเดียวและไม่ใช่สาขาอื่นหมายความว่าไฟล์นั้นไม่ได้ "อยู่ใน Git" ไม่ว่าที่ใดก็ตาม ไม่ว่าคุณจะสควอชหรือไม่สร้างความแตกต่าง git diffไม่แสดงความแตกต่างในไฟล์ที่ไม่ได้ติดตาม: เนื่องจากไฟล์เหล่านั้นไม่ได้ติดตามไม่มีการแสดงผลตามนิยาม มันเป็นเพียงวิธีการทำงานของ Git :)
toon81
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.