-
1. ZaÄetek
- 1.1 O nadzoru razliÄic
- 1.2 Kratka zgodovina Gita
- 1.3 Kaj je Git?
- 1.4 Ukazna vrstica
- 1.5 Namestitev Gita
- 1.6 Prva nastavitev Gita
- 1.7 Pridobivanje pomoÄi
- 1.8 Povzetek
-
2. Osnove Git
- 2.1 Pridobivanje repozitorija Git
- 2.2 Snemanje sprememb v repozitorij
- 2.3 Pregled zgodovine potrditev
- 2.4 Razveljavljanje stvari
- 2.5 Delo z daljavami
- 2.6 OznaÄevanje
- 2.7 Aliasi Git
- 2.8 Povzetek
-
3. Veje Git
- 3.1 Veje na kratko
- 3.2 Osnove vej in združevanja
- 3.3 Upravljanje vej
- 3.4 Poteki dela z vejami
- 3.5 Oddaljene veje
- 3.6 Ponovno baziranje
- 3.7 Povzetek
-
4. Git na strežniku
- 4.1 Protokoli
- 4.2 Pridobitev Gita na strežniku
- 4.3 Generiranje vaÅ”ih javnih kljuÄev SSH
- 4.4 Nastavitev strežnika
- 4.5 Prikriti proces Git
- 4.6 Pametni HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Možnosti gostovanja pri tretjih ponudnikih
- 4.10 Povzetek
-
5. Porazdeljeni Git
- 5.1 Porazdeljeni poteki dela
- 5.2 Prispevek k projektu
- 5.3 Vzdrževanje projekta
- 5.4 Povzetek
-
6. GitHub
-
7. Orodja Git
- 7.1 Izbira revizije
- 7.2 Interaktivno pripravljanje
- 7.3 Shranjevanje na varno (angl. stashing) in ÄiÅ”Äenje
- 7.4 Podpisovanje vaŔega dela
- 7.5 Iskanje
- 7.6 Prepisovanje zgodovine
- 7.7 Demistifikacija ponastavitve
- 7.8 Napredno združevanje
- 7.9 Rerere
- 7.10 RazhroÅ”Äevanje z Gitom
- 7.11 Podmoduli
- 7.12 Povezovanje v pakete
- 7.13 Zamenjava
- 7.14 Shramba poverilnic
- 7.15 Povzetek
-
8. Prilagoditev Gita
- 8.1 Konfiguracija Git
- 8.2 Atributi Git
- 8.3 Kljuke Git
- 8.4 Primer pravilnika, ki ga uveljavlja Git
- 8.5 Povzetek
-
9. Git in ostali sistemi
- 9.1 Git kot odjemalec
- 9.2 Migracija na Git
- 9.3 Povzetek
-
10. Notranjost Gita
- 10.1 Napeljava in keramika
- 10.2 Objekti Git
- 10.3 Reference Git
- 10.4 Packfiles (datoteke zmanjŔanih podatkov)
- 10.5 Refspec
- 10.6 Protokoli prenosa
- 10.7 Vzdrževanje in obnovitev podatkov
- 10.8 Spremenljivke okolja
- 10.9 Povzetek
-
A1. Dodatek A: Git v drugih okoljih
- A1.1 GrafiÄni vmesniki
- A1.2 Git v Visual Studio
- A1.3 Git v Visual Studio Code
- A1.4 Git v IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git v Sublime Text
- A1.6 Git v Bashu
- A1.7 Git v Zsh
- A1.8 Git v Powershellu
- A1.9 Povzetek
-
A2. Dodatek B: Vdelava Gita v vaŔo aplikacijo
- A2.1 Git v ukazni vrstici
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Dodatek C: Ukazi Git
- A3.1 Nastavitev in konfiguracija
- A3.2 Pridobivanje in ustvarjanje projektov
- A3.3 Osnove posnetkov
- A3.4 Veje in združevanje
- A3.5 Deljenje in posodabljanje projektov
- A3.6 Pregled in primerjava
- A3.7 RazhroÅ”Äevanje
- A3.8 Popravljanje
- A3.9 E-poŔta
- A3.10 Zunanji sistemi
- A3.11 Administracija
- A3.12 Orodja za sisteme napeljave
8.4 Prilagoditev Gita - Primer pravilnika, ki ga uveljavlja Git
Primer pravilnika, ki ga uveljavlja Git
V tem razdelku boste uporabili to, kar ste se nauÄili, da vzpostavite potek dela Git, ki preveri doloÄen format sporoÄila potrditve in dovoljuje samo doloÄenim uporabnikom spreminjanje doloÄenih poddirektorijev v projektu. Zgradili boste skripte za odjemalce, ki pomagajo razvijalcem vedeti, ali bo njihov potisk zavrnjen, in strežniÅ”ke skripte, ki dejansko izvajajo pravilnike.
Skripti, ki jih bomo prikazali, so napisani v Rubyju; deloma zaradi naÅ”e intelektualne vztrajnosti, vendar tudi zato, ker je Ruby enostaven za branje, tudi Äe ga ne morete nujno pisati. Vendar pa bo deloval kateri koli jezikāāāvsi primeri skriptov kljuk, ki jih distribuira Git, so v Perlu ali Bashu, zato lahko s pogledom na vzorce vidite tudi veliko primerov kljuk v teh jezikih.
Kljuke strežniŔke strani
Vsa strežniŔka dela bodo Ŕla v datoteko update
v vaŔem imeniku hooks
.
Kljuka update
se zažene enkrat za vsako potiskano vejo in sprejme tri argumente:
-
Ime referenÄne toÄke, ki se potiska
-
Stara revizija, kjer je bila ta veja
-
Nova revizija, ki se potiska
Äe se potisk izvaja prek SSH, imate tudi dostop do uporabnika, ki izvaja potisk.
Äe ste dovolili vsakomur, da se poveže z enim samim uporabnikom (kot je Ā»gitĀ«) prek overjanja z javnim kljuÄem, boste morda morali temu uporabniku dodeliti ovojnico lupine, ki glede na javni kljuÄ doloÄi, kateri uporabnik se povezuje, in ustrezno nastavi okoljsko spremenljivko.
Tukaj bomo predpostavili, da se povezujoÄi uporabnik nahaja v okoljski spremenljivki $USER
, zato vaÅ” skript update
zaÄne z zbiranjem vseh potrebnih informacij:
#!/usr/bin/env ruby
$refname = ARGV[0]
$oldrev = ARGV[1]
$newrev = ARGV[2]
$user = ENV['USER']
puts "Enforcing Policies..."
puts "(#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})"
Da, to so globalne spremenljivke. Ne soditeāāāenostavneje je demonstrirati na tak naÄin.
Uveljavljanje doloÄene oblike sporoÄila potrditve
VaÅ” prvi izziv je, da vsako potrditev prisilite k upoÅ”tevanju doloÄenega formata sporoÄila. Samo da imate cilj, predpostavite, da mora vsako sporoÄilo vsebovati niz, ki je videti kot Ā»ref: 1234Ā«, ker želite, da se vsaka potrditev poveže z delovnim elementom v vaÅ”em sistemu za sledenje nalogam. Za vsako potrditev, ki jo potiskate navzgor, morate preveriti, ali je ta niz v sporoÄilu potrditve in ali ta niz manjka pri kateri koli potrditvi, izstopite z neniÄelno vrednostjo, da se potisk zavrne.
Seznam vrednosti SHA-1 vseh potrditev, ki se potiskajo, lahko dobite tako, da vzamete vrednosti $newrev
in $oldrev
ter jih predate Gitovi ukazni vrstici, imenovani git rev-list
.
To je v bistvu ukaz git log
, vendar privzeto izpiŔe samo vrednosti SHA-1 in nobenih drugih informacij.
Zato lahko za pridobitev seznama vseh SHA-1 potrditev, ki so bile uvedene med dvema SHA-1 potrditvama, zaženete nekaj takega:
$ git rev-list 538c33..d14fc7
d14fc7c847ab946ec39590d87783c69b031bdfb7
9f585da4401b0a3999e84113824d15245c13f0be
234071a1be950e2a8d078e6141f5cd20c1e61ad3
dfa04c9ef3d5197182f13fb5b9b1fb7717d2222a
17716ec0f1ff5c77eff40b7fe912f9f6cfd0e475
IzpiÅ”ete lahko te izhode, greste z zanko skozi vsako od teh SHA-1 potrditev, pridobite sporoÄilo in ga preizkusite proti regularnemu izrazu, ki iÅ”Äe vzorec.
Ugotoviti morate, kako priti do sporoÄila potrditve od vsake od teh potrditev za testiranje.
Za pridobitev surovega podatka o potrditvi lahko uporabite Ŕe en ukaz napeljave imenovan git cat-file
.
Vsa ta orodja za ukazno vrstico bomo podrobno predstavili v Notranjost Gita; vendar pa vam tu prikazujemo, kaj vam da ta ukaz:
$ git cat-file commit ca82a6
tree cfda3bf379e4f8dba8717dee55aab78aef7f4daf
parent 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
author Scott Chacon <schacon@gmail.com> 1205815931 -0700
committer Scott Chacon <schacon@gmail.com> 1240030591 -0700
Change the version number
Preprost naÄin, kako priti do sporoÄila potrditve, ko imate njeno vrednost SHA-1, je iti do prve prazne vrstice in vzeti vse, kar sledi zanjo.
To lahko storite s pomoÄjo ukaza sed
na sistemih Unix:
$ git cat-file commit ca82a6 | sed '1,/^$/d'
Change the version number
Uporabite lahko to besedilo, da dobite sporoÄilo potrditve za vsako potrditev, ki se jo poskuÅ”a potisniti, in izstopite, Äe vidite karkoli, kar se ne ujema. Za izhod iz skripta in zavrnitev potiska, izstopite z neniÄelno vrednostjo. Celotna metoda je videti tako:
$regex = /\[ref: (\d+)\]/
# enforced custom commit message format
def check_message_format
missed_revs = `git rev-list #{$oldrev}..#{$newrev}`.split("\n")
missed_revs.each do |rev|
message = `git cat-file commit #{rev} | sed '1,/^$/d'`
if !$regex.match(message)
puts "[POLICY] Your message is not formatted correctly"
exit 1
end
end
end
check_message_format
Äe to vstavite v svoj skript update
, bo zavrnilo posodobitve, ki vsebujejo potrditve z neustreznimi sporoÄili.
Uveljavljanje sistema ACL, ki temelji na uporabniku
Recimo, da želite dodati mehanizem, ki uporablja seznam za kontrolo dostopa (ACL), ki doloÄa, kateri uporabniki smejo izvajati spremembe v katerem delu vaÅ”ih projektov.
Nekateri imajo polni dostop, drugi pa lahko spreminjajo le doloÄene poddirektorije ali specifiÄne datoteke.
Da bi to izvajali, boste pravila zapisali v datoteko, ki se imenuje acl
in se nahaja v vaŔem golem repozitoriju Git na strežniku.
Posodobitvena kljuka si bo ogledala ta pravila, videla, katere datoteke se uvajajo za vse potrditve, ki se potiskajo, in ugotovila, ali ima uporabnik, ki izvaja potiskanje, dostop do posodabljanja vseh teh datotek.
Prva stvar, ki jo boste storili, je, da boste napisali svoj ACL.
Tukaj boste uporabili format, zelo podoben mehanizmu ACL za CVS: uporablja serijo vrstic, kjer je prvo polje avail
ali unavail
, naslednje polje je seznam uporabnikov, loÄenih z vejico, ki se uporabljajo za pravilo, in zadnje polje je pot, za katero se uporablja pravilo (prazno pomeni odprti dostop).
Vsa ta polja so loÄena z znakom navpiÄnica (|
).
V tem primeru imate nekaj skrbnikov, nekaj piscev dokumentacije z dostopom do direktorija doc
, enega razvijalca, ki ima dostop samo do direktorijev lib
in tests
, vaŔa datoteka ACL pa je videti tako:
avail|nickh,pjhyett,defunkt,tpw
avail|usinclair,cdickens,ebronte|doc
avail|schacon|lib
avail|schacon|tests
ZaÄnete tako, da preberete te podatke v strukturo, ki jo lahko uporabljate.
V tem primeru boste zaradi preprostosti primera izvajali samo navodila avail
.
Tukaj je metoda, ki vam da asociativno tabelo, kjer je kljuÄ ime uporabnika, vrednost pa je tabela poti, do katerih ima uporabnik dostop za pisanje:
def get_acl_access_data(acl_file)
# read in ACL data
acl_file = File.read(acl_file).split("\n").reject { |line| line == '' }
access = {}
acl_file.each do |line|
avail, users, path = line.split('|')
next unless avail == 'avail'
users.split(',').each do |user|
access[user] ||= []
access[user] << path
end
end
access
end
Pri datoteki ACL, ki ste si jo ogledali prej, ta metoda get_acl_access_data
vrne podatkovno strukturo, ki je videti takole:
{"defunkt"=>[nil],
"tpw"=>[nil],
"nickh"=>[nil],
"pjhyett"=>[nil],
"schacon"=>["lib", "tests"],
"cdickens"=>["doc"],
"usinclair"=>["doc"],
"ebronte"=>["doc"]}
Zdaj, ko imate dovoljenja razÄiÅ”Äena, morate ugotoviti, katere poti so bile spremenjene v potrditvah, ki se poskuÅ”ajo potisniti, da se prepriÄate, da ima uporabnik, ki potiska, dostop do vseh njih.
Precej enostavno lahko vidite, katere datoteke so bile spremenjene v posamezni potrditvi z možnostjo --name-only
ukaza git log
(ki je omenjen na kratko v Osnove Git):
$ git log -1 --name-only --pretty=format:'' 9f585d
README
lib/test.rb
Äe uporabite strukturo ACL, ki jo vrne metoda get_acl_access_data
in jo preverimo z navedenimi datotekami v vsaki od potrditev, lahko ugotovimo, ali ima uporabnik dovoljenje za potiskanje vseh svojih potrditev:
# only allows certain users to modify certain subdirectories in a project
def check_directory_perms
access = get_acl_access_data('acl')
# see if anyone is trying to push something they can't
new_commits = `git rev-list #{$oldrev}..#{$newrev}`.split("\n")
new_commits.each do |rev|
files_modified = `git log -1 --name-only --pretty=format:'' #{rev}`.split("\n")
files_modified.each do |path|
next if path.size == 0
has_file_access = false
access[$user].each do |access_path|
if !access_path # user has access to everything
|| (path.start_with? access_path) # access to this path
has_file_access = true
end
end
if !has_file_access
puts "[POLICY] You do not have access to push to #{path}"
exit 1
end
end
end
end
check_directory_perms
S pomoÄjo git rev-list
dobite seznam novih potrditev, ki se potiskajo na vaŔ strežnik.
Nato za vsako od teh potrditev ugotovite, katere datoteke so spremenjene, in preverite, ali ima uporabnik, ki potiska spremembe, dostop do vseh poti, ki so bile spremenjene.
Zdaj uporabniki ne morejo potiskati nobenih potrditev z napaÄno oblikovanimi sporoÄili ali s spremenjenimi datotekami izven njihovih doloÄenih poti.
Testiranje
Äe zaženete chmod u+x .git/hooks/update
, kar je datoteka, v katero bi morali vstaviti vso to kodo, in nato poskusite potisniti potrditev s sporoÄilom, ki ne ustreza pravilom, boste dobili nekaj takega:
$ git push -f origin master
Counting objects: 5, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 323 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
Enforcing Policies...
(refs/heads/master) (8338c5) (c5b616)
[POLICY] Your message is not formatted correctly
error: hooks/update exited with error code 1
error: hook declined to update refs/heads/master
To git@gitserver:project.git
! [remote rejected] master -> master (hook declined)
error: failed to push some refs to 'git@gitserver:project.git'
Tu je nekaj zanimivih stvari. Najprej, vidite to, ko se kljuka zaÄne poganjati.
Enforcing Policies...
(refs/heads/master) (fb8c72) (c56860)
Pomnite, da ste to izpisali na zaÄetku svoje skripte za posodobitev.
Karkoli vaŔ skript izpiŔe v stdout
, se prenese na odjemalca.
Naslednja stvar, ki jo boste opazili, je sporoÄilo o napaki.
[POLICY] Your message is not formatted correctly
error: hooks/update exited with error code 1
error: hook declined to update refs/heads/master
Prva vrstica je bila izpisana s strani vas, ostali dve pa sta sporoÄili Git, ki vam sporoÄata, da se je posodobitveni skript zakljuÄil z neniÄelno vrednostjo, zaradi Äesar vaÅ”a sprememba ni bila sprejeta. Nazadnje imate to:
To git@gitserver:project.git
! [remote rejected] master -> master (hook declined)
error: failed to push some refs to 'git@gitserver:project.git'
Videli boste sporoÄilo zavrnitve daljave za vsako referenco, ki jo je vaÅ”a kljuka zavrnila, in sporoÄilo vam pove, da je bilo zavrnjeno posebej zaradi neuspeha funkcije kljuke.
Äe nekdo poskusi urediti datoteko, do katere nima dostopa, in nato potisne potrditev, ki to vsebuje, bo videl nekaj podobnega.
Na primer, Äe avtor dokumentacije poskusi potisniti potrditev, ki spreminja nekaj v imeniku lib
, bo videl naslednje:
[POLICY] You do not have access to push to lib/test.rb
Od tega trenutka naprej, dokler je skript update
tam in je izvrÅ”ljiv, vaÅ” repozitorij ne bo nikoli imel sporoÄil potrditve, ki ne bi imela vaÅ”ega vzorca in vaÅ”i uporabniki bodo v peskovniku.
Kljuke na strani odjemalca
Slaba stran tega pristopa je pritoževanje, ki se bo neizogibno pojavilo, ko bodo zavrnjeni poskusi uporabnikov, da potisnejo potrditev. Zavrnitev skrbno oblikovanega dela v zadnjem trenutku je lahko izjemno frustrirajoÄa in zmedena; in poleg tega bodo morali urediti svojo zgodovino, da jo popravijo, kar ni vedno enostavno.
ReŔitev te dileme je zagotoviti nekaj kljuk na strani odjemalca, ki jih lahko uporabniki zaženejo, da jih obvestijo, ko delajo nekaj, kar bo strežnik verjetno zavrnil.
Tako lahko popravijo morebitne težave pred potrditvijo in preden te težave postanejo težje za popravek.
Ker se kljuke ne prenaÅ”ajo s klonom projekta, morate te skripte razdeliti na drug naÄin in jih nato kopirati vaÅ”im uporabnikom v njihovo mapo .git/hooks
ter jih narediti izvrŔljive.
Te kljuke lahko razdelite znotraj projekta ali v loÄenem projektu, vendar Git jih ne bo samodejno nastavil.
ZaÄeti morate tako, da preverite sporoÄilo potrditve takoj, preden se posname vsaka potrditev, tako da veste, da strežnik ne bo zavrnil vaÅ”ih sprememb zaradi slabo oblikovanih sporoÄil potrditev.
Za to lahko dodate kljuko commit-msg
.
Äe ima kljuka funkcijo, da bere sporoÄilo iz datoteke, ki se poda kot prvi argument, in ga primerja z vzorcem, lahko prisilite Git, da prekine potrditev, Äe se prileganja ne najdejo:
#!/usr/bin/env ruby
message_file = ARGV[0]
message = File.read(message_file)
$regex = /\[ref: (\d+)\]/
if !$regex.match(message)
puts "[POLICY] Your message is not formatted correctly"
exit 1
end
Äe je ta skript v .git/hooks/commit-msg
in je izvrŔljiv ter potem naredite potrditev z besedilom, ki ni pravilno oblikovano, boste videli to:
$ git commit -am 'Test'
[POLICY] Your message is not formatted correctly
Nobena potrditev ni bila dokonÄana na tej instanci. Vendar, Äe vaÅ”e sporoÄilo vsebuje ustrezen vzorec, vam bo Git dovolil potrditi:
$ git commit -am 'Test [ref: 132]'
[master e05c914] Test [ref: 132]
1 file changed, 1 insertions(+), 0 deletions(-)
Naslednji korak je, da se prepriÄate, da ne spreminjate datotek, ki so zunaj obsega ACL.
Äe v mapi .git
vaŔega projekta obstaja kopija datoteke ACL, ki ste jo uporabljali prej, potem vam bo naslednji skript pre-commit
uveljavil te omejitve:
#!/usr/bin/env ruby
$user = ENV['USER']
# [ insert acl_access_data method from above ]
# only allows certain users to modify certain subdirectories in a project
def check_directory_perms
access = get_acl_access_data('.git/acl')
files_modified = `git diff-index --cached --name-only HEAD`.split("\n")
files_modified.each do |path|
next if path.size == 0
has_file_access = false
access[$user].each do |access_path|
if !access_path || (path.index(access_path) == 0)
has_file_access = true
end
if !has_file_access
puts "[POLICY] You do not have access to push to #{path}"
exit 1
end
end
end
check_directory_perms
Tole je približno enak skript kot tisti na strežniku, vendar z dvema pomembnima razlikama.
Prva je, da je datoteka ACL na drugem mestu, ker ta skript teÄe iz delovnega imenika, ne iz imenika .git
.
Pot do datoteke ACL morate spremeniti iz:
access = get_acl_access_data('acl')
na to:
access = get_acl_access_data('.git/acl')
Druga pomembna razlika je naÄin, kako pridobite seznam datotek, ki so bile spremenjene. Ker metoda na strežniku gleda na dnevnik potrditev in ta potrditev Å”e ni zabeležena, morate seznam datotek dobiti iz podroÄja priprave. Namesto tega:
files_modified = `git log -1 --name-only --pretty=format:'' #{ref}`
morate uporabiti:
files_modified = `git diff-index --cached --name-only HEAD`
Vendar to sta edini dve razlikiāāāsicer skript deluje na enak naÄin.
Eno opozorilo je, da od vas priÄakuje, da teÄe lokalno kot isti uporabnik kot tisti, ki potiska na oddaljeno napravo.
Äe je to drugaÄe, morate roÄno nastaviti spremenljivko $user
.
Druga stvar, ki jo lahko storimo tukaj, je, da poskrbimo, da uporabnik ne potiska ne-fast-forward referenc. Za referenco, ki ni fast-forward, morate potrditve ponovno bazirati, ki ste jih že potisnili na strežnik, ali pa poskuŔate potisniti drugo lokalno vejo na isto oddaljeno vejo.
Predvidevamo, da je strežnik že nastavljen z receive.denyDeletes
in receive.denyNonFastForwards
za uveljavitev tega pravilnika, zato lahko poskuŔamo ujeti le nenamerna ponovna baziranja že potisnjenih potrditev.
Tu je primer skripta pre-rebase
, ki preverja to.
Dobimo seznam vseh potrditev, ki jih nameravate prepisati in preverimo, ali obstajajo v kateri od vaŔih oddaljenih referenc.
Äe vidi, da je ena od teh dosegljiva iz ene od vaÅ”ih oddaljenih referenc, se ponovno baziranje prekine.
#!/usr/bin/env ruby
base_branch = ARGV[0]
if ARGV[1]
topic_branch = ARGV[1]
else
topic_branch = "HEAD"
end
target_shas = `git rev-list #{base_branch}..#{topic_branch}`.split("\n")
remote_refs = `git branch -r`.split("\n").map { |r| r.strip }
target_shas.each do |sha|
remote_refs.each do |remote_ref|
shas_pushed = `git rev-list ^#{sha}^@ refs/remotes/#{remote_ref}`
if shas_pushed.split("\n").include?(sha)
puts "[POLICY] Commit #{sha} has already been pushed to #{remote_ref}"
exit 1
end
end
end
Ta skript uporablja sintakso, ki ni bila pokrita v Izbira revizije. Z naslednjim pogonom dobite seznam potrditev, ki ste jih že potisnili:
`git rev-list ^#{sha}^@ refs/remotes/#{remote_ref}`
Sintaksa SHA^@
se doloÄa na vse nadrejene te potrditve.
IÅ”Äete katerokoli potrditev, ki je dostopna iz zadnje potrditve na oddaljenem mestu in ki ni dostopna iz nobene nadrejene katerega koli SHA-1, ki ga poskuÅ”ate potisniti gorāāākar pomeni, da gre za hitro previjanje naprej (fast-forward).
Glavna slabost tega pristopa je, da lahko postane zelo poÄasen in je pogosto nepotrebenāāāÄe ne poskuÅ”ate siliti potiskanja z uporabo -f
, vas bo strežnik opozoril in ne bo sprejel potiska.
Vendar je to zanimiva vaja in v teoriji vam lahko pomaga se izogniti ponovnemu baziranju, ki ga kasneje morda morate popraviti.