Git
Chapters ▾ 2nd Edition

8.2 Git’i Fərdiləşdirmək - Git Atributları

Git Atributları

Bu parametrlərdən bəziləri bir path üçün də göstərilə bilər, belə ki Git bu parametrləri yalnız bir subdirectory və ya bir fayl dəsti üçün tətbiq edir. Bu path-a xas olan parametrlərə Git atributları deyilir və ya dizinlərinizdən birindəki .gitattributes sənədində (normal olaraq layihənizin root-u) və ya .git/info/attributes faylında quraşdırılır. Layihənizlə əlaqəli xüsusiyyətlər sənədini istəyin.

Atributlardan istifadə edərək layihənizdə ayrı-ayrı fayllar və ya qovluqlar üçün ayrı birləşmə strategiyaları müəyyənləşdirmək, Git-ə mətndən kənar faylları necə fərqləndirəcəyini söyləmək və ya Git-ə daxil olub-çıxmadan əvvəl Git filtri məzmununa sahib olmaq kimi şeylər edə bilərsiniz. Bu bölmədə Git layihənizdə yollarınıza qura biləcəyiniz bəzi xüsusiyyətlər haqqında məlumat əldə edəcək və bu xüsusiyyətdən praktikada istifadə etmək üçün bir neçə nümunə əldə edə bilərsiniz.

Binary Fayllar

Git atributlarından istifadə edə biləcəyiniz yaxşı fəndlərdən biri, Git-ə hansı faylların binary olduğunu söyləmək (əks halda bunu başa düşməyə bilər) və Git-ə bu sənədləri necə idarə etməsi barədə xüsusi təlimatlar verməkdir. Məsələn, bəzi mətn faylları maşın şəklində yaradıla bilər və fərqlilik göstərməyə bilər, bəzi binary fayllar isə fərqli ola bilər. Git-ə hansının necə olduğunu necə izah edəcəyini görəcəksiz.

Binary Faylların Müəyyənləşdirilməsi

Bəzi fayllar mətn fayllarına bənzəyir, lakin bütün məqsədlər üçün binary məlumat kimi qəbul edilməlidir. Məsələn, macOS-dakı Xcode layihələri, .pbxproj ilə bitən, əsasən IDE tərəfindən diskə yazılmış bir JSON (düz mətnli JavaScript məlumat formatı) verilənlər bazası olan bir sənəd ehtiva edir və s. Texniki cəhətdən bir mətn faylı olmasına baxmayaraq (hamısı UTF-8 olduğu üçün), həqiqətən lightweight bir verilənlər bazası olduğu üçün bu şəkildə davranmaq istəmirsiniz - iki nəfər dəyişsə məzmunu birləşdirə bilməzsiniz və fərqlər ümumiyyətlə faydalı deyil. Fayl bir maşın tərəfindən istehlak edilməlidir. Əslində, binary bir fayl kimi davranmaq istəyirsiz. Git-ə bütün pbxproj fayllarını binary məlumatlar kimi qəbul etməsini söyləmək üçün .gitattributes faylınıza aşağıdakı sətri əlavə edin:

*.pbxproj binary

İndi Git, CRLF problemlərini çevirməyə və ya düzəltməyə çalışmayacaq; proyektinizdə git show və ya git diff işlətdiyiniz zaman bu fayldakı dəyişikliklər üçün bir fərqi hesablamağa və ya çap etməyə çalışmayacaq.

Binary Faylları Fərqləndirmək

Binary faylları effektiv şəkildə ayırmaq üçün Git atributları funksiyasından da istifadə edə bilərsiniz. Bunu Git-ə binary məlumatlarınızı normal fərq ilə müqayisə edilə bilən bir mətn formatına necə çevirəcəyinizi söyləyərək edirsiniz.

Birincisi, bu texnikanı insana məlum olan ən əsəbi problemlərdən birini həll etmək üçün istifadə edəcəksiniz: Microsoft Word sənədlərinin versiyaya nəzarəti. Hər kəs Word-un ətrafındakı ən qorxunc redaktor olduğunu bilir, amma qəribədir ki, hər kəs hələ də onu istifadə edir. Word sənədlərini versiya ilə idarə etmək istəyirsinizsə, onları Git deposuna saxlaya və bir dəfəyə edə bilərsiniz; bəs bunun nə faydası var? Normal olaraq git diff işlədirsinizsə, yalnız belə bir şey görürsünüz:

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

Əgər yoxlamamısınız və manual olaraq skan etməmisinizsə, iki versiyanı birbaşa müqayisə edə bilməzsiniz, düzdür? Bunu Git atributlarından istifadə edərək kifayət qədər yaxşı edə biləcəyiniz ortaya çıxdı. Aşağıdakı sətri .gitattributes faylınıza əlavə edin:

*.docx diff=word

