Legen Sie die Git-Konfigurationswerte für alle untergeordneten Ordner fest

77

Ich weiß, dass es möglich ist, Konfigurationen pro Repo festzulegen, die die Konfiguration auf Benutzerebene /path/to/my/repo/.gitconfigüberschreiben (dh überschreiben ~/.gitconfig). Ist es möglich, Git-Konfigurationen festzulegen, die die Einstellungen auf Benutzerebene für alle untergeordneten Ordner eines bestimmten Ordners überschreiben? Dh ich habe

|--topLevelFolder1
|--\
|   ---.gitconfig_override
|--\
|   ---childFolder1
|       \---[...]
|--\
|   ---childFolder2
|       \---[...]

Und ich möchte die definierten Einstellungen .gitconfig_overridein anzuwenden childFolder1und childFolder2.

Meine Motivation dafür ist folgende: Ich habe einen Arbeitslaptop, den ich auch in meiner Freizeit für persönliche Projekte benutze. Mein gesamter Arbeitscode ist in einem einzigen Ordner verschachtelt. Wenn ich zu Git-Repos drücke, muss ich dies mit meiner Arbeitsperson tun - Arbeitsanmeldung anstelle von Name und Arbeits-E-Mail. Wenn ich zu meinen persönlichen (Github-) Repos gehe, möchte ich dies mit meinem richtigen Namen und meiner persönlichen E-Mail-Adresse tun.

Andere mögliche Lösungen, an die ich gedacht habe (und Probleme):

  • Erstellen Sie separate Benutzer für "Arbeiten" und "Spielen", stellen Sie die Einstellungen auf Benutzerebene entsprechend ein und melden Sie sich als geeigneter Benutzer an, wenn ich den Kontext wechsle (Ärger, und ich könnte leicht vergessen, zu wechseln).
  • Erstellen Sie ein Skript, das in "workFolder" nach Git-Repos sucht und deren .gitconfig-Dateien hinzufügt / aktualisiert, um die entsprechenden Details zu speichern (wenn ich ein Repo erstelle und vergesse, das Skript vor dem Push auszuführen, werde ich als falsche Person pushen).
  • "hack" git so, dass jedes Mal, wenn ein Repo erstellt wird, der Dateipfad überprüft und gegebenenfalls die .gitconfig-Datei aktualisiert wird (kompliziert, chaotisch und mit ziemlicher Sicherheit die falsche Vorgehensweise - außerdem hätte ich das nicht erster Hinweis, wie es geht!)

Ich habe diese Frage überprüft , die nur Lösungen für einzelne Repos zu enthalten scheint, nicht für mehrere. Hoffentlich wird jemand diese Frage sehen, der diese verpasst hat!

scubbo
quelle
Arbeiten Sie am selben Repository wie "work you" und "personal you"? Wenn nicht, enthält die Frage, auf die Sie verlinkt haben, die Antwort, die ich geben würde. Ihre --globalBenutzereinstellungen sollten die Identität enthalten, die Sie häufiger verwenden. Jedes Repository, das die andere Identität verwenden sollte , sollte user.nameund user.emailentsprechend eingestellt.
Chris
Ich werde niemals mit zwei verschiedenen Benutzern im selben Repo arbeiten - jedes Repo wird entweder "Arbeit" oder "Zuhause" sein - aber das Problem ergibt sich aus der Tatsache, dass ich (zumindest für die Arbeit) ungefähr 35 Repos habe und füge regelmäßig hinzu. Ich könnte die user.nameund user.email-Einstellungen in jedem der vorhandenen Repos hinzufügen und ein Cron-Skript einrichten, um sie zu neu hinzugefügten Repos hinzuzufügen, aber es wäre viel einfacher, wenn ich sie an einer einzigen Stelle festlegen könnte, die auf eine beliebige Stelle "herunterfiltert" Repos in untergeordneten Ordnern.
Scubbo

Antworten:

32

BEARBEITEN: Git 2.13 führte bedingte Includes ein , die genau dieses Problem lösen sollen.

Meine ursprüngliche Antwort wird aus Gründen der Geschichte unten beibehalten (und Benutzer, die an älteren Versionen von git festhalten).

===================================

