Konfiguracja Gita
Jak w skrócie zobaczyłeś w rozdziale 1, możesz zmieniać ustawienia konfiguracyjne za pomocą komendy git config
. Jedną z pierwszych rzeczy którą zrobiłeś, było ustawienie imienia i adresu e-mail:
$ git config --global user.name "John Doe"
$ git config --global user.email [email protected]
Teraz poznasz kilka bardziej interesujących opcji, które możesz ustawić w ten sposób, aby dostosować działanie Gita.
Widziałeś już kilka przykładowych ustawień konfiguracyjnych w pierwszym rozdziale, ale przejdziemy przez nie szybko jeszcze raz. Git używa kilku plików konfiguracyjnych, aby odczytać niestandardowe ustawienia które możesz mieć ustawione. Pierwszym miejscem w którym Git sprawdzi te ustawienia jest plik /etc/gitconfig
, który zawiera ustawienia dla wszystkich użytkowników znajdujących się w systemie, oraz dla ich wszystkich repozytoriów. Jeżeli dodasz opcję --system
do git config
, Git będzie zapisywał i odczytywał ustawienia właśnie z tego pliku.
Następnym miejscem w które Git zajrzy jest plik ~/.gitconfig
, wskazujący na ustawienia dla konkretnych użytkowników. Dodając opcję --global
, zmusisz Gita to odczytywania i zapisywania ustawień z tego pliku.
Na końcu, Git szuka ustawień w pliku konfiguracyjnym znajdującym się z katalogu Git (.git/config
) w każdym repozytorium którego obecnie używasz. Ustawienia te są specyficzne dla tego konkretnego repozytorium. Każdy z poziomów nadpisuje ustawienia poprzedniego poziomu, więc na przykład ustawienia w .git/config
nadpisują te z /etc/gitconfig
. Możesz również ustawiać wartości ręcznie poprzez edycję i wprowadzenie danych w poprawnym formacie, ale generalnie dużo łatwiej jest użyć komendy git config
.
Podstawowa konfiguracja klienta
Opcje konfiguracyjne rozpoznawane przez Gita dzielą się na dwie kategorie: opcje klienta i serwera. Większość opcji dotyczy konfiguracji klienta - ustawień Twoich własnych preferencji. Chociaż jest dostępnych mnóstwo opcji, opiszę tylko kilka te z nich, które są albo często używane lub mogą w znaczący sposób wpłynąć na Twoją pracę. Duża ilość opcji jest użyteczna tylko w specyficznych sytuacjach, których nie opiszę tutaj. Jeżeli chcesz zobaczyć listę wszystkich opcji konfiguracyjnych które Twoja wersja Gita rozpoznaje, uruchom
$ git config --help
Podręcznik pomocy systemowej dla git config
pokazuje wszystkie dostępne opcje i opisuje je w dość szczegółowy sposób.
core.editor
Domyślnie, Git używa edytora ustawionego domyślnie, lub wraca do edytora Vi podczas tworzenia i edycji commitów i treści komentarzy do zmiany. Aby zmienić domyślny edytor na jakiś inny, używasz ustawienia core.editor
:
$ git config --global core.editor emacs
Od teraz, nie ważne na jaki edytor wskazuje zmienna konfiguracyjna w powłoce, Git będzie uruchamiał Emacs do edycji wiadomości.
commit.template
Jeżeli ustawisz ją na ścieżkę wskazującą na plik w Twoim systemie, Git będzie używał tego pliku jako szablonu komentarza do commita. Na przykład, załóżmy że stworzyłeś plik $HOME/.gitmessage.txt
zawierający:
subject line
what happened
[ticket: X]
Aby wskazać Gitowi, że chcesz używać go jako domyślnej treści komentarza pokazującej się w edytorze po uruchomieniu git commit
, ustaw zmienną konfiguracyjną commit.template
na:
$ git config --global commit.template $HOME/.gitmessage.txt
$ git commit
Potem, Twój edytor będzie ustawiał coś takiego jako domyślną treść komentarza po commicie:
subject line
what happened
[ticket: X]
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: lib/test.rb
#
~
~
".git/COMMIT_EDITMSG" 14L, 297C
Jeżeli masz specjalną politykę tworzenia treści komentarzy, to ustawienie takiego szablonu i skonfigurowanie Gita aby go używał zwiększy szanse na to, że będzie ona regularnie przestrzegana.
core.pager
Wartość core.pager określa jaki program do stronicowania jest używany przez Gita podczas pokazywania wyników komend log
i diff
. Możesz ustawić je na more
lub inny ulubiony (domyślnie jest to less
), lub możesz zupełnie je wyłączyć przez ustawienie pustej wartości:
$ git config --global core.pager ''
Jeżeli to uruchomisz, Git będzie pokazywał pełne wyniki wszystkich komend, bez względu na to jak długie są.
user.signingkey
Jeżeli tworzysz opisane etykiety (jak opisano w rozdziale 2), ustawienie Twojego klucza GPG jako zmiennej konfiguracyjnej ułatwi trochę sprawę. Ustaw swój identyfikator klucza w ten sposób:
$ git config --global user.signingkey <gpg-key-id>
Teraz, możesz podpisywać tagi bez konieczności wskazywania za każdym razem klucza podczas uruchamiania komendy git tag
:
$ git tag -s <tag-name>
core.excludesfile
Możesz umieścić wzorce w pliku .gitignore
w swoim projekcie, aby Git nie śledził ich i nie próbował dodawać do przechowalni po wykonaniu komendy git add
, jak wspomniałem już w rozdziale 2. Możesz jednak przechowywać te informacje w innym pliku, znajdującym się poza drzewem projektu, możesz wskazać Gitowi lokalizację tego pliku za pomocą ustawienia core.excludesfile
. Po prostu ustaw ją na ścieżkę wskazującą na plik, który ma zawartość podobną do tej, którą ma .gitignore
.
help.autocorrect
Ta opcja jest dostępna w wersjach Gita 1.6.1 i późniejszych. Jeżeli błędnie wpiszesz komendę w Git, zostanie Ci pokazany wynik podobny do:
$ git com
git: 'com' is not a git-command. See 'git --help'.
Did you mean this?
commit
Jeżeli ustawisz help.autocorrect
na 1, Git automatycznie uruchomi komendę, jeżeli będzie mógł ją dopasować tylko do jednego wyniku.
Kolory w Git
Git może również pokazywać wyniki swojego działania w kolorze, co ułatwi Ci ich odczytanie w szybszy i łatwiejszy sposób. Liczne opcje pozwalają na dostosowanie kolorowania do Twoich preferencji.
color.ui
Git może automatycznie pokazywać w kolorze większość wyników swojego działania. Możesz bardzo dokładnie ustawić to co ma być pokazywane w kolorze, oraz w jaki sposób; ale aby włączyć wszystkie domyślne ustawienia dotyczące kolorowania, ustaw color.ui
na true:
$ git config --global color.ui true
Gdy ta wartość jest ustawiona, Git będzie pokazywał w kolorze wyniki swojego działania na terminalu. Inne możliwe ustawienia to "false", które nigdy nie będzie pokazywało w kolorze wyników działania, oraz "always", które zawsze ustawi kolory, nawet w przypadku gdy będziesz chciał zapisać wyniki do pliku lub przekazać do innej komendy.
Bardzo rzadko będziesz potrzebował color.ui = always
. Najczęściej, jeżeli będziesz chciał kolory w wynik działania Gita, użyjesz opcji --color
do komendy Gita, aby wymusić na nim użycie kolorów. Ustawienie color.ui = true
jest najczęściej tym, które będziesz chciał użyć.
color.*
Jeżeli chciałbyś móc bardziej dokładnie ustalać co i w jaki sposób jest pokazywane w kolorze, Git dostarcza odpowiednie ustawienia. Każde z nich może mieć wartość true
, false
lub always
:
color.branch
color.diff
color.interactive
color.status
Dodatkowo, każde z nich ma dodatkowe ustawienia, których możesz użyć, aby zmienić konkretne kolory dla części z wyświetlanego wyniku, jeżeli chciałbyś nadpisać jakiś z kolorów. Na przykład, aby pokazać w kolorze wynik komendy diff z niebieskim kolorem pierwszoplanowym, czarnym tłem i pogrubioną czcionką, uruchom:
$ git config --global color.diff.meta "blue black bold"
Możesz ustawić kolor na wartość jedną z: normal, black, red, green, yellow, blue, magenta, cyan lub white. Jeżeli chciałbyś użyć dodatkowego atrybutu takiego jak pogrubienie z poprzedniego przykładu, możesz wykorzystać bold, dim, ul, blink oraz reverse.
Zobacz podręcznik systemowy do komendy git config
, aby poznać wszystkie ustawienia których możesz użyć podczas zmiany tych ustawień.
Zewnętrzne narzędzia do łączenia i pokazywania różnic
Chociaż Git posiada wbudowaną obsługę narzędzia diff, którego dotychczas używałeś, możesz ustawić inny zewnętrzny program zamiast niego. Możesz również ustawić graficzny program pozwalający na łączenie zmian i rozwiązywanie konfliktów, bez konieczności robienia tego ręcznie. Zaprezentuję na przykładzie Perforce Visual Merge Tool (P4Merge) w jaki sposób ustawić do obsługi łączenia i pokazywania różnic zewnętrzny program, ponieważ ma on prosty graficzny interfejs i jest darmowy.
Jeżeli chcesz tego również spróbować, P4Merge działa na wszystkich głównych platformach, więc prawdopodobnie będziesz mógł to zrobić. Będę używał nazw ścieżek w przykładach które działają na systemach Mac i Linux; dla systemu Windows będziesz musiał zmienić /usr/local/bin
na odpowiednią ścieżkę w Twoim środowisku.
Możesz pobrać P4Merge stąd:
http://www.perforce.com/perforce/downloads/component.html
Na początek, ustawimy zewnętrzny skrypt do uruchamiania komend. Użyję ścieżki z systemu Mac wskazującej na program; w innych systemach, będzie ona musiała wskazywać na miejsce w którym program p4merge
został zainstalowany. Stwórz skrypt o nazwie extMerge
, który będzie przyjmował wszystkie podane parametry i uruchamiał program:
$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/p4merge.app/Contents/MacOS/p4merge $*
Skrypt do obsługi diff sprawdza czy zostało podanych 7 argumentów i przekazuje dwa z nich do skryptu obsługującego merge. Domyślnie, Git przekazuje te argumenty do programu obsługującego pokazywanie różnic:
ścieżka stary-plik stara-wartość-hex stary-tryb nowy-plik nowa-wartość-hex nowy-tryb
Ponieważ chcesz tylko argumentów stary-plik
i nowy-plik
, w skrypcie przekazujesz tylko te które potrzebujesz.
$ cat /usr/local/bin/extDiff
#!/bin/sh
[ $# -eq 7 ] && /usr/local/bin/extMerge "$2" "$5"
Musisz zwrócić uwagę, czy te skrypty mają poprawne uprawnienia:
$ sudo chmod +x /usr/local/bin/extMerge
$ sudo chmod +x /usr/local/bin/extDiff
Teraz możesz ustawić swój plik konfiguracyjny, aby korzystał z innych niż domyślne programów do łączenia i rozwiązywania konfliktów. Dostępnych jest kilka opcji konfiguracyjnych: merge.tool
wskazująca jaką strategię TODO
$ git config --global merge.tool extMerge
$ git config --global mergetool.extMerge.cmd \
'extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"'
$ git config --global mergetool.trustExitCode false
$ git config --global diff.external extDiff
lub możesz wyedytować swój plik ~/.gitconfig
i dodać następujące linie:
[merge]
tool = extMerge
[mergetool "extMerge"]
cmd = extMerge \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"
trustExitCode = false
[diff]
external = extDiff
Po wprowadzeniu tych ustawień, jeżeli uruchomisz komendę diff w ten sposób:
$ git diff 32d1776b1^ 32d1776b1
Zamiast wyniku pokazanego w wierszu poleceń, Git uruchomi P4Merge, pokazując wynik podobny do tego zamieszczonego na Rysunku 7-1.
Figure 7-1. P4Merge.
Jeżeli spróbujesz wykonać łączenie (ang. merge) na dwóch gałęziach, które zakończy się konfliktem, możesz uruchomić komendę git mergetool
; zostanie uruchomiony skrypt P4Merge, pozwalający na rozwiązanie konfliktów poprzez interfejs graficzny GUI.
Zaletą tej konfiguracji jest to, że możesz zmienić łatwo zmienić narzędzia służące do porównywania (diff), oraz łączenia (merge). Na przykład, aby skrypty extDiff
i extMerge
uruchamiały KDiff3, musisz tylko zmienić plik extMerge
:
$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/kdiff3.app/Contents/MacOS/kdiff3 $*
teraz, Git będzie używał programu KDiff3 podczas pokazywania różnic oraz rozwiązywania konfliktów.
Git jest wstępnie skonfigurowany do używania wielu innych narzędzi do łączenia i rozwiązywania konfliktów, bez konieczności wprowadzania konfiguracji odpowiednich komend. Możesz wybrać narzędzia takie jak kdiff3, opendiff, tkdiff, meld, xxdiff, emerge, vimdiff, oraz gvimdiff. Jeżeli nie chcesz używać KDiff3 do pokazywania różnic, ale chcesz aby dalej służył do rozwiązywania konfliktów, w przypadku gdy kdiff3 znajduje się w zmiennej środowiskowej PATH, możesz uruchomić
$ git config --global merge.tool kdiff3
Jeżeli uruchomić tę komendę, zamiast ustawienia plików extMerge
i extDiff
, Git będzie używał KDiff3 do rozwiązywania konfliktów i standardowego narzędzia Git diff do pokazywania różnic.
Formatowanie i białe znaki
Problemy związane z formatowaniem i białymi znakami są jednymi z bardziej uciążliwych i wyrafinowanych, które wielu deweloperów mogą spotkać podczas pracy, szczególnie jeżeli korzystają z różnych systemów operacyjnych. Bardzo łatwo można je wprowadzić w łatach lub modyfikacjach, poprzez samoistne dodanie ich przez edytor tekstowy, lub dodanie znaku powrotu karetki na końcach linii przez programistów korzystających z systemu Windows. Git posiada kilka opcji konfiguracyjnych, które pomagają rozwiązać te problemy.
core.autocrlf
Jeżeli programujesz na systemie Windows, lub używasz innego systemu, ale współpracujesz z osobami które programują na tym systemie, prawdopodobnie będziesz miał w pewnym momencie problemy związane ze znakami końca linii. Dzieje się tak dlatego, ponieważ system Windows używa obu znaków powrotu karetki i nowej linii w celu oznaczenia końca wiersza w swoich plikach, a tymczasem w systemach Mac i Linux użwany jest jedynie znak nowej linii. To jest subtelny, ale bardzo irytujący fakt przy współpracy na wielu platformach.
Git może to obsłużyć poprzez automatyczną konwersję linii CRLF na LF, gdy wykonujesz commit, i odwrotnie podczas pobierania kodu na dysk. Możesz włączyć tą funkcjonalność za pomocą ustawienia core.autocrlf
. Jeżeli pracujesz na systemie Windows, ustaw jej wartość na true
- zamieni to znaki LF na CRLS podczas pobierania kodu.
$ git config --global core.autocrlf true
Jeżeli pracujesz na systemie Linux lub Mac, który używa znaków LF oznaczających koniec wiersza, nie będziesz chciał, aby Git automatycznie konwertował je podczas pobierania kodu; jednakże, jeżeli zostanie przez pomyłkę wgrany plik z zakończeniami CRLF, możesz chcieć aby Git je poprawił. Możesz wskazać Git, aby konwertował znaki CRLF na LF podczas commita, ale nie w odwrotną stronę ustawiając core.autocrlf
na input:
$ git config --global core.autocrlf input
Takie ustawienia powinny zachować znaki CRLF na systemach Windows, oraz LF na systemach Mac i Linux, oraz w repozytorium.
Jeżeli jesteś programistą tworzącym aplikację przeznaczoną wyłącznie na systemy Windows, możesz zupełnie wyłączyć tą funkcjonalność przez ustawienie wartości false, przez co znaki powrotu karetki również będą zapisywanie w repozytorium.
$ git config --global core.autocrlf false
core.whitespace
Git comes preset to detect and fix some whitespace issues. It can look for four primary whitespace issues — two are enabled by default and can be turned off, and two aren’t enabled by default but can be activated.
The two that are turned on by default are trailing-space
, which looks for spaces at the end of a line, and space-before-tab
, which looks for spaces before tabs at the beginning of a line.
The two that are disabled by default but can be turned on are indent-with-non-tab
, which looks for lines that begin with eight or more spaces instead of tabs, and cr-at-eol
, which tells Git that carriage returns at the end of lines are OK.
You can tell Git which of these you want enabled by setting core.whitespace
to the values you want on or off, separated by commas. You can disable settings by either leaving them out of the setting string or prepending a -
in front of the value. For example, if you want all but cr-at-eol
to be set, you can do this:
$ git config --global core.whitespace \
trailing-space,space-before-tab,indent-with-non-tab
Git will detect these issues when you run a git diff
command and try to color them so you can possibly fix them before you commit. It will also use these values to help you when you apply patches with git apply
. When you’re applying patches, you can ask Git to warn you if it’s applying patches with the specified whitespace issues:
$ git apply --whitespace=warn <patch>
Or you can have Git try to automatically fix the issue before applying the patch:
$ git apply --whitespace=fix <patch>
These options apply to the git rebase
command as well. If you’ve committed whitespace issues but haven’t yet pushed upstream, you can run a rebase
with the --whitespace=fix
option to have Git automatically fix whitespace issues as it’s rewriting the patches.
Server Configuration
Not nearly as many configuration options are available for the server side of Git, but there are a few interesting ones you may want to take note of.
receive.fsckObjects
By default, Git doesn’t check for consistency all the objects it receives during a push. Although Git can check to make sure each object still matches its SHA-1 checksum and points to valid objects, it doesn’t do that by default on every push. This is a relatively expensive operation and may add a lot of time to each push, depending on the size of the repository or the push. If you want Git to check object consistency on every push, you can force it to do so by setting receive.fsckObjects
to true:
$ git config --system receive.fsckObjects true
Now, Git will check the integrity of your repository before each push is accepted to make sure faulty clients aren’t introducing corrupt data.
receive.denyNonFastForwards
If you rebase commits that you’ve already pushed and then try to push again, or otherwise try to push a commit to a remote branch that doesn’t contain the commit that the remote branch currently points to, you’ll be denied. This is generally good policy; but in the case of the rebase, you may determine that you know what you’re doing and can force-update the remote branch with a -f
flag to your push command.
To disable the ability to force-update remote branches to non-fast-forward references, set receive.denyNonFastForwards
:
$ git config --system receive.denyNonFastForwards true
The other way you can do this is via server-side receive hooks, which I’ll cover in a bit. That approach lets you do more complex things like deny non-fast-forwards to a certain subset of users.
receive.denyDeletes
One of the workarounds to the denyNonFastForwards
policy is for the user to delete the branch and then push it back up with the new reference. In newer versions of Git (beginning with version 1.6.1), you can set receive.denyDeletes
to true:
$ git config --system receive.denyDeletes true
This denies branch and tag deletion over a push across the board — no user can do it. To remove remote branches, you must remove the ref files from the server manually. There are also more interesting ways to do this on a per-user basis via ACLs, as you’ll learn at the end of this chapter.