Bu, Git-ə, bu pattern ilə (.docx) uyğun gələn hər hansı bir faylın dəyişiklikləri ehtiva edən bir fərqə baxmağa çalışdığınız zaman “word” filterindən istifadə etməsi lazım olduğunu bildirir. “word” filteri nədir? Siz bunu qurmalısınız. Burada Git’i Word sənədlərini oxunaqlı mətn sənədlərinə çevirmək üçün docx2txt proqramından istifadə etmək üçün konfiqurasiya edəcəksiniz, daha sonra düzgün şəkildə fərqlənəcəkdir.

Əvvəlcə docx2txt yükləməlisiniz; https://sourceforge.net/projects/docx2txt saytından yükləyə bilərsiniz. Shell-nizin tapa biləcəyi bir yerə qoymaq üçün INSTALL faylındakı təlimatları izləyin. Sonra çıxışı Git-in gözlədiyi formata çevirmək üçün bir wrapper skript yazacaqsınız. Yolunuzda bir yerdə docx2txt adlı bir sənəd yaradın və bu məzmunu əlavə edin:

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

Bu faylı chmod a+x etməyi unutmayın. Nəhayət, Git’i bu skriptdən istifadə etmək üçün konfiqurasiya edə bilərsiniz:

$ git config diff.word.textconv docx2txt

İndi Git bilir ki, iki snapshot arasında bir fərq yaratmağa çalışarsa və hər hansı bir sənəd .docx ilə bitərsə, bu sənədləri docx2txt proqramı olaraq təyin olunan “word” filterindən keçirməlidir. Bu, onları fərqləndirməyə çalışmadan əvvəl Word sənədlərinizin gözəl mətn əsaslı versiyalarını effektiv şəkildə hazırlayır.

Nümunə: Bu kitabın 1-ci fəsli Word formatına çevrildi və Git deposunda hazırlandı. Sonra yeni bir abzas əlavə edildi. git diff nəyi göstərdiyinə baxaq:

$ git diff
diff --git a/chapter1.docx b/chapter1.docx
index 0b013ca..ba25db5 100644
--- a/chapter1.docx
+++ b/chapter1.docx
@@ -2,6 +2,7 @@
 This chapter will be about getting started with Git. We will begin at the beginning by explaining some background on version control tools, then move on to how to get Git running on your system and finally how to get it setup to start working with. At the end of this chapter you should understand why Git is around, why you should use it and you should be all setup to do so.
 1.1. About Version Control
 What is "version control", and why should you care? Version control is a system that records changes to a file or set of files over time so that you can recall specific versions later. For the examples in this book you will use software source code as the files being version controlled, though in reality you can do this with nearly any type of file on a computer.
+Testing: 1, 2, 3.
 If you are a graphic or web designer and want to keep every version of an image or layout (which you would most certainly want to), a Version Control System (VCS) is a very wise thing to use. It allows you to revert files back to a previous state, revert the entire project back to a previous state, compare changes over time, see who last modified something that might be causing a problem, who introduced an issue and when, and more. Using a VCS also generally means that if you screw things up or lose files, you can easily recover. In addition, you get all this for very little overhead.
 1.1.1. Local Version Control Systems
 Many people's version-control method of choice is to copy files into another directory (perhaps a time-stamped directory, if they're clever). This approach is very common because it is so simple, but it is also incredibly error prone. It is easy to forget which directory you're in and accidentally write to the wrong file or copy over files you don't mean to.

Git uğurla və qısaca olaraq bizə “Testing: 1, 2, 3.” string-i əlavə etdiyimizi söyləyir, bu düzgündür. Bu təbii ki mükəmməl deyil — formatlaşdırma dəyişiklikləri burada görünməyəcək - amma əlbəttə ki, işləyir.

Bu şəkildə həll edə biləcəyiniz bir başqa maraqlı problem, şəkil sənədlərinin diffing edilməsidir. Bunu etmək üçün bir üsul, şəkil sənədlərini EXIF məlumatlarını çıxaran bir filtrdən keçirməkdir - əksər şəkil formatları ilə qeyd olunan metadata. exiftool proqramını yüklədiyiniz və yüklədiyiniz təqdirdə, şəkillərinizi metadata aid mətnə çevirmək üçün istifadə edə bilərsiniz, beləliklə ən azı fərq sizə baş verən bütün dəyişikliklərin mətn şəklində göstərilməsini göstərəcəkdir. Aşağıdakı sətri .gitattributes faylınıza qoyun:

*.png diff=exif

Bu aləti istifadə etmək üçün Git’i konfiqurasiya edin:

$ git config diff.exif.textconv exiftool

Layihənizdəki bir şəkli əvəz edib git diff işlədirsinizsə, belə bir şey görürsünüz:

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

