ฉันกำลังพยายามทำของแฟนซีที่นี่ด้วย Git hooks แต่ฉันไม่รู้ว่าจะทำอย่างไร (หรือถ้าเป็นไปได้)
สิ่งที่ฉันต้องทำคือ: ในการคอมมิตทุกครั้งฉันต้องการแฮชของมันแล้วอัปเดตไฟล์ในคอมมิตด้วยแฮชนี้
ความคิดใด ๆ ?
ฉันกำลังพยายามทำของแฟนซีที่นี่ด้วย Git hooks แต่ฉันไม่รู้ว่าจะทำอย่างไร (หรือถ้าเป็นไปได้)
สิ่งที่ฉันต้องทำคือ: ในการคอมมิตทุกครั้งฉันต้องการแฮชของมันแล้วอัปเดตไฟล์ในคอมมิตด้วยแฮชนี้
ความคิดใด ๆ ?
คำตอบ:
ฉันขอแนะนำให้ทำสิ่งที่คล้ายกับสิ่งที่คุณคิดไว้: การวาง SHA1 ในไฟล์ที่ไม่มีการติดตามซึ่งสร้างขึ้นเป็นส่วนหนึ่งของกระบวนการสร้าง / การติดตั้ง / การปรับใช้ เห็นได้ชัดว่าทำได้ง่าย ( git rev-parse HEAD > filename
หรืออาจgit describe [--tags] > filename
) และหลีกเลี่ยงการทำอะไรที่บ้าคลั่งเช่นจบลงด้วยไฟล์ที่แตกต่างจากการติดตามของคอมไพล์
จากนั้นรหัสของคุณสามารถอ้างอิงไฟล์นี้เมื่อต้องการหมายเลขเวอร์ชันหรือกระบวนการสร้างอาจรวมข้อมูลไว้ในผลิตภัณฑ์ขั้นสุดท้าย อันหลังนี้เป็นวิธีที่ git รับหมายเลขเวอร์ชันของมันเอง - กระบวนการสร้างจะดึงหมายเลขเวอร์ชันออกจาก repo จากนั้นสร้างเป็นไฟล์ปฏิบัติการ
เป็นไปไม่ได้ที่จะเขียนแฮชคอมมิตปัจจุบัน: หากคุณจัดการคำนวณแฮชคอมมิตในอนาคตล่วงหน้า - มันจะเปลี่ยนทันทีที่คุณแก้ไขไฟล์ใด ๆ
อย่างไรก็ตามมีสามตัวเลือก:
pre-commit
จัดเก็บแฮชคอมมิตก่อนหน้านี้ :) คุณไม่ได้แก้ไข / แทรกคอมมิตในกรณี 99.99% ดังนั้นสิ่งนี้จะได้ผล ในกรณีที่แย่ที่สุดคุณยังสามารถระบุการแก้ไขแหล่งที่มาได้ฉันกำลังทำงานกับสคริปต์เบ็ดจะโพสต์ไว้ที่นี่ 'เมื่อมันเสร็จสิ้น' แต่ก็ยัง - เร็วกว่าที่ Duke Nukem Forever จะออก :))
ปรับปรุง : รหัสสำหรับ.git/hooks/pre-commit
:
#!/usr/bin/env bash
set -e
#=== 'prev-commit' solution by o_O Tync
#commit_hash=$(git rev-parse --verify HEAD)
commit=$(git log -1 --pretty="%H%n%ci") # hash \n date
commit_hash=$(echo "$commit" | head -1)
commit_date=$(echo "$commit" | head -2 | tail -1) # 2010-12-28 05:16:23 +0300
branch_name=$(git symbolic-ref -q HEAD) # http://stackoverflow.com/questions/1593051/#1593487
branch_name=${branch_name##refs/heads/}
branch_name=${branch_name:-HEAD} # 'HEAD' indicates detached HEAD situation
# Write it
echo -e "prev_commit='$commit_hash'\ndate='$commit_date'\nbranch='$branch'\n" > gitcommit.py
ตอนนี้สิ่งเดียวที่เราต้องการคือเครื่องมือที่แปลงprev_commit,branch
คู่เป็นแฮชคอมมิตจริง :)
ฉันไม่รู้ว่าวิธีนี้สามารถบอกการรวมคอมมิตออกจากกัน จะตรวจสอบเร็ว ๆ นี้
มีคนชี้ให้ฉันไปที่ส่วน "man gitattributes" ใน ident ซึ่งมีสิ่งนี้:
ident
เมื่อแอตทริบิวต์ระบุถูกตั้งค่าสำหรับเส้นทาง git จะแทนที่ $ Id $ ในวัตถุ blob ด้วย $ Id: ตามด้วยชื่อวัตถุหยดเลขฐานสิบหก 40 อักขระตามด้วยเครื่องหมายดอลลาร์ $ เมื่อชำระเงิน ลำดับไบต์ใด ๆ ที่ขึ้นต้นด้วย $ Id: และลงท้ายด้วย $ ในไฟล์ worktree จะถูกแทนที่ด้วย $ Id $ เมื่อเช็คอิน
ถ้าคุณลองคิดดูนี่คือสิ่งที่ CVS การโค่นล้มและอื่น ๆ ทำได้เช่นกัน หากคุณดูที่เก็บคุณจะเห็นว่าไฟล์ในที่เก็บนั้นมีอยู่เสมอตัวอย่างเช่น $ Id $ มันไม่เคยมีส่วนขยายของสิ่งนั้น เฉพาะในขั้นตอนการชำระเงินที่ขยายข้อความ
ident
คือแฮชสำหรับไฟล์นั้นเองไม่ใช่แฮชของคอมมิต จากgit-scm.com/book/en/… : "อย่างไรก็ตามผลลัพธ์นั้นใช้งานได้ จำกัด หากคุณเคยใช้การทดแทนคีย์เวิร์ดใน CVS หรือ Subversion คุณสามารถใส่ datestamp - SHA ไม่ได้มีประโยชน์ทั้งหมด เพราะมันค่อนข้างสุ่มและคุณไม่สามารถบอกได้ว่า SHA อันหนึ่งเก่าหรือใหม่กว่าอีกอันหนึ่ง " filter
ใช้งานได้ แต่สามารถรับข้อมูลการคอมมิตเข้า (และออกจาก) ไฟล์ได้
นี้สามารถทำได้โดยใช้filter
แอตทริบิวต์ในgitattributes คุณต้องระบุsmudge
คำสั่งที่แทรกรหัสคอมมิตและไฟล์clean
คำสั่งที่ลบมันออกไปเพื่อให้ไฟล์ที่ใส่เข้าไปจะไม่เปลี่ยนแปลงเพียงเพราะรหัสคอมมิต
ดังนั้นรหัสการคอมมิตจะไม่ถูกเก็บไว้ในหยดของไฟล์ เพียงแค่ขยายในสำเนาการทำงานของคุณ (จริงๆแล้วการใส่รหัสคอมมิตลงในหยดจะกลายเป็นงานวนซ้ำไม่สิ้นสุด☺) ใครก็ตามที่โคลนนิ่งต้นไม้นี้จะต้องตั้งค่าคุณสมบัติให้ตัวเอง
คิดนอกกรอบการกระทำ!
เปิดสิ่งนี้ลงใน file hooks / post-checkout
#!/bin/sh
git describe --all --long > config/git-commit-version.txt
เวอร์ชันนี้จะพร้อมใช้งานทุกที่ที่คุณใช้งาน
ฉันไม่คิดว่าคุณต้องการทำเช่นนั้นจริง ๆ เพราะเมื่อไฟล์ในคอมมิตถูกเปลี่ยนแฮชของคอมมิตก็เปลี่ยนไปด้วย
ให้ฉันสำรวจว่าเหตุใดปัญหานี้จึงเป็นปัญหาที่ท้าทายโดยใช้ git internalals คุณสามารถรับ sha1 ของการกระทำปัจจุบันโดย
#!/bin/bash
commit=$(git cat-file commit HEAD) #
sha1=($((printf "commit %s\0" $(echo "$commit" | wc -c); echo "$commit") | sha1sum))
echo ${sha1[0]}
โดยเฉพาะอย่างยิ่งคุณเรียกใช้การตรวจสอบ sha1 git cat-file commit HEAD
ข้อความที่ส่งกลับโดย มีสองสิ่งที่จะกลายเป็นปัญหาทันทีเมื่อคุณตรวจสอบข้อความนี้ หนึ่งคือต้นไม้ sha1 และที่สองคือเวลากระทำ
ตอนนี้เวลาในการคอมมิตนั้นได้รับการดูแลอย่างง่ายดายโดยการแก้ไขข้อความและคาดเดาว่าจะต้องใช้เวลาในการคอมมิตหรือกำหนดเวลาในการคอมมิตนานแค่ไหน ปัญหาที่แท้จริงคือ sha1 git ls-tree $(git write-tree) | git mktree
ต้นไม้ที่คุณจะได้รับจาก โดยพื้นฐานแล้วคุณกำลังทำการตรวจสอบ sha1 บนข้อความจาก ls-tree ซึ่งเป็นรายการไฟล์ทั้งหมดและการตรวจสอบ sha1
ดังนั้นการตรวจสอบ sha1 ของคุณจึงขึ้นอยู่กับการตรวจสอบ sha1 ต้นไม้ของคุณซึ่งขึ้นอยู่กับไฟล์ sha1 checksum โดยตรงซึ่งทำให้วงกลมเสร็จสมบูรณ์และขึ้นอยู่กับการกระทำ sha1 ดังนั้นคุณจึงมีปัญหาแบบวงกลมกับเทคนิคที่มีให้กับตัวเอง
ด้วยการตรวจสอบที่มีความปลอดภัยน้อยแสดงให้เห็นว่าสามารถเขียนเช็คซัมของไฟล์ลงในไฟล์ได้โดยใช้กำลังดุร้าย อย่างไรก็ตามฉันไม่รู้ว่ามีงานใดที่ทำให้งานนั้นสำเร็จด้วย sha1 นี่ไม่ใช่เรื่องที่เป็นไปไม่ได้ แต่ถัดจากความเข้าใจในปัจจุบันของเราไปไม่ได้ (แต่ใครจะรู้ว่าในอีกไม่กี่ปีข้างหน้ามันจะเป็นเรื่องเล็กน้อย) อย่างไรก็ตามสิ่งนี้ยังยากกว่าที่จะ brute Force เนื่องจากคุณต้องเขียน (กระทำ) การตรวจสอบ (ต้นไม้) การตรวจสอบ (ต้นไม้) ของการตรวจสอบ (หยด) ลงในไฟล์