Das genaue gewünschte Verhalten wird nicht unterstützt, basierend auf dem Lesen der Manpage gitconfig.

Wie jedoch von git 1.7.12 liest Git Konfigurationsdaten aus vier verschiedenen Quellen , von denen zwei benutzerspezifisch sind:

$XDG_CONFIG_HOME/git/configund ~/.gitconfig. Einträge in ~/.gitconfigüberschreiben Einträge in $XDG_CONFIG_HOME/git/config.

Das heißt, Sie können Ihre persönliche gitconfig unter speichern $XDG_CONFIG_HOME/git/configund maschinenspezifische Überschreibungen einfügen ~/.gitconfig. Etwas wie

[user]
    email = [email protected]

in ~/.gitconfigsollte Ihren E-Mail-Fall abdecken.

Beachten Sie, dass git sucht, wenn $ XDG_CONFIG_HOME nicht festgelegt ist ~/.config/git/config.

Dies funktioniert gut für mich, da ich immer nur zwei persönliche Repos auf Arbeitsmaschinen habe (meine Emacs-Konfiguration und meine Punktedateien). Wenn Sie Ihren Arbeitsmaschinen häufig persönliche Repos hinzufügen, ist dies möglicherweise nicht gut genug für Sie.

In diesem Fall sind benutzerdefinierte Wrapper vorhanden git initund git clonedie beste Wahl.

Jede Binärdatei auf Ihrem $ PATH, deren Name mit 'git- *' übereinstimmt, kann als git-Befehl aufgerufen werden. Sie benötigen also nur ein Paar Shell-Skripte, die den ursprünglichen Befehl mit allen übergebenen Argumenten aufrufen, und kopieren dann die richtige Konfigurationsdatei in .git/config.

NateEag
quelle
Einige Git-Einstellungen können durch Festlegen von Umgebungsvariablen gesteuert werden. Sie überschreiben Werte aus der Konfigurationsdatei. Ein sehr gutes Dienstprogramm zum Festlegen / Deaktivieren von env-Variablen pro Verzeichnishierarchie ist , direnv. Siehe meine Antwort unten für alle Details.
Ajay M
87

Wie in NateEags Bearbeitung erwähnt , sind die Conditional Includes von git perfekt dafür. Da diese Antwort die für Leute mit Git <2.13 ist, ist hier eine für diejenigen, die neuere Versionen haben.

Erstellen Sie zunächst irgendwo eine neue Konfigurationsdatei mit den Einstellungen, die in den Unterordnern wirksam werden sollen. Verwenden Sie beispielsweise die Ordner der ursprünglichen Frage ~/topLevelFolder1/.gitconfig_include

In ~/.gitconfighinzufügen:

[includeIf "gitdir:~/toplevelFolder1/"]
    path = ~/topLevelFolder1/.gitconfig_include

Jeder Unterordner von ~/topLevelFolder1wird jetzt die Konfiguration in enthalten ~/toplevelFolder1/.gitconfig_include- es ist nicht erforderlich, .git/configdas Repo in jedem Unterordner manuell zu ändern . (Dies überschreibt nicht alles, was in der Unterordner-Konfiguration enthalten ist - es wird nur hinzugefügt , wie "Einschließen" impliziert.)

Ayulin
quelle
9
Der abschließende Schrägstrich ( /) in der gitdirBedingung ist wichtig.
stefanct
2
Dies sollte als die richtige Antwort auf diese Frage markiert werden. Dank der Erwähnung von includeIf(und ein wenig Versuch und Irrtum) habe ich jetzt einen bestimmten Ordnerbaum auf meinem Arbeits-PC konfiguriert, in dem jede Git-Aktion mich als mein persönliches Konto identifiziert und meinen persönlichen SSH-Schlüssel zusammen mit einem verwendet ähnlicher Ordner für Arbeiten auf meinem persönlichen PC. In der Zwischenzeit verwendet der Rest jedes Systems auf beiden Computern die entsprechende E-Mail, den Namen und den SSH-Schlüssel. Ich wünschte nur, ich würde diese Antwort mehr als einmal
Ist das ifTeil wirklich notwendig? Wenn der referenzierte pathnicht vorhanden ist, scheint der Eintrag ignoriert zu werden.
Oliver Pearmain
Wenn nur git nur das logische getan hätte und über den Baum nach .gitVerzeichnissen in jedem übergeordneten Verzeichnis gesucht hätte ...
Ian Kemp
@OliverPearmain Das Ziel ist nicht, die Datei einzuschließen, falls vorhanden, sondern die Datei einzuschließen, wenn Sie sich in einem Repo unter dem angegebenen Pfad befinden.
Patrick
14

