Git
Chapters ▾ 2nd Edition

8.2 Pag-aangkop sa Sariling Pangangailagan ng Git - Mga Katangian ng Git

Mga Katangian ng Git

Ang ilan sa mga setting na ito ay maaari ding tinukoy para sa isang landas, kaya inilapat ng Git ang mga setting na iyon para lamang sa isang subdirectory o subset ng mga file. Ang mga setting na tukoy sa landas na ito ay tinatawag na mga katangian ng Git at nakatakda sa alinman sa .gitattributes na file sa isa sa mga direktoryo mo (sa kasanayan ito ay ang ugat ng iyong proyekto) o sa .git/info/attributes na file kung hindi mo gusto ang mga katangian ng file na naka-commit sa iyong proyekto.

Sa paggamit ng mga katangian, maaari mong gawin ang mga bagay tulad ng tukuyin ang mga hiwalay na estratehiya ng pagcommit para sa mga indibidwal na file o mga direktoryo sa iyong proyekto, sabihin sa Git kung paano i-diff ang mga file na di-teksto, o magkaroon ng nilalaman ng Filter ng Git bago mo itong i-check-in o i-check-out sa Git. Sa seksyon na ito, matututunan mo ang tungkol sa ilang mga katangian na maaari mong itakda sa iyong mga landas sa iyong proyektong Git at tingnan ang kakaunting mga halimbawa sa paggamit ng katangian na ito sa pagsasanay.

Mga File na Binary

Ang isang magandang paraan para sa kung saan maaari mong gamitin ang mga katangian ng Git ay ang pagsasabi sa Git na ang mga file ay binary (sa mga iilang kaso maaring hindi nito malaman) at pagbibigay ng Git ng espesyal na mga tagubilin tungkol sa kung paano pangasiwaan ang mga file na iyon For instance, some text files may be machine generated and not diffable, whereas some binary files can be diffed. Halimbawa, ang ilang mga tekstong file ay maaaring ginawa ng makina at hindi maaring i-diff, samantalang ang ilang mga binary file ay maaaring i-diff. Makikita mo kung paano sabihin sa Git na kung ano ang nararapat.

Identifying Binary Files

Ilang mga file ay parang mga file na teksto ngunit para sa lahat ng mga sadya at layunin ay dapat tratuhin bilang binary data. Halimbawa, ang proyektong Xcode sa Mac ay naglalaman ng file na nagtatapos sa .pbxproj, kung saan ay isang karaniwang JSON (naka-format sa malinaw na tekstong Javascript na data) dataset na isinulat sa disk ng IDE, kung saan ay nagrerecord sa iyong mga setting ng paggawa at iba pa. Sa totoo lang kahit na ito ay isang tekstong file (dahil ang lahat ng mga ito ay UTF-8), hindi mo nais na tratuhin ito bilang ganyan dahil ito ay talagang isang magaan na database - hindi mo maaaring pagsamahin ang mga nilalaman kung binago ito ng dalawang tao, at ang pag-diff sa pangkalahatan ay hindi rin makakatulong. Ang file ay sinadya upang maubos ng isang makina Sa kakanyahan, nais mong tratuhin ito tulad ng isang binary file.

Para sabihin sa Git na tratuhin ang lahat ng pbxproj na mga file bilang data na binary, idagdag ang mga sumusunod na linya sa iyong .gitattributes na file:

*.pbxproj binary

Sa ngayon, hindi sisikapin ng Git na palitan o ayusin ang mga isyu ng CRLF; ni hindi nito susubukang magkalkula o i-print ang isang diff para sa mga pagbabago sa file na ito kung ikaw ang magpapatakbo ng git show o git diff sa iyong proyekto.

Diffing Binary Files

Maaari mo ring gamitin ang pag-aandar ng mga katangian ng Git upang epektibong i-diff ang mga file na binary. Gawin mo ito sa pamamagitan ng pagsasabi sa Git kung paano palitan ang iyong data na binary para sa tekstong format na pwedeng ikumpara sa normal na diff.

