ฉันจะรับความแตกต่างระหว่างการกระทำทั้งหมดที่เกิดขึ้นระหว่างสองวันที่กับ Git ได้อย่างไร


117

หรือแค่การกระทำทั้งหมดที่เกิดขึ้นระหว่างวันที่สองวัน? ใน SVN คุณสามารถทำสิ่งต่างๆเช่น

svn diff -r{date}:{date}

จะทำ! ฉันไม่พบ Git ที่เทียบเท่ากับสิ่งนี้

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

คำตอบ:


160

คุณสามารถใช้ git whatchanged --since="1 day ago" -p

นอกจากนี้ยังใช้เวลา--untilโต้แย้ง

เอกสาร


ขอบคุณ! นี่คือสิ่งที่ฉันต้องการมันใช้พารามิเตอร์ --committer แม้ว่าจะไม่ได้ระบุไว้ในเอกสารประกอบก็ตาม! นอกจากนี้ 'git whatchanged' ก็ไม่ปรากฏใน 'git help'! ไม่รู้ว่าทำไม ... ขอบคุณอีกครั้ง
คริส

5
คุณควรตอบคำตอบที่คุณเลือกเพื่อให้เซทได้รับผลกรรมบางอย่าง
Scott

18
@brbob ฉันรู้ว่าคำตอบนี้เมื่อนานมาแล้ว แต่สำหรับคนที่สะดุดกับสิ่งนี้ (เหมือนที่ฉันทำ) Git ช่วยพูดว่า: The command is kept primarily for historical reasons; fingers of many people who learned Git long before git log was invented by reading Linux kernel mailing list are trained to type it. ดังนั้นเอกสารจึงสนับสนุนให้ใช้git logแทนgit whatchanged; คำสั่งสุดท้ายนี้ยังใช้อ็อพชัน --no-merge ของ git log ดังนั้นจึงให้ผลลัพธ์ที่เหมือนกัน
Ramses

2
git whatchanged เป็นนามแฝงของคำสั่ง git log ตามเอกสารของ git log
Vincent

2
git whatchangedเลิกใช้งานแล้วเนื่องจากเวอร์ชันล่าสุดปัจจุบัน 2.21.0 git whatchangedความสำเร็จทั้งหมดสามารถทำได้โดยgit logและเก็บรักษาไว้ด้วยเหตุผลทางประวัติศาสตร์เท่านั้น ดูรายละเอียดgit-scm.com/docs/git-whatchanged/2.21.0
Devy

60

คำแนะนำก่อนหน้านี้มีข้อบกพร่องบางประการ โดยพื้นฐานแล้วฉันกำลังมองหาสิ่งที่เทียบเท่ากับcvs diff -D"1 day ago" -D"2010-02-29 11:11". ในขณะที่รวบรวมข้อมูลมากขึ้นเรื่อย ๆ ฉันพบวิธีแก้ปัญหา

สิ่งที่ฉันได้ลอง:

  • git whatchanged --since="1 day ago" -pจากที่นี่

    แต่สิ่งนี้ให้ความแตกต่างสำหรับแต่ละคอมมิตแม้ว่าจะมีหลายคอมมิตในไฟล์เดียวก็ตาม ฉันรู้ว่า"วันที่" เป็นแนวคิดที่หลวม ๆ ในคอมไพล์ฉันคิดว่าต้องมีวิธีการทำเช่นนี้

  • git diff 'master@{1 day ago}..masterให้คำเตือนwarning: Log for 'master' only goes back to Tue, 16 Mar 2010 14:17:32 +0100.และไม่แสดงความแตกต่างทั้งหมด

  • git format-patch --since=yesterday --stdout ไม่ให้อะไรกับฉัน

  • revs=$(git log --pretty="format:%H" --since="1 day ago");git diff $(echo "$revs"|tail -n1) $(echo "$revs"|head -n1) ใช้งานได้ แต่ดูเหมือนซับซ้อนและไม่ จำกัด เฉพาะสาขาปัจจุบัน

สุดท้าย:

อย่างสนุกสนาน git-cvsserver ไม่รองรับ "cvs diff -D" (โดยที่ไม่มีการบันทึกไว้ที่ใดที่หนึ่ง)