Mit dem direnvBefehl können Sie Umgebungsvariablen festlegen, die für alle untergeordneten Ordner gelten. Sie können sich an einer beliebigen Stelle in dieser Verzeichnishierarchie befinden. Wenn die Git-Einstellung, die Sie festlegen möchten, von einer Umgebungsvariablen gesteuert werden kann, haben Sie Glück.

Lesen Sie die direnvBasisseite http://direnv.net/ , um sie für Ihre Shell einzurichten. Für zsh war es so einfach, diese Linie am unteren Rand von my zu kleben .zshrcund die Shell neu zu starten.

eval "$(direnv hook zsh)"

Überprüfen Sie, ob die gewünschte Git-Einstellung von einer Umgebungsvariablen gesteuert werden kann. Es scheint, dass Sie author.emailfür einen bestimmten Verzeichnisbaum steuern möchten , der von der Umgebungsvariablen gesteuert wird GIT_AUTHOR_EMAIL. Beachten Sie, dass Umgebungsvariablen Vorrang vor config haben. Eine vollständige Liste der von git unterstützten Umgebungsvariablen finden Sie hier: https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables

As, direnv‚s - Seite gibt an , eine Datei mit dem Namen, .envrcan der Wurzel der Hierarchie; in deinem Fall,topLevelFolder1

Zum Beispiel:

echo export [email protected] > .envrc

"Erlaube" der Umgebung: direnv allow .Das war's!

Jedes Mal, wenn Sie in die Hierarchie springen, direnvfinden Sie die besagte .envrcDatei und laden sie.

$ cd ~/topLevelFolder1/childFolder1/project_name
direnv: loading ../../../.envrc
direnv: export +GIT_AUTHOR_EMAIL

$ echo ${GIT_AUTHOR_EMAIL}
[email protected]

Wechseln Sie aus der Verzeichnisstruktur und direnventladen Sie diese Variablen

cd ~
direnv: unloading
Ajay M.
quelle
7

Der [include]Abschnitt in git config ( .git/config, ~/.gitconfig...) ist genau das , wonach Sie suchen.

[include]
    path = /path/to/foo.inc ; include by absolute path
    path = foo ; expand "foo" relative to the current file
    path = ~/foo ; expand "foo" in your $HOME directory

Siehe ausführlich beantwortete Frage: Ist es möglich, eine Datei in Ihre .gitconfig aufzunehmen?

Siehe git-config-Dokumentation: http://git-scm.com/docs/git-config#_includes

BEARBEITEN

Hinzufügen childFolder1/.git/configund childFolder2/.git/config:

[include]
    path = ../.gitconfig_override
barthel
quelle
2
OK - das löst also das Problem, nur das user.nameund user.emailan einem Ort (in ../.gitconfig_override) zu definieren, aber ich denke nicht, dass es tatsächlich die ursprüngliche Frage beantwortet? Wenn childFolder1und untergeordnet childFolder2sind parentFolder, habe ich nach einer Möglichkeit gesucht, Konfigurationswerte festzulegen parentFolder, die auf alle in untergeordneten Ordnern verwurzelten Repos herunterfiltern.
Scubbo
1
Wie NateEag betonte, wurde dies nur in Git 2.13 eingeführt. (Git 2.13.0 stammt vom 9. Mai 2017.) Wenn sich jemand, der diese Antwort liest, fragt, warum sie bei ihm nicht funktioniert, verwendet er möglicherweise eine ältere Version von Git.
Sampablokuper
HINWEIS: Ich bin kürzlich auf ein Problem gestoßen, bei dem diese bedingten Includes nicht berücksichtigt wurden. Das Problem war, dass Git (zumindest meine Installation - 2.17.0 unter MacOSX) anscheinend einen abschließenden Schrägstrich in Verzeichnispfaden erfordert.
Scubbo