Una, gagamitin mo ang pamamaraan na ito upang malutas ang isa sa mga pinaka nakakainis na mga problema na kilala sa sangkatauhan: pagkokontrol sa bersyon ng mga dokumentong Microsoft Word. Alam ng lahat na ang Word ay ang pinaka-kasuklam-suklam na editor, ngunit nakakatwa na ginagamit pa ng lahat ito. Kung gusto mong kontrolin ang bersyon ng mga dokumentong Word, maaari mong ilagay ang mga ito sa isang repositoryo ng Git at parati mo itong i-commit kada sandali; ngunit ano ba ang magandang ma idudulot nito? Kung patatakbuhin mo ang git diff kadalasan, makikita mo lamang ang isang bagay na katulad nito:

$ git diff
diff --git a/chapter1.docx b/chapter1.docx
index 88839c4..4afcb7c 100644
Binary files a/chapter1.docx and b/chapter1.docx differ

Hindi mo maaaring direktang ikumpara ang dalawang mga bersyon maliban kung suriin mo ang mga ito at i-scan ang mga ito nang manu-mano, tama? Sa kinalabasan maaari mong gawin ito na medyo mabuti gamit ang mga katangian ng Git. Ilagay ang sumusunod na linya sa iyong .gitattributes na file:

*.docx diff=word

Sinasabi nito sa Git na ang anumang file na tumutugma sa pattern na ito (.docx) ay dapat gamitin ang “word” na pagsasala kapag sinubukan mong tingnan ang isang diff na naglalaman ng mga pagbabago. Ano ang “word” na pagsasala? Kailangan mong itakda ito. Dito mo i-configure ang Git upang gamitin ang docx2txt na programa para palitan ang mga dokumentong Word upang gawing nababasang mga file na teksto, na kung saan ito ay i-diff ng maayos.

Una, kailangan mong i-install ang docx2txt; maari mo itong i-download sa http://docx2txt.sourceforge.net. Sundin ang mga tagubilin sa INSTALL na file upang ilagay ito sa isang lugar na kung saan maaring mahanap ng iyong shell. Susunod, magsusulat ka ng script na pambalot upang i-convert ang output sa format na inaasahan ng Git.

Lumikha ng isang file na sa isang lugar sa iyong landas na tinatawag na docx2txt, at idagdag ang mga nilalaman na ito:

#!/bin/bash
docx2txt.pl "$1" -

Huwag kalimutan na i-chmod a+x ang file na iyon. Sa katapusan, maaari mong i-kompigura ang Git upang magamit ang script na ito:

$ git config diff.word.textconv docx2txt

Alam na ngayon ng Git kung susubukang gumawa ng diff sa pagitan ng dalawang snapshot, at alinman sa mga file na nagtatapos sa .docx, dapat itong patakbuhin ang mga file sa pamamagitan ng “word” na salaan, na tinukoy bilang programa ng docx2txt. Ito ay epektibong gumagawa ng magandang bersyon ng tekstong nakabatay sa iyong Word na mga file bago sinusubukang i-diff sila.

Narito ang isang halimbawa: Kabanata 1 ng aklat na ito ay napalitan sa format ng Word at nakatuon sa isang repositoryong Git. Pagkatapos ay idinagdag ang isang bagong talata. Narito kung ano ang ipinapakita ng git diff:

$ git diff
diff --git a/chapter1.docx b/chapter1.docx
index 0b013ca..ba25db5 100644
--- a/chapter1.docx
+++ b/chapter1.docx
@@ -2,6 +2,7 @@
 Ang kabanatang ito ay tungkol sa pagsisimula sa Git. Magsisimula tayo sa simula sa pamamagitan ng pagpapaliwanag ng ilang mga background sa mga kasangkapan ng pagkontrol sa bersyon, pagkatapos ay lilipat sa kung paano makakuha ng Git na tumatakbo sa iyong sistema at sa panghuli kung paano makakuha ng setup na ito upang simulan ang pakikipagtulungan. Sa dulo ng kabanatang ito