4
+1 สำหรับgit rev-listซึ่งช่วยแก้ปัญหาที่คล้ายกันมากที่ฉันเห็น
me_and

นี่ไม่ควรเป็นคำตอบที่ยอมรับได้เซทนั้นกระชับและถูกต้องมากกว่า
ctford

6
@ctford ในมุมมองของฉันมันไม่ถูกต้อง อาจรายงานความแตกต่างหลายรายการสำหรับไฟล์เดียวไม่ใช่ความแตกต่างต่อไฟล์เป็น svn / cvs diff
Weidenrinde

1
@Weidenrinde +1 นี่ฉลาดกว่านี้มาก
rostamn739

1
git diff 'master@{1 day ago}..masterไวยากรณ์หมายถึง "การตรวจสอบreflogและตัวเลขออกที่สาขาmasterที่ใช้ในการจุดในพื้นที่เก็บข้อมูลในท้องถิ่นของคุณ 1 day ago " masterโดยเฉพาะจะไม่ใช้จริงกระทำประวัติศาสตร์ของสาขาในปัจจุบัน นี่เป็นสิ่งที่คุณต้องการไม่มากนัก
Mikko Rantalainen

22

"date" เป็นแนวคิดที่หลวม ๆ ในคอมไพล์ การคอมมิตจะมีวันที่ของผู้เขียนซึ่งอาจเป็นเวลาที่ดีในอดีตก่อนที่จะมีคนดึง / ส่งคอมมิตไปยังที่เก็บของพวกเขาคอมมิตอาจได้รับการ rebased และอัปเดตเพื่อให้อยู่เหนือการกระทำที่ใหม่กว่าอย่างเห็นได้ชัด

คอมมิตยังมีวันที่คอมมิตซึ่งจะอัพเดตหากคอมมิตถูก rebased หรือแก้ไขด้วยวิธีใด ๆ การกระทำเหล่านี้มีแนวโน้มที่จะเป็นไปตามลำดับเวลา แต่คุณยังคงอยู่ในความเมตตาของผู้สื่อสารที่กำหนดเวลาที่ถูกต้องในคอมพิวเตอร์ของเขาและถึงอย่างนั้นการคอมมิตที่ไม่ได้ปรับเปลี่ยนสามารถนั่งอยู่บนสาขาคุณลักษณะบนพื้นที่เก็บข้อมูลระยะไกลได้โดยไม่มีกำหนดก่อน ถูกรวมเข้ากับสาขาหลักของที่เก็บกลาง

สิ่งที่น่าจะเป็นประโยชน์ที่สุดสำหรับวัตถุประสงค์ของคุณคือวันที่อ้างอิงในที่เก็บเฉพาะที่เป็นปัญหา หากคุณเปิดใช้งาน reflogs ต่อสาขา (ดูgit config core.logAllRefUpdates) คุณสามารถใช้ref@{date}ไวยากรณ์เพื่ออ้างถึงว่าสาขาอยู่ที่ใดในช่วงเวลาหนึ่ง

เช่น

git log -p master@{2009-07-01}..master@{now}

คุณยังสามารถใช้คำอธิบาย 'ฟัซซี่' เช่น:

git log -p "master@{1 month ago}..master@{yesterday}"

คำสั่งเหล่านี้จะแสดงการกระทำทั้งหมดที่ 'ปรากฏ' ในสาขาที่กำหนดของที่เก็บโดยไม่คำนึงว่าจะ 'เก่า' เพียงใดตามผู้เขียนและวันที่กระทำ

โปรดทราบว่า reflog ต่อสาขานั้นเฉพาะสำหรับที่เก็บดังนั้นหากคุณกำลังเรียกใช้คำสั่งบันทึกบนโคลนและคุณไม่ดึง (พูด) เดือนจากนั้นดึงการเปลี่ยนแปลงทั้งหมดของเดือนที่แล้วพร้อมกัน จากนั้นการเปลี่ยนแปลงทั้งหมดของเดือนที่แล้วจะปรากฏใน@{1 hour ago}..@{now}ช่วง หากคุณสามารถเรียกใช้คำสั่งบันทึกบน repostory 'ส่วนกลาง' ที่ผู้คนส่งไปก็อาจทำในสิ่งที่คุณต้องการ


