git
[GIT] Jak poradziś sobie ze znakami końca linii (.gitattributes)
Już kiedyś o tym pisałem tylko z tamtego wpisu muszę wywalić że autocrlf.true jest dobre: Rozwiązanie CRLF dla git (znaki końca linii w Windows)
Na różnych systemach znaki końca linii są inne (Windows – CRLF, Unix – LF, Mac – CR).
Więc podczas zapisywania historii plików potrzebna jest standard jak to zapisywać. Tym standardem jest LF. Podczas wyciągania takich plików z repo na dysk następują na Windowsie zmiana na CRLF a na Macu na CR. Podobnie w drugą stronę, pliki na Windowsie edytowane z CRLF podczas zapisu do repozytorium zostaną zamienione na LF.
Kiedyś, żebo to zrobić to ustawiało się opcję autocrlf.true globalnie dla systemu. Teraz już tak nie należy robić, trzeba to zrobić w repozytorium. Żeby to dobrze zrobić na dziś dzień korzysta się z plików .gitattributes.
Poniżej taki plik jako gist, którego sobie będę utrzymywał:
# taken from https://github.com/aspnet/SignalR-samples/blob/master/.gitattributes | |
# Auto detect text files and perform LF normalization | |
* text=auto | |
*.doc diff=astextplain | |
*.DOC diff=astextplain | |
*.docx diff=astextplain | |
*.DOCX diff=astextplain | |
*.dot diff=astextplain | |
*.DOT diff=astextplain | |
*.pdf diff=astextplain | |
*.PDF diff=astextplain | |
*.rtf diff=astextplain | |
*.RTF diff=astextplain | |
*.jpg binary | |
*.png binary | |
*.gif binary | |
*.cs text=auto diff=csharp | |
*.vb text=auto | |
*.resx text=auto | |
*.c text=auto | |
*.cpp text=auto | |
*.cxx text=auto | |
*.h text=auto | |
*.hxx text=auto | |
*.py text=auto | |
*.rb text=auto | |
*.java text=auto | |
*.html text=auto | |
*.htm text=auto | |
*.css text=auto | |
*.scss text=auto | |
*.sass text=auto | |
*.less text=auto | |
*.js text=auto | |
*.lisp text=auto | |
*.clj text=auto | |
*.sql text=auto | |
*.php text=auto | |
*.lua text=auto | |
*.m text=auto | |
*.asm text=auto | |
*.erl text=auto | |
*.fs text=auto | |
*.fsx text=auto | |
*.hs text=auto | |
*.csproj text=auto | |
*.vbproj text=auto | |
*.fsproj text=auto | |
*.dbproj text=auto | |
*.sln text=auto eol=crlf | |
*.sh eol=lf | |
##### | |
# End of core list, below put you custom 'per project' settings | |
##### |
Chcę wrzucić commita na nie mój projekt na githubie
– Forkuję ten projekt.
– clonuję mojego forka.
– ustawiam nowy remote wskazujący na oryginalne repo (to tak bardziej na przyszłość) – nazywam go upstream
– tworzę brancha (konwencją dowolna, byle się nazywał podobnie jak Pull Request który zrobię)
– wrzucam moje zmiany
– robię Pull Request z mojego brancha na mastera w oryginalnym repo.
– gdy master oryginalny posuwa się do przodu to się z nim synchronizuję: ‘git checkout master; git reset –hard upstream/master’
– analogicznie działa ‘git pull upstream’, a potem ‘git push’ (bo mój master ma “origin” jako domyślny)
!!! nie działa w C:\Work\GitHub\Tellurium\.git – nie wiem jak zrobić update do upstream/master
Materiały po Git szkoleniu
Tutorial i rzeczy, które fajnie rozwiązać żeby się więcej nauczyć:
https://learngitbranching.js.org
https://onlywei.github.io/explain-git-with-d3/
https://github.com/SkillsTemple/git-devWarsztaty-rebase
Ksiązka o gicie, jest też polska wersja:
https://git-scm.com/book/en/v2
Pozostałe:
http://ohshitgit.com/
https://stackoverflow.com/questions/2596805/how-do-i-make-git-use-the-editor-of-my-choice-for-commits
najczęściej będzie to “git config –global core.editor notepad”
KDiff3:
https://krzysztofmorcinek.wordpress.com/2016/03/01/git-rozwiazywanie-konfliktow/
https://krzysztofmorcinek.wordpress.com/2016/02/16/git-i-poprawianie-commitow-z-poziomu-source-tree/
Bardzo ważne o tym jak nazywać commity:
https://chris.beams.io/posts/git-commit/
Sa różne flow, którymi można pracować w gicie. Dla potrzeb, które macie najlepiej sprawdza się https://trunkbaseddevelopment.com/
Aliasy i inne:
[core] | |
# autocrlf = true/input # it should be done explicit using .gitattributes https://help.github.com/en/github/using-git/configuring-git-to-handle-line-endings | |
[pull] | |
rebase = true | |
[push] | |
default = current | |
[alias] | |
ls = log –pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cgreen\\ [%an]" –decorate | |
lst = log –pretty=format:%C(yellow)%h%Cred%d\\ %Creset%s%Cgreen\\ [%an] –decorate -10 | |
lds = log –pretty=format:"%C(yellow)%h\\ %ad%Cred%d\\ %Creset%s%Cgreen\\ [%an]" –decorate –date=short | |
ll = log –pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cgreen\\ [%an]" –decorate –numstat | |
lol = log –graph –decorate –pretty=oneline –abbrev-commit –all | |
cp = cherry-pick | |
st = status -s | |
ci = commit | |
co = checkout | |
br = branch | |
diff = diff –word-diff | |
wdiff = diff –word-diff=plain | |
dc = diff –cached | |
r = reset | |
r1 = reset HEAD^ | |
rh = reset –hard | |
rh1 = reset –hard HEAD^ | |
rh2 = reset –hard HEAD^^ | |
ready = rebase -i @{u} | |
amend = commit –amend -aC HEAD | |
undo = reset –soft HEAD^ | |
#clean = add . && git rh | |
# standup = log –since '1 day ago' –oneline –author <YOUREMAIL> # hack it with your email and uncomment | |
# jira = log –since '6am' –oneline –author <YOUREMAIL> # hack it with your email and uncomment | |
# git-svn | |
spull = svn rebase | |
spush = svn dcommit | |
# even faster aliases | |
aa = add –all | |
com = checkout master | |
cam = commit -am | |
ac = !git add -A && git commit | |
acam = !git add -A && git commit -am | |
ri2 = rebase -i HEAD~2 | |
ri3 = rebase -i HEAD~3 | |
ri5 = rebase -i HEAD~5 | |
ri9 = rebase -i HEAD~9 | |
ri22 = rebase -i HEAD~22 | |
ri = rebase -i | |
rc = rebase –continue | |
ra = rebase –abort | |
rs = rebase –skip | |
mt = mergetool | |
ref1 = reset –hard HEAD@{1} | |
ref2 = reset –hard HEAD@{2} | |
cv = checkout – # checkout on previous branch, faster to type than 'cb' | |
cod = checkout develop | |
red = rebase develop | |
rem = rebase master | |
syncd = !git checkout develop && git pull –rebase && git checkout – && git rebase develop | |
syncm = !git checkout master && git pull –rebase && git checkout – && git rebase master | |
riod = rebase -i origin/develop # rebase origin/develop | |
cppb = cherry-pick HEAD@{1} # Cherry-pick previous branch | |
pushf = push –force-with-lease | |
revh = revert HEAD | |
fp = fetch –prune | |
# Some common commit messages | |
dead = commit -am 'Remove dead code' | |
readme = commit *.md -m'Just update readme' | |
# Add files based on extension | |
cs = add *.cs | |
js = add *.js | |
ts = add *.ts | |
sql = add *.sql | |
json = add *.json | |
java = add *.java | |
yml = add *.yml | |
[merge] | |
tool = kdiff3 | |
[mergetool "kdiff3"] | |
path = c:/Program Files/KDiff3/kdiff3.exe | |
[diff] | |
tool = kdiff3 | |
guitool = kdiff3 | |
[difftool "kdiff3"] | |
path = c:/Program Files/KDiff3/kdiff3.exe | |
[mergetool] | |
keepBackup = false | |
[color] | |
ui = true |
Jak sprawdzić jakie znaki końca linii (Line Endings) są w zdalnym repozytorium
Ustawić globalnie aby autoCrlf było takie że nic nie zmienia znaków końca linii (“core.autocrlf” is set to “false”).
Wywalić plik .gitattributes z repozytorium.
Sprawdzić co dostaniemy po git clone.
[GIT] Szybkie przechodzenie między repozytoriami w konsoli
Idziemy do katalogu z zainstalowanym GITem do folderu etc (C:\Program Files\Git\etc).
Jest tam plik bash.bashrc.
Plik edytujemy jako administrator i na końcu dodajemy aliasy:
alias noyp="cd C:/SRC/NameOfYourProject/" # noyp is example abbreviation from NameOfYourProject | |
alias blef="cd C:/Work/Github/Blef/" | |
alias brlocal="git br | grep local" |
To samo można uzyskać na wiele innych sposobów (ten akurat działa w mojej konfiguracji systemu). Ten tutaj sprawia, przy otwieraniu konsoli gitowej dodane zostaną do basha aliasy. Dzięki temu możemy wyjść poza to co można dodać w .gitconfig i możemy korzystać z łączenia z komendami konsolowymi takimi jak grep w przykładzie.
Niech commit sobie odczeka
Jako że korzystam z GITa mogę zrobić taki scenariusz:
– robię commit (kilka commitów)
– biorę się za nastepny task
– w międzyczasie pojawia się obiad
– wracam po obiedzie
– ściągam najnowszą histori i robię rebase moich commitów (‘git pull –rebase’, gdzie wystarcza ‘git pull’, bo opcja rebase mam defaultowo włączoną)
– przeglądam commity zanim je wpushuje !!! i tutaj dzieją się fajne rzeczy. Zauważam jakiś bug, zauważam czego zapomniałem, co mogę czytelniej napisać. I do publicznej historii trafia kod po prostu lepszy.
W tym przykładzie nieistotne jest czy pushuje bezpośrednio na brach “develop” czy tworzę branch pod PR i code review.
Git – bardzo duża zmiana/migracja/grzebanie w gównie – jak sobie poradzić
Zaletą GITa jest commitowanie lokalne krok po kroku. Taki powtarzający się w kółko schemat:
– kodujemy kawałek
– sprawdzamy czy działa
– commitujemy (dodatkowo dając coś mówiący opis)
Gdy to coś co zmieniamy jest duuuże i trudno ogarnialne bo będą występować sytuacje gdzie:
– doszliśmy do miejsca, które jest ślepą uliczką – trzeba się wrócić kilka commitów bo w ten sposób “się nie da”
– inna rzecz się wywaliła która nie powinna – wtedy możemy przejść wstecz historię lokalnych commitów i zobaczyc w którym miejscu coś się wywala (jeszcze lepsze jest szukanie połówkowe git-bisect)
Use cases
Podniesie do kolejnej wersji GoogleMaps – kolega miał kiedyś coś takiego. Na starej stronie było GoogleMaps api w wersji 1, a Google zarzucił już wsparcie. Trzeba było podnieść do wspieranej wersji. Kod był taki, że można się ciąć – zero reużywalności kodu, logika JavaScript zawarta na stronach ASP.NET Web Forms (brak oddzielnych plików *.js). Coś napisanego ponad dekadę temu, nieużywanego od lat o czym wszyscy chcieli zapomnieć, a tu klientowi się wysypało i trzeba zrobić. Bez chodzenia krok po kroku, commit po commicie nie wyobrażam sobie tego zadania.
Migracja do Entity Framework Code First – też krok po kroku, wiele rzeczy może nie zadziałać, Research, poprawanie, etc.
Z jakim kodem zakończyć?
Na koniec gdy juz mamy ostateczny efekt możemy zrobić kilka rzeczy
– zrobić z tego jeden wielki commit – wygląda na brute force, ale nie jest to taka zła opcja. Oczywiście przeglądamy taki commit czy nie powinniśmy czegoś poprawić czy wyrzucić.
– powiązać commity w sensowe kilka commitów zmieniających jakieś oddzielne componenty – jest to trudniejsze, bo wymaga wprawy w operowaniu gitem.
GitKraken – wreszcie dobry UI dla GITa
Wreszcie jest dobry klient GITa dla klikaczy – https://www.gitkraken.com. Dopiero co wystartowała wersja 1.0. Więc jeszcze nie ma wszystkich feature które ma np Source Tree, jak na przykład “rebase interactive”, ale wkrótce zostaną dodane. Myślę tutaj o takich bardziej zaawansowanych rzeczach bo do zwykłej pracy jak commit, amend, przechodzenie między branchami, cherry-pick, przeglądanie historii, stage wybranych fragmentów pliku nadaje się znakomicie.
Instalacja
Ściągamy najnowszą wersję i konfigurujemy. W zasadzie konfiguracja sprowadza się do wpisania emaila i nazwy użytkownika. Pozostałe rzeczy warto przeklikać tam gdzie nas prowadzą strzałki tylko po to żeby wiedzieć później że takie ustawienia są. Nie przejmujemy się niczym więcej.
Czy jest darmowy
Na tą wersję tak. Kod nie jest open source. Jak sama firma o tym pisze to pewnie kiedyś zrobią wersję płatną która będzie mieć dodatkowe bajery. Zakładam więc, że dla zwykłych zastowowań (czyli i tak 300% tego użytkownik co SVN wie o sposobach pracy z kodem), wersja zawsze będzie darmowa.
Git – czasem dopiero po chwili wiesz jak dobrze nazwać
Tak najpierw nazwałem commity:
Install angular
AngularJS TypeScript typings
Update jQuery definitions for TypeScript
A później samo do mnie doszło że lepszymi nazwami będzie:
Install angular with TypeScript typings (z połączenia dwóch pierwszych)
Update jQuery definitions for TypeScript
Dzięki funkcjonalności rebase interactive możemy pozmieniać nazwy (posklejać commity), aby było to bardziej sensowne. Opisuję jak to wyklikać z GUI.