dapat mong maintindihan kung bakit ang Git ay nandito, bakit dapat mong gamitin ito at dapat mong i-setup ang lahat upang magawa ito.
1.1. Tungkol sa Pagkontrol ng Bersyon
Ano ang "pagkontrol sa bersyon", at bakit dapat kang makialam? Ang pagkontrol sa bersyon ay isang sistema na nagtatala sa mga pagbabago sa isang file o hanay ng mga file sa paglipas ng panahon upang maaari mong iurong ang mga tiyak na mga bersyon pagkalipas.
+Testing: 1, 2, 3.
 Kung ikaw ay taga-desinyo ng graphic o ng web at gusto mong itago ang bawat bersyon ng isang imahe o ang pagkakaayos (kung saan ay tiyak na ninanais mo ito), ang Version Control System (VCS) ay isang matalinong bagay na magagamit. Pinapayagan ka nitong ibalik ang mga file pabalik sa nakaraang estado, ibalik ang buong proyekto pabalik sa nakaraan estado, ihambing ang mga pagbabago sa paglipas ng panahon, tingnan kung sino ang huling nagbago sa isang bagay na maaaring magdulot ng problema, sino ang nagpakilala ng isang isyu at kung kailan, at marami pang iba.
 Ang paggamit ng isang VCS sa pangkalahatan ay nangangahulugan na kung sira mo ang mga bagay o mawawala ang mga file, madali mo itong mabawi. Sa karagdagan, makukuha mo ang lahat ng ito para sa napakaliit na overhead.
 1.1.1. Lokal na Version Control Systems
 Karamihan ng mga tao ay pinipili ang pagkontrol ng bersyon sa pamamagitan ng pagkopya sa mga file patungo sa ibang direktoryo (marahil isang direktoryo na may nakatala na oras, kung sila ay matalino).

 Ang pamaraan na ito ay karaniwan dahil ito ay sobrang simple, ngunit ito rin ay hindi kapani-paniwalang madaling magkamali. Madaling kalimutan kung aling direktoryo ka at aksidenteng masulatan ang maling file o kopyahin ang maling mga file na hindi mo nais.

Matagumpay at maliwanag ang pagsasabi ng Git sa atin na idinagdag natin ang string na “Testing: 1, 2, 3.”, kung saan ay tama. Ito ay hindi perpekto - ang mga pagbabago sa pagformat ay hindi lumantad dito - ngunit ito ay tiyak na gumagana.

Isa pang kawili-wiling problema na maaari mong malutas sa paraan na ito ay nagsasangkot sa pag-diff ng mga file na imahe. Isang paraan sa paggamit nito ay ang pagpatakbo sa mga file na imahe sa pamamagitan ng pagsasala na nagpapalabas sa kanilang EXIF na impormasyong metadata kung saan ay nakarekord sa mga nakakaraming format ng imahe. Kung iyong i-download at i-install ang exiftool na programa, maaari mo itong gamitin upang palitan ang iyong mga imahe ng teksto tungkol sa metadata, kaya hindi bababa sa diff ang pagpapakita sa iyo ng isang tekstuwal na representasyon ng anumang mga pagbabago na nangyari. Ilagay ang sumusunod na linya sa iyong .gitattributes na file:

*.png diff=exif

I-kompigura ang Git upang magamit ang kasangkapang ito:

$ git config diff.exif.textconv exiftool

Kung iyong papalitan ang isang imahe ng iyong proyekto at patakbuhin ang git diff, makikita mo ang isang bagay na ganito:

diff --git a/image.png b/image.png
index 88839c4..4afcb7c 100644
--- a/image.png
+++ b/image.png
@@ -1,12 +1,12 @@
 ExifTool Version Number         : 7.74
-File Size                       : 70 kB
-File Modification Date/Time     : 2009:04:21 07:02:45-07:00
+File Size                       : 94 kB
+File Modification Date/Time     : 2009:04:21 07:02:43-07:00
 File Type                       : PNG
 MIME Type                       : image/png
-Image Width                     : 1058
-Image Height                    : 889
+Image Width                     : 1056
+Image Height                    : 827
 Bit Depth                       : 8
 Color Type                      : RGB with Alpha