การเขียนที่ดีมากและคำตอบที่ดีสำหรับคำถามที่ระบุไว้ ...
Jakub Narębski

ขึ้นอยู่กับว่ามันอาจช่วยได้ถ้าเขาต้องการแยกวิเคราะห์สิ่งที่ถูกผลักไปยังสาขาหนึ่งบนที่เก็บส่วนกลางบางแห่งและคำสั่งบันทึกถูกรันบนที่เก็บนั้น ฉันคิดว่าการแก้ไขเป็นไปตามลำดับ ...
CB Bailey

"วันที่กระทำซึ่งได้รับการอัปเดตหากมีการคืนค่าคอมมิตหรือแก้ไขไม่ว่าด้วยวิธีใดก็ตาม" จริงๆแล้ววันที่นั้นจะไม่มีการเปลี่ยนแปลง คอมมิตทั้งหมดจะถูกแทนที่ด้วยคอมมิตอื่น (แม้ว่าทรีอาจจะเหมือนกัน)
hasen

2
@hasen j: ในทางเทคนิคคุณถูกต้อง คอมมิตไม่เปลี่ยนรูป เมื่อคุณปรับฐานใหม่หรือแก้ไขคอมมิตและสร้างคอมมิตใหม่ข้อความคอมมิตที่มีอยู่รายละเอียดผู้แต่งและวันที่ผู้เขียนมักจะถูกคัดลอกจากคอมมิตเก่าดังนั้นจึงเหมือนกับว่าคุณกำลังอัปเดตคอมมิตด้วยรหัสคอมมิตใหม่และวันที่คอมมิต
CB Bailey

โปรดทราบว่า@{time spec}ไวยากรณ์จะอ้างอิงถึงreflogในเครื่องของคุณเสมอ ไม่ได้อ้างถึงประวัติการกระทำจริง (DAG) หากคุณไม่เข้าใจความแตกต่างอย่าใช้ไวยากรณ์นี้!
Mikko Rantalainen

14
git diff --stat @{2013-11-01}..@{2013-11-30}

หรือ

git diff --stat @{2.weeks.ago}..@{last.week}

ขึ้นอยู่กับ reflog หรือไม่? เพราะถ้าเป็นเช่นนั้นคุณจะไม่สามารถใช้สิ่งนี้ได้จริงหาก repo ที่คุณกำลังเรียกใช้คำสั่งนี้ใหม่กว่า (เช่นโคลนใหม่) กว่าประวัติการกระทำที่มีอยู่

2
ใช่ทั้งหมดนี้ขึ้นอยู่กับ reflog และใช่สิ่งนี้ใช้ได้เฉพาะในประวัติสำเนาภายในเครื่อง แต่เป็นคำสั่งที่สะดวกเล็กน้อย
AA.

1
ใช่ฉันยอมรับอย่างแน่นอนว่าสะดวกตราบใดที่คุณมีรายการ reflog เก่าพอที่จะรองรับได้

ขอบคุณ AA. จากคำตอบของคุณฉันสามารถทำได้: git annotate --stat .. @ {2017-08-8} ชื่อไฟล์ | น้อย; git ใส่คำอธิบายประกอบ --stat .. @ {5.days.ago} ชื่อไฟล์; เพื่อให้ฉันเห็นการเปลี่ยนแปลงในบริบท
คริส

โปรดทราบว่า@{time spec}ไวยากรณ์เสมอหมายของคุณ reflogในเครื่องเสมอ ไม่ได้อ้างถึงประวัติการกระทำจริง (DAG) หากคุณไม่เข้าใจความแตกต่างอย่าใช้ไวยากรณ์นี้!
Mikko Rantalainen

4

บางที

$ git format-patch --committer=<who> --since=yesterday --stdout

คือสิ่งที่คุณต้องการ (มีหรือไม่มี "--stdout")?


1
คำถามด่วน - ตั้งแต่ใช้วันที่กระทำหรือไม่?
CB Bailey

3