Fayl ölçüsünün və şəkil ölçülərinin hər ikisinin dəyişdiyini asanlıqla görə bilərsiniz.

Keyword Expansion

SVN və ya CVS üslubunda keyword genişləndirilməsi çox vaxt bu sistemlərdə istifadə olunan developerlər tərəfindən tələb olunur. Git-də bunun əsas problemi, commit etdikdən sonra commit barədə məlumatı olan bir faylı dəyişdirə bilməməyinizdir, çünki Git əvvəlcə bu faylı yoxlayır. Bununla birlikdə, mətni yoxlandıqda bir fayla daxil edə və commit-ə əlavə olunmadan yenidən silə bilərsiniz. Git atributları sizə bunun üçün iki yol təklif edir.

Əvvəlcə, bir blobun SHA-1 hesablama məbləğini avtomatik olaraq fayldakı $Id$ sahəsinə daxil edə bilərsiniz. Bu xüsusiyyəti bir faylda və ya fayl dəstində qursanız, bu branch-ı növbəti dəfə yoxladığınız zaman Git bu sahəni blokun SHA-1 ilə əvəz edəcəkdir. Commit-in SHA-1-nin deyil, blob-un özünün olduğuna diqqət yetirmək vacibdir. Aşağıdakı sətri .gitattributes faylınıza qoyun:

*.txt ident

Bir test sənədinə $Id$ referansına əlavə edin:

$ echo '$Id$' > test.txt

Növbəti dəfə bu fayla baxanda Git blobun SHA-1-ini vurur:

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

Ancaq bu nəticə məhdud istifadə üçündür. CVS-də və ya Subversion-da keyword əvəzetməsindən istifadə etmisinizsə, bir məlumat datestamp əlavə edə bilərsiniz - SHA-1 o qədər də faydalı deyil, çünki kifayət qədər təsadüfi və yalnız onlara baxmaqla bir SHA-1-in digərindən daha yaşlı və ya daha yeni olduğunu deyə bilməzsiniz.

commit/checkout fayllarında dəyişiklik etmək üçün öz filtrlərinizi yaza biləcəyiniz ortaya çıxdı. Bunlara “clean” və “smudge” filtrləri deyilir.

.gitattributes faylında, müəyyən yollar üçün bir filtr qura və sonra sənədləri yoxlanılmadan dərhal əvvəl işləyəcək skriptlər qura bilərsiniz (“smudge”, bax “smudge” filtri checkout zamanı işləyir) və bunlardan bir az əvvəl. səhnələşdirilmişdir (“clean”, bax Fayllar səhnələşdirildikdə “clean” filtr işə salınır). Bu filtrlər hər cür əyləncəli şeylər etmək üçün qurula bilər.

``smudge'' filtri checkout zamanı işləyir
Figure 144. “smudge” filtri checkout zamanı işləyir
Fayllar səhnələşdirildikdə ``clean'' filtr işə salınır
Figure 145. Fayllar səhnələşdirildikdə “clean” filtr işə salınır

Bu xüsusiyyət üçün orijinal commit mesajı, bütün C qaynaq kodunuzu işləmədən əvvəl indent proqramı vasitəsilə işlədən sadə bir nümunə verir. Bunu .gitattributes faylında *.c fayllarını “indent” filtri ilə filtrləmək üçün filtr atributunu quraraq edə bilərsiniz:

*.c filter=indent

Sonra Git-ə “indent” filtrinin ləkə və təmizləmədə nə etdiyini söyləyin:

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

Bu vəziyyətdə, *.c-yə uyğun fayllar işlədiyiniz zaman Git onları mərhələləndirmədən əvvəl indent proqramı vasitəsilə işə salacaq və onları diskə qaytarmadan əvvəl cat proqramı vasitəsilə işə salacaqdır. cat proqramı əslində heç bir şey etmir: daxil olduğu məlumatları verir. Bu birləşmə bütün C mənbə kodu fayllarını committing etmədən əvvəl indent ilə effektiv şəkildə filtrləyir.

Digər maraqlı bir nümunə RCS stili olan $Date$ keyword expansion alır. Bunu düzgün şəkildə yerinə yetirmək üçün bir fayl adı götürən, bu layihə üçün son commit tarixini müəyyənləşdirən və tarixi fayla əlavə edən kiçik bir skriptə ehtiyacınız var. Bunu edən kiçik bir Ruby skriptidir:

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

Bütün skriptlər git log əmrindən ən son commit tarixini almaq, stdin-də gördüyü hər hansı bir $Date$ sətrinə yapışdırmaq və nəticələri yazdırmaqdır - istədiyiniz dildə etmək sadə olmalıdır. ən rahat. Bu fayla expand_date adını verib path-nıza qoya bilərsiniz. İndi Git-də bir filtr qurmalısınız (onu dater adlandırın) və kassadakı sənədləri ləkələmək üçün expand_date filtrinizi istifadə etməsini söyləməlisiniz. Bunu başa çatdırmaq üçün Perl ifadəsini istifadə edəcəksiniz:

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