Madali mong makikita na ang laki ng file at ang sukat ng imahe ay kapwa nagbago.

Pagpapalawak ng Keyword

SVN- or CVS- na estilo sa pagpapalawak ng keyword ay madalas na hinihiling ng mga nag-develop na ginagamit sa mga sistema na iyon. Ang pangunahing problema nito sa Git ay hindi mo maaaring baguhin ang isang file na may impormasyon tungkol sa commit pagkatapos mong na-commit, dahil ang Git ay nauna sa pag-checksums sa file.

Gayunpaman, maaari mong i-inject ng teksto sa isang file kung ito ay naka-check out at alisin ito muli bago ito idinagdag sa isang commit. Ang mga katangian ng Git ay nag-aalok sa iyo ng dalawang paraan upang magawa ito.

Una, maaari mong awtomatikong i-inject ang SHA-1 na checksum ng isang blob sa isang $Id$ na field sa file. Kung itinakda mo ang katangiang ito sa isang file o hanay ng mga file, pagkatapos sa susunod na i-check out mo ang branch na iyon, papalitan ng Git ang field na iyon kasama ang SHA-1 na blob.

Mahalagang mapansin na hindi ito ang SHA-1 ng commit, kundi ng mismong blob. Ilagay ang sumusunod na linya sa iyong .gitattributes na file:

*.txt ident

Magdagdag ng isang $Id$ na sanggunian sa isang file na pagsusulit:

$ echo '$Id$' > test.txt

Sa susunod na i-check out mo ang file na ito, ang Git ay mag-inject ng SHA-1 ng blob:

$ rm test.txt
$ git checkout -- test.txt
$ cat test.txt
$Id: 42812b7653c7b88933f8a9d6cad0ca16714b9bb3 $

Gayunpaman, ang resulta ay limitado ang paggamit. Kung ginamit mo ang pagpapalit ng keyword sa CVS o Subversion, maaari mong isama ang isang datestamp - ang SHA-1 ay hindi masyadong kapaki-pakinabang, dahil medyo alisaga ito at hindi mo masabi kung ang isang SHA-1 ay mas matanda o mas bago kaysa sa iba pa sa pamamagitan lamang ng pagtingin sa mga ito.

Iyon pala ay maari kang magsulat ng sarili mong mga pagsala para sa paggawa ng mga pamalit sa mga file sa commit/checkout. Ang mga ito ay tinatawag na “clean” at “smudge” na mga pagsala. Ang sa .gitattributes na file, maaari kang magtakda ng pagsasala para sa mga partikular na landas at pagkatapos ay i-set up ang mga script na magpoproseso ng mga file bago pa man sila i-check out (“smudge”, tingnan Ang “smudge” ang pagsala ay pinapatakbo sa checkout.) at bago pa man ang mga ito ay i-stage (“clean”, tingnan Ang “clean” na pagsasala ay pinapatakbo kung ang mga file ay naka-stage.). Ang mga pagsala na ito ay maaaring itakda upang gawin ang lahat ng uri ng mga bagay na masaya.

Ang ``smudge'' na pagsasala ay pinapatakbo sa checkout.
Figure 144. Ang “smudge” ang pagsala ay pinapatakbo sa checkout.
Ang ``clean'' na pagsasala ay pinapatakbo kung ang mga file ay naka-stage.
Figure 145. Ang “clean” na pagsasala ay pinapatakbo kung ang mga file ay naka-stage.

Ang orihinal na mensahe ng commit para sa katangian na ito ay nagbibigay ng isang simpleng halimbawa ng pagpapatakbo ng lahat ng iyong source code sa C sa pamamagitan ng indent na programa bago i-commit. Maaari mo itong i-set up sa pamamagitan ng pagtatakda ng pagsasala na katangian sa iyong .gitattributes na file hanggang sa *.c na mga file kasama na ang “indent” na pagsala:

*.c filter=indent

Pagkatapos, sabihin sa Git kung ano ang ginagawa ng pagsasala na “indent” sa smudge at clean:

$ git config --global filter.indent.clean indent
$ git config --global filter.indent.smudge cat

Sa kasong ito, kapag nag-commit ka ng mga file na tumutugma sa *.c, ang Git ay tatakbo sa mga ito sa pamamagitan ng indent na programa bago ito i-stage nila at pagkatapos patakbuhin ang mga ito sa programa ng cat bago suriin ang mga ito pabalik sa disk. Ang cat na programa ay talagang walang magawa: iniluwa palabas nito ang parehong data na pinasok dito. Ang kumbinasyon na ito ay epektibong sinasala ang lahat ng mga file ng source code sa C indent bago ito i-commit.

Ang isa pang kawili-wiling halimbawa ay nakakuha ng pagpapalawak ng keyword na $Date$, estilo ng RCS. Upang gawin ito ng maayos, kailangan mo ng script na tumatagal sa filename, alamin ang huling petsa ng pag-commit para sa proyektong ito, at isingit ang petsa sa file. Narito ang Ruby script na ginagawa niyan:

#! /usr/bin/env ruby
data = STDIN.read
last_date = `git log --pretty=format:"%ad" -1`
puts data.gsub('$Date$', '$Date: ' + last_date.to_s + '$')

Ang lahat ng script ay makakakuha ng pinakabagong petsa ng pag-commit mula sa git log na utos, idikit sa anumang $Date$ na mga string na nakikita sa stdin, at i-print ang mga resulta - ito ay dapat madaling gawin sa anumang language na ikaw ay pinaka-komportable. Maaari mong pangalanan ang file na ito expand_date at ilagay ito sa iyong path. Sa ngayon, kailangan mong mag-set up ng isang filter sa Git (tawagin mo dater) at sabihin ito upang gamitin ang iyong expand_date na filter sa smudge ng mga file sa checkout. Gagamitin mo ang Perl expression upang linisin ito sa commit:

$ git config filter.dater.smudge expand_date
$ git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'

Ang Perl snippet ay nagtatanggal ng anumang nakikita nito sa $Date$ string, upang makabalik kung saan ka nagsimula. Ngayon na handa na ang iyong filter, maaari mong subukan ito sa pamamagitan ng pagse-set up ng isang katangian ng Git para sa file na nakikipag-ugnayan sa bagong filter at paglikha ng isang file sa iyong $Date$ na keyword

date*.txt filter=dater
$ echo '# $Date$' > date_test.txt

Kung nag-commit ka ng mga pagbabago at tingnan mo muli ang file, nakikita mo ang keyword na maayos na pinalitan:

$ git add date_test.txt .gitattributes
$ git commit -m "Testing date expansion in Git"
$ rm date_test.txt
$ git checkout date_test.txt
$ cat date_test.txt
# $Date: Tue Apr 21 07:26:52 2009 -0700$

Makikita mo kung gaano kabisa ang pamamaraan na ito para sa mga na-customize na aplikasyon. Dapat kang mag-ingat, bagaman, dahil sa .gitattributes file ay nag-commit at naipasa sa proyekto, pero ang driver (sa kasong ito, dater) ay hindi, kaya hindi ito gagana saan man. Kapag dinisenyo mo ang mga filter na ito, dapat silang mabigo ng buong-husay at ayusin pa rin ang proyekto.

Pag-e-export ng Iyong Repository

Ang Git ng katangian ng data ay hinahayaan ka na gawin ang ilang mga kagiliw-giliw na bagay kapag nag-export ng isang archive ng iyong proyekto.

export-ignore

Maaari mong sabihin sa Git na huwag i-export ang ilang mga file o mga direktoryo kapag bumubuo ng isang archive. Kung mayroong isang subdirectory o file na hindi mo gustong isama sa iyong file ng archive ngunit nais mong i-tsek sa iyong proyekto, maaari mong matukoy ang mga file na iyon sa pamamagitan ng katangian ng export-ignore.

