Git
Bestanden en mappen negeren
Zoeken…
Invoering
Dit onderwerp illustreert hoe te voorkomen dat ongewenste bestanden (of bestandswijzigingen) worden toegevoegd aan een Git-repo. Er zijn verschillende manieren (globaal of lokaal .gitignore
, .git/exclude
, git update-index --assume-unchanged
en git update-index --skip-tree
), maar houd in gedachten dat Git inhoud beheert, wat betekent: negeren negeert eigenlijk de inhoud van een map (bijv. bestanden). Een lege map wordt standaard genegeerd, omdat deze toch niet kan worden toegevoegd.
Bestanden en mappen negeren met een .gitignore-bestand
Je kunt Git bepaalde bestanden en mappen laten negeren - dat wil zeggen ze uitsluiten van het volgen door Git - door een of meer .gitignore
bestanden in je repository te maken.
In softwareprojecten bevat .gitignore
meestal een lijst met bestanden en / of mappen die tijdens het .gitignore
of tijdens runtime worden gegenereerd. Vermeldingen in het .gitignore
bestand kunnen namen of paden bevatten die verwijzen naar:
- tijdelijke bronnen zoals caches, logbestanden, gecompileerde code, enz.
- lokale configuratiebestanden die niet met andere ontwikkelaars mogen worden gedeeld
- bestanden die geheime informatie bevatten, zoals inlogwachtwoorden, sleutels en inloggegevens
Wanneer de regels worden gemaakt in de map op het hoogste niveau, zijn ze recursief van toepassing op alle bestanden en submappen in de hele repository. Wanneer de regels in een submap worden gemaakt, zijn de regels van toepassing op die specifieke map en de submappen.
Wanneer een bestand of map wordt genegeerd, is dit niet:
- gevolgd door Git
- gerapporteerd door commando's zoals
git status
ofgit diff
- geënsceneerd met opdrachten zoals
git add -A
In het ongewone geval dat u bijgehouden bestanden moet negeren, moet u extra voorzichtig zijn. Zie: Negeer bestanden die al zijn vastgelegd in een Git-repository .
Voorbeelden
Hier zijn een aantal generieke voorbeelden van regels in een .gitignore
bestand, gebaseerd op glob file patronen :
# Lines starting with `#` are comments.
# Ignore files called 'file.ext'
file.ext
# Comments can't be on the same line as rules!
# The following line ignores files called 'file.ext # not a comment'
file.ext # not a comment
# Ignoring files with full path.
# This matches files in the root directory and subdirectories too.
# i.e. otherfile.ext will be ignored anywhere on the tree.
dir/otherdir/file.ext
otherfile.ext
# Ignoring directories
# Both the directory itself and its contents will be ignored.
bin/
gen/
# Glob pattern can also be used here to ignore paths with certain characters.
# For example, the below rule will match both build/ and Build/
[bB]uild/
# Without the trailing slash, the rule will match a file and/or
# a directory, so the following would ignore both a file named `gen`
# and a directory named `gen`, as well as any contents of that directory
bin
gen
# Ignoring files by extension
# All files with these extensions will be ignored in
# this directory and all its sub-directories.
*.apk
*.class
# It's possible to combine both forms to ignore files with certain
# extensions in certain directories. The following rules would be
# redundant with generic rules defined above.
java/*.apk
gen/*.class
# To ignore files only at the top level directory, but not in its
# subdirectories, prefix the rule with a `/`
/*.apk
/*.class
# To ignore any directories named DirectoryA
# in any depth use ** before DirectoryA
# Do not forget the last /,
# Otherwise it will ignore all files named DirectoryA, rather than directories
**/DirectoryA/
# This would ignore
# DirectoryA/
# DirectoryB/DirectoryA/
# DirectoryC/DirectoryB/DirectoryA/
# It would not ignore a file named DirectoryA, at any level
# To ignore any directory named DirectoryB within a
# directory named DirectoryA with any number of
# directories in between, use ** between the directories
DirectoryA/**/DirectoryB/
# This would ignore
# DirectoryA/DirectoryB/
# DirectoryA/DirectoryQ/DirectoryB/
# DirectoryA/DirectoryQ/DirectoryW/DirectoryB/
# To ignore a set of files, wildcards can be used, as can be seen above.
# A sole '*' will ignore everything in your folder, including your .gitignore file.
# To exclude specific files when using wildcards, negate them.
# So they are excluded from the ignore list:
!.gitignore
# Use the backslash as escape character to ignore files with a hash (#)
# (supported since 1.6.2.1)
\#*#
De meeste .gitignore
bestanden zijn standaard in verschillende talen, dus om te beginnen, hier is een aantal voorbeeld .gitignore
bestanden die zijn gerangschikt per taal van waaruit ze naar uw project moeten klonen of kopiëren / wijzigen. Als alternatief kunt u voor een nieuw project overwegen een startbestand automatisch te genereren met behulp van een online tool .
Andere vormen van .gitignore
.gitignore
bestanden zijn bedoeld om te worden .gitignore
als onderdeel van de repository. Als u bepaalde bestanden wilt negeren zonder de negeerregels te gebruiken, zijn hier enkele opties:
- Bewerk het
.git/info/exclude
bestand (met dezelfde syntaxis als.gitignore
). De regels zullen algemeen zijn in het bereik van de repository; - Stel een globaal gitignore-bestand in dat negeerregels zal toepassen op al uw lokale repositories:
Verder kun je lokale wijzigingen in bijgehouden bestanden negeren zonder de globale git-configuratie te wijzigen met:
-
git update-index --skip-worktree [<file>...]
: voor kleine lokale aanpassingen -
git update-index --assume-unchanged [<file>...]
: voor productie gereed, niet-veranderende bestanden stroomopwaarts
Zie meer details over verschillen tussen de laatste vlaggen en de git update-index
documentatie voor verdere opties.
Genegeerde bestanden opschonen
Je kunt git clean -X
om genegeerde bestanden op te git clean -X
:
git clean -Xn #display a list of ignored files
git clean -Xf #remove the previously displayed files
Opmerking: -X
(hoofdletters) ruimt alleen genegeerde bestanden op. Gebruik -x
(geen hoofdletters) om ook niet-bijgehouden bestanden te verwijderen.
Zie de git clean
documentatie voor meer details.
Zie de Git-handleiding voor meer details.
Uitzonderingen in een .gitignore-bestand
Als u bestanden negeert met behulp van een patroon maar uitzonderingen hebt, moet u een uitroepteken (!) Voor de uitzondering plaatsen. Bijvoorbeeld:
*.txt
!important.txt
In het bovenstaande voorbeeld wordt Git geïnstrueerd om alle bestanden met de extensie .txt
te negeren, behalve de bestanden met de naam important.txt
.
Als het bestand in een genegeerde map staat, kunt u het NIET zo gemakkelijk opnieuw opnemen:
folder/
!folder/*.txt
In dit voorbeeld blijven alle .txt-bestanden in de map genegeerd.
De juiste manier is om de map zelf opnieuw op te nemen op een afzonderlijke regel en vervolgens alle bestanden in de folder
negeren op *
, ten slotte de *.txt
in de folder
, als volgt:
!folder/
folder/*
!folder/*.txt
Opmerking : voeg voor bestandsnamen die met een uitroepteken beginnen twee uitroeptekens toe of ontsnap met het \
-teken:
!!includethis
\!excludethis
Een globaal .gitignore-bestand
Om Git bepaalde bestanden in alle repositories te laten negeren, kun je een globale .gitignore maken met de volgende opdracht in je terminal of opdrachtprompt:
$ git config --global core.excludesfile <Path_To_Global_gitignore_file>
Git zal dit nu gebruiken naast het eigen .gitignore- bestand van elke repository. Regels hiervoor zijn:
- Als het lokale
.gitignore
bestand expliciet een bestand bevat terwijl de globale.gitignore
negeert, heeft de lokale.gitignore
prioriteit (het bestand wordt opgenomen) - Als de repository op meerdere machines wordt gekloond, moet de globale
.gigignore
op alle machines worden geladen of op zijn minst worden opgenomen, omdat de genegeerde bestanden naar de repo worden gepusht, terwijl de pc met de globale.gitignore
deze niet zou bijwerken . Dit is de reden waarom een repo-specifieke.gitignore
een beter idee is dan een wereldwijd idee als het project door een team wordt bewerkt
Dit bestand is een goede plek om platform-, machine- of gebruikersspecifieke .DS_Store
te bewaren, bijv. OSX .DS_Store
, Windows Thumbs.db
of Vim *.ext~
en *.ext.swp
negeert als je die niet in de repository wilt houden . Dus een teamlid dat werkt met OS X kan alle .DS_STORE
en _MACOSX
(wat eigenlijk nutteloos is), terwijl een ander teamlid op Windows alle thumbs.bd
kan negeren.
Negeer bestanden die al zijn toegewezen aan een Git-repository
Als je al een bestand hebt toegevoegd aan je Git-repository en nu wilt stoppen met het volgen ervan (zodat het in toekomstige commits niet aanwezig zal zijn), kun je het uit de index verwijderen:
git rm --cached <file>
Dit zal het bestand uit de repository verwijderen en voorkomen dat verdere wijzigingen worden gevolgd door Git. De optie --cached
zorgt ervoor dat het bestand niet fysiek wordt verwijderd.
Merk op dat eerder toegevoegde inhoud van het bestand nog steeds zichtbaar is via de Git-geschiedenis.
Houd er rekening mee dat als iemand anders uit de repository haalt nadat u het bestand uit de index heeft verwijderd, zijn kopie fysiek wordt verwijderd .
Je kunt Git doen doen alsof de versie van de werkmap van het bestand up-to-date is en in plaats daarvan de indexversie lezen (waardoor wijzigingen daarin worden genegeerd) met het bit " werktijd overslaan ":
git update-index --skip-worktree <file>
Het schrijven wordt niet beïnvloed door dit bit, inhoudveiligheid is nog steeds de eerste prioriteit. Je zult nooit je kostbare genegeerde veranderingen verliezen; aan de andere kant conflicteert dit bit met stashing: gebruik dit om dit bit te verwijderen
git update-index --no-skip-worktree <file>
Het wordt soms ten onrechte aanbevolen om tegen Git te liegen en ervan uit te gaan dat het bestand ongewijzigd is zonder het te onderzoeken. Het ziet er op het eerste gezicht uit als het negeren van verdere wijzigingen aan het bestand, zonder het uit de index te verwijderen:
git update-index --assume-unchanged <file>
Dit zal git dwingen om elke wijziging in het bestand te negeren (houd er rekening mee dat als je wijzigingen in dit bestand ophaalt, of je stopt het, je genegeerde wijzigingen verloren gaan )
Als je wilt dat git dit bestand weer "verzorgt", voer je de volgende opdracht uit:
git update-index --no-assume-unchanged <file>
Controleren of een bestand wordt genegeerd
Het git check-ignore
commando rapporteert over bestanden die door Git worden genegeerd.
Je kunt bestandsnamen doorgeven op de opdrachtregel en git check-ignore
zal de bestandsnamen weergeven die worden genegeerd. Bijvoorbeeld:
$ cat .gitignore
*.o
$ git check-ignore example.o Readme.md
example.o
Hier zijn alleen * .o-bestanden gedefinieerd in .gitignore, dus Readme.md wordt niet vermeld in de uitvoer van git check-ignore
.
Als je de regel wilt zien waarvan .gitignore verantwoordelijk is voor het negeren van een bestand, voeg je -v toe aan de opdracht git check-ignore:
$ git check-ignore -v example.o Readme.md
.gitignore:1:*.o example.o
Vanaf Git 1.7.6 kun je ook de git status --ignored
gebruiken om genegeerde bestanden te zien. Meer informatie hierover vindt u in de officiële documentatie of in Zoeken naar bestanden die zijn genegeerd door .gitignore .
Bestanden in submappen negeren (meerdere gitignore-bestanden)
Stel dat u een repositorystructuur als deze heeft:
examples/
output.log
src/
<files not shown>
output.log
README.md
output.log
in de voorbeeldenmap is geldig en vereist voor het project om inzicht te krijgen terwijl degene onder src/
tijdens het debuggen is gemaakt en niet in de geschiedenis of een deel van de repository zou moeten staan.
Er zijn twee manieren om dit bestand te negeren. U kunt een absoluut pad in het .gitignore
bestand in de hoofdmap van de werkmap plaatsen:
# /.gitignore
src/output.log
U kunt ook een .gitignore
bestand maken in de src/
directory en het bestand negeren dat relatief is aan deze .gitignore
:
# /src/.gitignore
output.log
Een bestand in een willekeurige map negeren
Om een bestand foo.txt
in een willekeurige map te negeren, moet u gewoon de naam ervan schrijven:
foo.txt # matches all files 'foo.txt' in any directory
Als u het bestand alleen in een deel van de boom wilt negeren, kunt u de submappen van een specifieke map met **
patroon opgeven:
bar/**/foo.txt # matches all files 'foo.txt' in 'bar' and all subdirectories
Of u kunt een .gitignore
bestand maken in de bar/
map. Gelijk aan het vorige voorbeeld zou het maken van een bestandsbalk bar/.gitignore
met deze inhoud:
foo.txt # matches all files 'foo.txt' in any directory under bar/
Negeer bestanden lokaal zonder regels te negeren
.gitignore
negeert bestanden lokaal, maar het is bedoeld om te worden .gitignore
in de repository en gedeeld met andere bijdragers en gebruikers. U kunt een globale .gitignore
, maar dan zouden al uw repositories die instellingen delen.
Als je bepaalde bestanden in een repository lokaal wilt negeren en het bestand geen deel van een repository wilt maken, bewerk dan .git/info/exclude
in je repository.
Bijvoorbeeld:
# these files are only ignored on this repo
# these rules are not shared with anyone
# as they are personal
gtk_tests.py
gui/gtk/tests/*
localhost
pushReports.py
server/
Voorgevulde .gitignore-sjablonen
Als u niet zeker weet welke regels u in uw .gitignore
bestand moet opnemen, of als u gewoon algemeen geaccepteerde uitzonderingen aan uw project wilt toevoegen, kunt u een .gitignore
bestand kiezen of genereren:
Veel hostingservices zoals GitHub en BitBucket bieden de mogelijkheid om .gitignore
bestanden te genereren op basis van de programmeertalen en IDE's die u mogelijk gebruikt:
Volgende wijzigingen aan een bestand negeren (zonder het te verwijderen)
Soms wil je een bestand in Git hebben, maar negeer volgende wijzigingen.
Laat Git wijzigingen in een bestand of map negeren met behulp van update-index
:
git update-index --assume-unchanged my-file.txt
De bovenstaande opdracht geeft Git de opdracht om aan te nemen dat my-file.txt
niet is gewijzigd en om wijzigingen niet te controleren of te rapporteren. Het bestand is nog steeds aanwezig in de repository.
Dit kan handig zijn om standaardwaarden te bieden en lokale omgevingsoverschrijvingen mogelijk te maken, bijvoorbeeld:
# create a file with some values in cat <<EOF MYSQL_USER=app MYSQL_PASSWORD=FIXME_SECRET_PASSWORD EOF > .env # commit to Git git add .env git commit -m "Adding .env template" # ignore future changes to .env git update-index --assume-unchanged .env # update your password vi .env # no changes! git status
Slechts een deel van een bestand negeren [stub]
Soms wilt u misschien lokale wijzigingen in een bestand dat u niet wilt vastleggen of publiceren. Idealiter zouden lokale instellingen moeten worden geconcentreerd in een afzonderlijk bestand dat in .gitignore
kan worden geplaatst, maar soms als een oplossing op korte termijn kan het nuttig zijn om iets lokaal in een ingecheckt bestand te hebben.
Je kunt Git die regels "onzichtbaar maken" met een schoon filter. Ze zullen niet eens in diffs verschijnen.
Stel dat hier een fragment uit bestand file1.c
:
struct settings s;
s.host = "localhost";
s.port = 5653;
s.auth = 1;
s.port = 15653; // NOCOMMIT
s.debug = 1; // NOCOMMIT
s.auth = 0; // NOCOMMIT
U wilt NOCOMMIT
regels nergens publiceren.
Maak een "nocommit" -filter door dit toe te voegen aan het Git-configuratiebestand zoals .git/config
:
[filter "nocommit"]
clean=grep -v NOCOMMIT
Voeg dit toe (of maak dit) aan .git/info/attributes
of .gitmodules
:
file1.c filter=nocommit
En je NOCOMMIT-regels zijn verborgen voor Git.
Voorbehoud:
- Het gebruik van een schone filter vertraagt de verwerking van bestanden, vooral op Windows.
- De genegeerde regel kan uit het bestand verdwijnen wanneer Git deze bijwerkt. Het kan worden tegengegaan met een veegfilter, maar het is lastiger.
- Niet getest op Windows
Negeren van wijzigingen in bijgehouden bestanden. [stomp]
.gitignore en .git/info/exclude
werk uitsluiten alleen voor niet-bijgehouden bestanden.
Gebruik de opdracht update-index om de vlag voor het negeren van een bijgehouden bestand in te stellen:
git update-index --skip-worktree myfile.c
Om dit terug te zetten, gebruik:
git update-index --no-skip-worktree myfile.c
Je kunt dit fragment toevoegen aan je globale git-configuratie om handiger git hide
, git unhide
en git hidden
opdrachten te hebben:
[alias]
hide = update-index --skip-worktree
unhide = update-index --no-skip-worktree
hidden = "!git ls-files -v | grep ^[hsS] | cut -c 3-"
U kunt ook de optie --assume-ongewijzigd met de update-indexfunctie gebruiken
git update-index --assume-unchanged <file>
Gebruik als u dit bestand opnieuw wilt bekijken voor de wijzigingen
git update-index --no-assume-unchanged <file>
Wanneer de vlag --assume-ongewijzigd is opgegeven, belooft de gebruiker het bestand niet te wijzigen en laat Git aan dat het werkende boombestand overeenkomt met wat is opgenomen in de index. Git zal mislukken in het geval dat dit bestand in de index moet worden gewijzigd bijv. bij het samenvoegen van een commit; dus in het geval dat het veronderstelde niet-bijgehouden bestand stroomopwaarts wordt gewijzigd, moet u de situatie handmatig verwerken. De nadruk ligt in dit geval op de prestaties.
Hoewel de vlag --skip-worktree nuttig is wanneer je git instrueert nooit een specifiek bestand aan te raken omdat het bestand lokaal zal worden gewijzigd en je niet per ongeluk de wijzigingen wilt doorvoeren (dat wil zeggen configuratie / eigenschappenbestand geconfigureerd voor een bepaald milieu). Skip-worktree heeft voorrang op veronderstellen-onveranderd wanneer beide zijn ingesteld.
Wis al vastgelegde bestanden, maar opgenomen in .gitignore
Soms gebeurt het dat een bestand werd bijgehouden door git, maar op een later tijdstip werd toegevoegd aan .gitignore, om te stoppen met het volgen. Het is een veel voorkomend scenario om dergelijke bestanden op te ruimen voordat ze worden toegevoegd aan .gitignore. In dit geval blijft het oude bestand rondhangen in de repository.
Om dit probleem op te lossen, zou men een "dry-run" verwijdering van alles in de repository kunnen uitvoeren, gevolgd door het opnieuw toevoegen van alle bestanden. Zolang u geen openstaande wijzigingen heeft en de parameter --cached
is doorgegeven, is deze opdracht redelijk veilig om uit te voeren:
# Remove everything from the index (the files will stay in the file system)
$ git rm -r --cached .
# Re-add everything (they'll be added in the current state, changes included)
$ git add .
# Commit, if anything changed. You should see only deletions
$ git commit -m 'Remove all files that are in the .gitignore'
# Update the remote
$ git push origin master
Maak een lege map
Het is niet mogelijk om een lege map in Git toe te voegen en te plegen vanwege het feit dat Git bestanden beheert en hun map eraan toevoegt, wat commits afslankt en de snelheid verbetert. Om dit te omzeilen, zijn er twee methoden:
Methode één: .gitkeep
Een hack om dit te omzeilen is om een .gitkeep
bestand te gebruiken om de map voor Git te registreren. Maak hiervoor de gewenste map en voeg een .gitkeep
bestand toe aan de map. Dit bestand is leeg en heeft geen ander doel dan alleen het registreren van de map. Om dit te doen in Windows (die lastige bestandsnaamconventies heeft) open je git bash in de map en voer je de opdracht uit:
$ touch. gitkeep
Met deze opdracht maakt u gewoon een leeg .gitkeep
bestand in de huidige map
Methode twee: dummy.txt
Een andere hack hiervoor lijkt erg op het bovenstaande en dezelfde stappen kunnen worden gevolgd, maar in plaats van een .gitkeep
, gebruik gewoon een dummy.txt
. Dit heeft de toegevoegde bonus dat het gemakkelijk in Windows kan worden gemaakt met behulp van het contextmenu. En je kunt er ook grappige berichten in achterlaten. Je kunt ook het .gitkeep
bestand gebruiken om de lege map bij te houden. .gitkeep
normaal gesproken een leeg bestand dat wordt toegevoegd om de lege directoy te volgen.
Zoeken naar bestanden genegeerd door .gitignore
Je kunt alle bestanden die door git worden genegeerd in de huidige map weergeven met de opdracht:
git status --ignored
Dus als we een repository-structuur hebben zoals deze:
.git
.gitignore
./example_1
./dir/example_2
./example_2
... en .gitignore bestand met:
example_2
... dan is het resultaat van de opdracht:
$ git status --ignored
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
.example_1
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
dir/
example_2
Als u recursief genegeerde bestanden in mappen wilt weergeven, moet u een extra parameter gebruiken - --untracked-files=all
Resultaat ziet er als volgt uit:
$ git status --ignored --untracked-files=all
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
example_1
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
dir/example_2
example_2