Bu Perl snippet-i başladığınız yerə qayıtmaq üçün bir $Date$ sətrində gördüyü hər şeyi silir. Artıq filtriniz hazır olduqda yeni filtrlə əlaqəli bir fayl üçün bir Git atributu quraraq və $Date$ keyword ilə bir fayl yaradaraq test edə bilərsiniz:

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

Bu dəyişiklikləri edib yenidən faylı yoxlayırsınızsa, keyword düzgün şəkildə əvəzləndiyini görürsünüz:

$ git add date_test.txt .gitattributes
$ git commit -m "Test 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$

Bu texnikanın xüsusi tətbiqetmələr üçün nə qədər güclü ola biləcəyini görə bilərsiniz. Diqqətli olmalısınız, çünki .gitattributes faylları layihə ilə əlaqələndirilir və ötürülür, lakin driver (bu halda dater) belə deyil, buna görə də hər yerdə işləməyəcəkdir. Bu filtrləri hazırladığınız zaman, onlar problemsiz bir şəkildə uğursuz olmalı və layihənin hələ də düzgün işləməsini təmin etməlidirlər.

Deponuzu İxrac Edin

Git atribut məlumatlarıl ayihənizin bir arxivini ixrac edərkən bəzi maraqlı şeylər etməyə imkan verir.

export-ignore

Arxiv yaradan zaman Git-ə müəyyən faylları və ya qovluqları ixrac etməməsini deyə bilərsiniz. Arxiv sənədinizə daxil etmək istəmədiyiniz, ancaq layihənizə baxılmasını istədiyiniz bir subdirectory və ya bir sənəd varsa, bu faylları export-ignore atributu ilə təyin edə bilərsiniz.

Məsələn, bir test/ subdirectory-da bəzi test sənədləriniz olduğunu və bunları layihənizin tarball ixracatına daxil etməyin mənasız olduğunu söyləyin. Git atributları sənədinizə aşağıdakı sətri əlavə edə bilərsiniz:

test/ export-ignore

İndi layihənizin bir tarball-unu yaratmaq üçün git archive işə saldığınız zaman, bu qovluq arxivə daxil edilməyəcəkdir.

export-subst

Deployment üçün faylları ixrac edərkən, export-subst atributu ilə işarələnmiş seçilmiş fayl hissələrinə git log formatlaşdırma və keyword-expansion işləmə tətbiq edə bilərsiniz.

Məsələn, layihənizə LAST_COMMIT adlı bir sənəd əlavə etmək və git archive işə salındıqda avtomatik olaraq ona enjekte edilmiş son commit barədə metadata sahib olmaq istəyirsinizsə, məsələn, .gitattributes and LAST_COMMIT qura bilərsiniz:

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'

git archive işlədiyiniz zaman arxivləşdirilmiş sənədin məzmunu belə görünür:

$ 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

Əvəzetmələrə, məsələn, commit mesajı və hər hansı bir git notes daxil ola bilər və git log sadə word wrapping edə bilər:

$ 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.

Nəticədə yaradılan arxiv yerləşdirmə işləri üçün əlverişlidir, lakin ixrac olunan hər hansı bir arxiv kimi uyğundur, daha da inkişaf etdirmək üçün uyğun deyil.

Merge Strategies

Ayrıca, Git-ə layihənizdə müəyyən sənədlər üçün fərqli birləşmə strategiyaları istifadə etməsini söyləmək üçün Git atributlarından istifadə edə bilərsiniz. Çox faydalı seçimlərdən biri, Git-ə müəyyən faylları bir-birinə konflikt olduqda birləşdirməyə çalışmamasını, əksinə birləşmə tərəfinizi başqasının üzərindən istifadə etməsini söyləməkdir.

Bu, dəyişiklikləri yenidən birləşdirmək və müəyyən sənədləri görməməzlikdən gəlmək istəsəniz, layihənizdəki bir branch ayrıldığı və ya ixtisaslaşmış olduğu halda faydalıdır. İki verilənlər bazasında fərqli olan database.xml adlı verilənlər bazası parametrləri sənədinizin olduğunu və verilənlər bazası faylını qarışdırmadan digər branch-nızda birləşmək istədiyinizi söyləyin. Belə bir atribut qura bilərsiniz:

database.xml merge=ours

Və sonra bir dummy ours birləşmə strategiyasını müəyyənləşdirin:

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

Digər verilənlər bazasında birləşirsinizsə, database.xml faylı ilə birləşmə konfliktləri yerinə, buna bənzər bir şey görürsünüz:

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

Bu vəziyyətdə, database.xml əvvəldə olduğunuz hər hansı bir versiyada qalır.