Halimbawa, sabihin nating mayroon kang ilang mga test file sa test/ subdirectory, at hindi ito makatwiran upang isama ang mga ito sa pag-export ng tarball ng iyong proyekto. Maaari mong idagdag ang sumusunod na linya sa iyong mga file na katangian ng Git:

test/ export-ignore

Sa ngayon, kapag nagpatakbo ka ng git archive upang lumikha ng isang tarball ng iyong proyekto, ang direktoryo na iyon ay hindi isasama sa archive.

export-subst

Kapag nag-export ng mga file para sa pag-deploy maaari mong gamitin ang it git log sa pag-format at pagpapalawak ng keyword-expansion ng mga napiling bahagi ng mga file na minarkahan ng katangian ng export-subst.

Halimbawa, kung gusto mong isama ang isang file na pinangalanang LAST_COMMIT sa iyong proyekto, at may metadata tungkol sa huling nag-commit awtomatikong na-inject ito kapag ang git archive ay tumatakbo, kaya mo tulad ng halimbawang i-set up ang iyong mga .gitattributes at LAST_COMMIT na mga file tulad nito:

LAST_COMMIT export-subst
$ echo 'Last commit date: $Format:%cd by %aN$' > LAST_COMMIT
$ git add LAST_COMMIT .gitattributes
$ git commit -am 'adding LAST_COMMIT file for archives'

Kapag nagpatakbo ka ng git archive, ang mga nilalaman ng naka-archive na file ay magiging ganito:

$ git archive HEAD | tar xCf ../deployment-testing -
$ cat ../deployment-testing/LAST_COMMIT
Last commit date: Tue Apr 21 08:38:48 2009 -0700 by Scott Chacon

Maaaring isama sa mga pamalit na halimbawa ang na i-commit na mensahe at anumang git notes, at git log ay maaaring gumawa ng simpleng word wrapping:

$ echo '$Format:Last commit: %h by %aN at %cd%n%+w(76,6,9)%B$' > LAST_COMMIT
$ git commit -am 'export-subst uses git log'\''s custom formatter

git archive uses git log'\''s `pretty=format:` processor
directly, and strips the surrounding `$Format:` and `$`
markup from the output.
'
$ git archive @ | tar xfO - LAST_COMMIT
Last commit: 312ccc8 by Jim Hill at Fri May 8 09:14:04 2015 -0700
       export-subst uses git log's custom formatter

         git archive uses git log's `pretty=format:` processor directly, and
         strips the surrounding `$Format:` and `$` markup from the output.

Ang resultang archive ay angkop para sa pag-deploy ng trabaho, ngunit tulad ng anumang na-export na archive na ito ay hindi angkop para sa karagdagang pag-unlad ng trabaho.

Pagsamahin ang mga Istratehiya

Maaari mo ring gamitin ang mga katangian ng Git upang sabihin sa Git na gumamit ng iba’t ibang mga istratehiya sa pagsasama para sa mga partikular na file sa iyong proyekto. Ang isa sa kapaki-pakinabang na pagpipilian ay ang sabihin sa Git na huwag subukan na pagsamahin ang mga tiyak na file kapag mayroon silang mga salungatan, ngunit sa halip na gamitin ang iyong bahagi ng pagsasama sa ibang tao.

Ito ay kapaki-pakinabang kung ang isang branch sa iyong proyekto ay diverged o dalubhasa, ngunit nais mong ma-merge ang mga pagbabago sa likod mula dito, at nais mong huwag pansinin ang ilang mga file. Sabihing mayroon kang database settings file na tinatawag na database.xml na iba sa dalawang mga branch, at nais mong pagsamahin Maaari kang mag-set up ng isang katangian tulad nito:

database.xml merge=ours

At pagkatapos ay tukuyin ang isang istratehiya ng dummy ours na may:

$ git config --global merge.ours.driver true

Kung pinagsama mo ang ibang branch, sa halip na pagsamahin ang mga salungatan sa database.xml file, nakakita ka ng ganito:

$ git merge topic
Auto-merging database.xml
Merge made by recursive.

Sa kasong ito, ang database.xml mananatili sa anumang bersyon sa dati.

scroll-to-top