ฉันเชื่อว่าวิธีแก้ปัญหาทั่วไปคือการใช้:

git rev-list -n1 --first-parent --until=<a date string> <a ref>

หากไม่มี - พ่อแม่ลำดับแรกคุณอาจได้รับคอมมิตจากสาขาที่รวมเข้าด้วยกันในภายหลังa refแต่ยังไม่ได้รวมเข้าด้วยกันa date stringแต่ไม่ได้รับการควบรวมกิจการเป็นของ

นี่เป็นอีกทางเลือกหนึ่งในการใช้--childrenและgrepแทน-n1:

mlm_git_ref_as_of() {
    # # Examples #
    #
    # Show all commits between two dates:
    #
    #     git log $(mlm_git_ref_as_of '2012-05-21 09:00:00-0400')..$(mlm_git_ref_as_of '2012-05-21 17:00:00-0400')
    #
    # Show diffs of all commits between two dates:
    #
    #     git diff $(mlm_git_ref_as_of '2012-05-21 09:00:00-0400')..$(mlm_git_ref_as_of '2012-05-21 17:00:00-0400')
    local as_of="$1"
    local ref="${2:-HEAD}"
    # Get the most recent commit (--children, grep -v ' ') that was on
    # the given branch ($ref, --first-parent) as of a given date
    # ($as_of)
    git rev-list --children --first-parent --until="$as_of" "$ref" | grep -v ' '
}

ฉันไม่คุ้นเคยgit whatchangedมาก่อนที่จะอ่านคำถามและคำตอบนี้ แต่มันให้ผลลัพธ์ที่แตกต่างกันมากสำหรับฉันดังนั้นฉันจึงไม่แน่ใจว่ามันทำอะไร


3

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

git diff X

สิ่งนี้มีข้อได้เปรียบที่ไม่ได้ขึ้นอยู่กับรายการ reflog ในโคลนใหม่ซึ่งแตกต่างจากไฟล์

git diff <reference>@{n}..
git log <reference>@{n}..

โซลูชั่นใน


3

ในการดูไฟล์ Git ที่เปลี่ยนไปจากวันที่ไปยังวันที่ในสาขาของคุณให้ใช้สูตรต่อไปนี้:

  1. ชำระเงินสาขาของคุณ
  2. ดึงและอัปเดตการเปลี่ยนแปลงจากที่เก็บระยะไกล
  3. ดูไฟล์ที่แตกต่างจากวันที่ถึงช่วงวันที่

สูตร :

git checkout <branch>
git pull
git diff --stat @{fromDate}..@{toDate}

โปรดทราบว่าวันที่อยู่ในรูปแบบ YYYY-MM-DD :

git diff --stat @{2019-08-20}..@{2019-08-21}

หากคุณต้องการสังเกตการเปลี่ยนแปลงของไฟล์เฉพาะในช่วงเวลาที่กำหนด (ดูความแตกต่างในโค้ด) เพียงแค่ไปที่ไฟล์ปัจจุบัน:

ตัวอย่าง :

git diff @{2019-01-01}..@{2019-01-02} ~/dev/myApp/package.json

2

นี่เป็นคำตอบที่ตลกกว่าเพราะมีวิธีที่ดีกว่า สิ่งนี้จะแสดงแฮชคอมมิตทั้งหมดสำหรับวันนี้

git log --pretty="format:%H %ai" | grep `date +"%Y-%m-%d"` | awk {'print $1'}`

·)


2

คุณยังสามารถใช้git-format-patchเพื่อเตรียมแพตช์ (diffs) และส่งทางอีเมล

ใช้ตัวเลือก [ตั้งแต่] หรือ [ช่วงการแก้ไข] เพื่อระบุช่วงการคอมมิต


0

ฉันจะทำในแบบที่ฉันทำ: git logสำหรับวันที่ให้คุณคอมมิตแฮชสำหรับสาขาปัจจุบัน จากนั้นฉันก็ใช้บางอย่างgit diff 8fgdfg8..565k4l5ที่ให้ความแตกต่างที่เหมาะสมที่รวบรวมโดยไฟล์ หวังว่านี่จะช่วยได้ แต่ไม่ได้ทดสอบมากนัก

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