Browse files

Merge from progit/master

  • Loading branch information...
2 parents 0d7cc6a + 0376aa7 commit 3d935365b932de2b0ff38c96773572f1bc93b408 @afgomez afgomez committed Jan 28, 2010
Showing with 10,516 additions and 830 deletions.
  1. +991 −0 de/07-customizing-git/01-chapter7.markdown
  2. +225 −99 de/08-git-and-other-scms/01-chapter8.markdown
  3. +18 −7 de/NOTES
  4. +2 −2 de/STATUS
  5. 0 {es-es → es}/01-introduction/01-chapter1.markdown
  6. +44 −10 {es-es → es}/02-git-basics/01-chapter2.markdown
  7. 0 {es-es → es}/03-git-branching/01-chapter3.markdown
  8. 0 {es-es → es}/04-git-server/01-chapter4.markdown
  9. 0 {es-es → es}/05-distributed-git/01-chapter5.markdown
  10. 0 {es-es → es}/06-git-tools/01-chapter6.markdown
  11. 0 {es-es → es}/07-customizing-git/01-chapter7.markdown
  12. 0 {es-es → es}/08-git-and-other-scms/01-chapter8.markdown
  13. 0 {es-es → es}/09-git-internals/01-chapter9.markdown
  14. 0 {es-es → es}/NOTES
  15. 0 {es-es → es}/README
  16. BIN figures/18333fig0309-tn.png
  17. +10 −10 fr/01-introduction/01-chapter1.markdown
  18. +1,122 −0 id/02-git-basics/01-chapter2.markdown
  19. +189 −188 nl/03-git-branching/01-chapter3.markdown
  20. +239 −237 nl/05-distributed-git/01-chapter5.markdown
  21. +48 −48 nl/06-git-tools/01-chapter6.markdown
  22. +80 −77 nl/07-customizing-git/01-chapter7.markdown
  23. +37 −37 pt-br/04-git-server/01-chapter4.markdown
  24. +39 −40 zh/05-distributed-git/01-chapter5.markdown
  25. +75 −75 zh/07-customizing-git/01-chapter7.markdown
  26. +265 −0 zh_TW/01-introduction/01-chapter1.markdown
  27. +1,122 −0 zh_TW/02-git-basics/01-chapter2.markdown
  28. +598 −0 zh_TW/03-git-branching/01-chapter3.markdown
  29. +852 −0 zh_TW/04-git-server/01-chapter4.markdown
  30. +897 −0 zh_TW/05-distributed-git/01-chapter5.markdown
  31. +1,126 −0 zh_TW/06-git-tools/01-chapter6.markdown
  32. +875 −0 zh_TW/07-customizing-git/01-chapter7.markdown
  33. +685 −0 zh_TW/08-git-and-other-scms/01-chapter8.markdown
  34. +977 −0 zh_TW/09-git-internals/01-chapter9.markdown
View
991 de/07-customizing-git/01-chapter7.markdown
@@ -0,0 +1,991 @@
+# Customizing Git #
+# Git Personalisieren #
+
+Ich habe nun die grundlegende Funktionsweise und die Benutzung von Git besprochen. Weiterhin habe ich einige Werkzeuge von Git eingefuehrt, die dem Benutzer ein einfaches und effizientes Arbeiten erlauben sollen. In diesem Kapitel werde ich nun auf einige Operationen eingehen, die Du benutzen kannst, um die Funktionsweise von Git Deinen persönlichen Beduerfnissen anzupassen. Dazu fuhre ich einige wichtige Konfigurationseinstellungen ein, sowie das Schnittstellen-System, auch Hooks genannt. Mit diesen Mitteln ist es einfach Git so anzupassen, dass es genau den Anspruechen des Benutzers, des Unternehmens oder des Teams entspricht.
+
+So far, I’ve covered the basics of how Git works and how to use it, and I’ve introduced a number of tools that Git provides to help you use it easily and efficiently. In this chapter, I’ll go through some operations that you can use to make Git operate in a more customized fashion by introducing several important configuration settings and the hooks system. With these tools, it’s easy to get Git to work exactly the way you, your company, or your group needs it to.
+
+## Git Configuration ##
+## Git Konfiguration ##
+
+Wie Du in Kapitel 1 kurz gesehen hast, kann man die Konfiguration von Git mit dem Befehl `git config` steuern. Eine Deiner ersten Aktionen war es, Deinen Namen und Deine e-mail Adresse anzugeben:
+
+As you briefly saw in the Chapter 1, you can specify Git configuration settings with the `git config` command. One of the first things you did was set up your name and e-mail address:
+
+ $ git config --global user.name "John Doe"
+ $ git config --global user.email johndoe@example.com
+
+Jetzt wirst Du einige weitere, interessantere Optionen lernen, die Du genauso benutzen kannst, um Git Deiner Arbeitsumgebung anzupassen.
+
+Now you’ll learn a few of the more interesting options that you can set in this manner to customize your Git usage.
+
+In Kapitel 1 hast Du bereits einige einfache Konfigurationsdetails von Git kennengelernt, aber ich möchte sie hier noch einmal schnell wiederholen. Git benutzt eine Reihe von Konfigurationsdateien, um nicht-Standard Verhalten zu kontrollieren, an dem Du interessiert sein könntest. Der erste Ort, an dem Git danach sucht ist in der Datei `/etc/gitconfig`. Diese Datei enthält Werte fuer alle Benutzer des Systems und alle ihre Repositories. Wenn Du `git config` mit der Option `--system` benutzt, liest und schreibt Git speziell in dieser Datei.
+
+You saw some simple Git configuration details in the first chapter, but I’ll go over them again quickly here. Git uses a series of configuration files to determine non-default behavior that you may want. The first place Git looks for these values is in an `/etc/gitconfig` file, which contains values for every user on the system and all of their repositories. If you pass the option `--system` to `git config`, it reads and writes from this file specifically.
+
+Als nächstes sucht Git in der benutzerspezifischen Datei `~/.gitconfig` nach Kofigurationsdaten. Damit Git diese Date zum Lesen und Schreiben nutzt, kannst Du die Option `--global` benutzen.
+
+The next place Git looks is the `~/.gitconfig` file, which is specific to each user. You can make Git read and write to this file by passing the `--global` option.
+
+Als letztes sucht Git in der Konfigurationsdatei im Git Verzeichnis (`.git/config`) des aktuell benutzten Repositories nach Konfigurationsdaten. Diese Daten sind dann speziell fuer dieses Repository gueltig. Jede der erwähnten Ebenen ueberschreibt die vorhergehende, das heisst also das zum Beispiel die Konfiguration aus `.git/config` Vorrang vor derjenigen aus `/etc/gitconfig` hat. Du kannst alle Konfigurationen auch surch manuelles Editieren dieser Dateien mit der korrekten Syntax vornehmen, aber in der Regel ist es einfacher den Befehl `git config` zu benutzen.
+
+Finally, Git looks for configuration values in the config file in the Git directory (`.git/config`) of whatever repository you’re currently using. These values are specific to that single repository. Each level overwrites values in the previous level, so values in `.git/config` trump those in `/etc/gitconfig`, for instance. You can also set these values by manually editing the file and inserting the correct syntax, but it’s generally easier to run the `git config` command.
+
+### Basic Client Configuration ###
+### Grundlegende Client Konfiguration ###
+
+Die von Git verwendeten Konfigurationsoptionen teilen sich in zwei Kategorien: den Client und den Server. Der Grossteil der Optionen beziehen sich auf den Client — zur Konfiguration Deines persönlichen Arbeitsflusses. Auch wenn es eine grosse Menge an Optionen gibt werde ich nur die wenigen besprechen, die sehr gebräuchlich sind oder die Deine Arbeitsweise bedeutend beeinflussen können. Viele Optionen sind nur fuer Spezialfälle nuetzlich, die ich hier nicht auffuehren werde. Falls Du eine Liste aller Optionen sehen willst, fuehre den folgenden Befehl aus
+
+The configuration options recognized by Git fall into two categories: client side and server side. The majority of the options are client side—configuring your personal working preferences. Although tons of options are available, I’ll only cover the few that either are commonly used or can significantly affect your workflow. Many options are useful only in edge cases that I won’t go over here. If you want to see a list of all the options your version of Git recognizes, you can run
+
+ $ git config --help
+
+Die Hilfeseite zu `git config` listet alle möglichen Optionen sehr detailiert auf.
+
+The manual page for `git config` lists all the available options in quite a bit of detail.
+
+#### core.editor ####
+
+In der Grundeinstellung benutzt Git Deinen Standard Texteditor oder greift auf den Vi Editor zurueck, um Deine Commit und Tag Nachrichten zu editieren. Um einen andern Editor als Standard einzurichten kannst Du die Option `core.editor` benutzen:
+
+By default, Git uses whatever you’ve set as your default text editor or else falls back to the Vi editor to create and edit your commit and tag messages. To change that default to something else, you can use the `core.editor` setting:
+
+ $ git config --global core.editor emacs
+
+Hiermit wird Git nun immer unabhängig von Deinem Standard Shell-Editor Emacs starten, um Nachrichten zu editieren.
+
+Now, no matter what is set as your default shell editor variable, Git will fire up Emacs to edit messages.
+
+#### commit.template ####
+
+Wenn Du diese Einstellung auf einen Pfad zu einer Datei auf Deinem System einstellst, wird Git diese Datei als Standard-Nachricht fuer Deine Commits verwenden. Nehmen wir zum Beispiel an, Du hättest eine Vorlage unter dem Namen `$HOME/.gitmessage.txt` erstellst, die aussieht wie folgt:
+
+If you set this to the path of a file on your system, Git will use that file as the default message when you commit. For instance, suppose you create a template file at `$HOME/.gitmessage.txt` that looks like this:
+
+ subject line
+
+ what happened
+
+ [ticket: X]
+
+Damit Git nun diese Datei als Standard-Nachricht benutzt, die in Deinem Editor erscheint, wenn Du `git commit` aufrufst, richte die Option `commit.template` ein:
+
+To tell Git to use it as the default message that appears in your editor when you run `git commit`, set the `commit.template` configuration value:
+
+ $ git config --global commit.template $HOME/.gitmessage.txt
+ $ git commit
+
+Wenn Du dann das nächste Mal ein Commit ausfuehrst, wird Dein Editor mit etwas ähnlichem wie dieser Nachricht starten:
+Then, your editor will open to something like this for your placeholder commit message when you commit:
+
+ 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
+
+Falls Du eine Richtlinie fuer Commit Nachrichten hast, erhöht es die Chance, dass diese Richtlinie auch eingehalten wird, wenn Du dazu eine Vorlage erstellst und Git so konfigurierst, dass sie als Standard geladen wird.
+
+If you have a commit-message policy in place, then putting a template for that policy on your system and configuring Git to use it by default can help increase the chance of that policy being followed regularly.
+
+#### core.pager ####
+
+Die Einstellung `core.pager` legt fest, welche Anwendung zur Seitenanzeige benutzt wird, wenn Git Text ausgib, wie zum Beispiel bei `log` und `diff`. Du kannst es zum Beispiel auf `more` einstellen oder eine andere Seitenznzeige Deiner Wahl (der Standard ist `less`), oder Du kannst es mittels eines leeren Strings ganz ausschalten:
+
+The core.pager setting determines what pager is used when Git pages output such as `log` and `diff`. You can set it to `more` or to your favorite pager (by default, it’s `less`), or you can turn it off by setting it to a blank string:
+
+ $ git config --global core.pager ''
+
+Wenn Du dies ausfuehrst wird Git immer die komplette Ausgabe aller Befehle anzeigen, egal wie lang sie ist.
+
+If you run that, Git will page the entire output of all commands, no matter how long they are.
+
+#### user.signingkey ####
+
+Falls Du signierte annotierte Tags erstellst (wie in Kapitel 2 diskutiert) so macht es die Arbeit leichter, wenn Du Deinen GPG Signier-Schluessel als Konfiguration einstellst. Du kannst Deine Schluessel ID wie folgt festlegen:
+
+If you’re making signed annotated tags (as discussed in Chapter 2), setting your GPG signing key as a configuration setting makes things easier. Set your key ID like so:
+
+ $ git config --global user.signingkey <gpg-key-id>
+
+Jetzt kannst Du Tags signieren, ohne Deinen Schluessel bei jedem `git tag` angeben zu muessen:
+
+Now, you can sign tags without having to specify your key every time with the `git tag` command:
+
+ $ git tag -s <tag-name>
+
+#### core.excludesfile ####
+
+Du kannst Muster in der `.gitignore` Datei Deines Projektes einrichten, damit Git passende Dateien ignoriert und nicht als nicht-verfolgte Dateien ansieht oder versucht, sie zu Stagen, wenn Du fuer sie ein `git add` ausfuehrst, wie in Kapitel 2 besprochen. Falls Du jedoch eine andere Datei ausserhalb des Projektes hast, die diese Werte enthält, oder zusätzliche Muster definiert, dann kannst Du Git mit der Option `core.excludesfile` mitteilen, wo diese Datei zu finden ist. Stelle hier einfach den Pfad zu einer Datei ein, die Einträge enthält, welche denen in `.gitignore` entsprechen.
+
+You can put patterns in your project’s `.gitignore` file to have Git not see them as untracked files or try to stage them when you run `git add` on them, as discussed in Chapter 2. However, if you want another file outside of your project to hold those values or have extra values, you can tell Git where that file is with the `core.excludesfile` setting. Simply set it to the path of a file that has content similar to what a `.gitignore` file would have.
+
+#### help.autocorrect ####
+
+Diese Option ist nur in Git 1.6.1 und neueren Versionen verfuegbar. Wenn Du in Git 1.6 einen Befehl falsch schreibst, bekommst Du eine Meldung wie diese:
+
+This option is available only in Git 1.6.1 and later. If you mistype a command in Git 1.6, it shows you something like this:
+
+ $ git com
+ git: 'com' is not a git-command. See 'git --help'.
+
+ Did you mean this?
+ commit
+
+Wenn Du auf 1 setzt wird Git den vorgeschlagenen Befehl automatisch ausfuehren, falls es in dieser Situation die einzige passende Alternative ist.
+
+If you set `help.autocorrect` to 1, Git will automatically run the command if it has only one match under this scenario.
+
+### Colors in Git ###
+
+Git kann fuer die Textanzeige im Terminal Farben benuutzen, die Dir helfen können, die Ausgabe schnell und einfach zu Ueberfliegen. Mit einer Anzahl Optionen kannst Du die Farben an Deine Vorlieben anpassen.
+
+Git can color its output to your terminal, which can help you visually parse the output quickly and easily. A number of options can help you set the coloring to your preference.
+
+#### color.ui ####
+
+Wenn Du Git entsprechend anweist, wird es den Grossteil der Ausgaben automatisch farblich darstellen. Du kannst sehr detailiert einstellen, wofuer Git Farben verwendet und welche; aber um alle Standard Terminalfarben zu aktivieren, setze `color.ui` auf 'true':
+
+Git automatically colors most of its output if you ask it to. You can get very specific about what you want colored and how; but to turn on all the default terminal coloring, set `color.ui` to true:
+
+ $ git config --global color.ui true
+
+Wenn dieser Wert gesetzt wurde benutzt Git fuer seine Ausgaben Farben, sofern diese zu einem Terminal geleitet werden. Weitere mögliche Einstellungen sind 'false', wodurch alle Farben deaktiviert werden, sowie 'always', wodurch Farben immer aktiviert sind, slebst wenn Du Git Befehle in eine Datei umleitest oder ueber eine Pipe zu einem anderen Befehl umleitest. Diese Option wurde in Git 1.5.5 hinzugefuegt. Solltest Du eine ältere Git Version benutzen, so musst Du alle Farbeinstellungen einzeln vornehmen.
+
+When that value is set, Git colors its output if the output goes to a terminal. Other possible settings are false, which never colors the output, and always, which sets colors all the time, even if you’re redirecting Git commands to a file or piping them to another command. This setting was added in Git version 1.5.5; if you have an older version, you’ll have to specify all the color settings individually.
+
+Du wirst selten die Einstellung `color.ui = always` benötigen. In den meisten Situationen in denen Du Farben in Deiner umgeleiteten Ausgabe haben willst, kannst Du stattdessen die Option `--color` auf der Kommandozeile benutzen, um Git anzuweisen die Farbkodierung fuer die Ausgabe zu verwenden. Die Einstellung sollte fast immer das sein, was Du benutzen willst.
+
+You’ll rarely want `color.ui = always`. In most scenarios, if you want color codes in your redirected output, you can instead pass a `--color` flag to the Git command to force it to use color codes. The `color.ui = true` setting is almost always what you’ll want to use.
+
+#### `color.*` ####
+
+Falls Du im Detail kontrollieren willst welche Befehle wie gefärbt werden, oder wenn Du eine ältere Version benutzt, dann stellt Git Verb-spezifische Farbeinstellungen zur Verfuegung. Jede dieser Optionen kann auf `true`, `false`, oder `always` eingestellt werden:
+
+If you want to be more specific about which commands are colored and how, or you have an older version, Git provides verb-specific coloring settings. Each of these can be set to `true`, `false`, or `always`:
+
+ color.branch
+ color.diff
+ color.interactive
+ color.status
+
+Jede von diesen hat zusätzliche Unteroptionen, die Du benutzen kannst, um spezifische Farben fuer Telie der Ausgabe einzustellen, falls Du jede Farbe zu ueberschreiben. Um zum Beispiel die Meta Informationen in Deiner Diff Ausgabe mit blauem Text auf schwarzem Hintergrund in Fettschrift darstellen willst, kannst Du folgenden Befehl ausfuehren:
+
+In addition, each of these has subsettings you can use to set specific colors for parts of the output, if you want to override each color. For example, to set the meta information in your diff output to blue foreground, black background, and bold text, you can run
+
+ $ git config --global color.diff.meta “blue black bold”
+
+Du kannst als Farben jeden der folgenden Werte verwenden: `normal`, `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, oder `white`. Falls Du ein Attribute wie Fettschrift im vorigen Beispiel willst kannst Du aus `bold`, `dim`, `ul`, `blink`, und `reverse` auswählen.
+
+You can set the color to any of the following values: normal, black, red, green, yellow, blue, magenta, cyan, or white. If you want an attribute like bold in the previous example, you can choose from bold, dim, ul, blink, and reverse.
+
+Auf der Manpage zu `git config` findest Du eine Liste aller Unteroptionen, die Du konfigurieren kannst, falls Du das tun möchtest.
+See the `git config` manpage for all the subsettings you can configure, if you want to do that.
+
+### External Merge and Diff Tools ###
+
+Git besitzt zwar eine interne Implementierung von diff, das Du bisher benutzt hast, aber Du kannst stattdessen auch eine externe Anwendung benutzen. Du kannst auch ein grafisches Merge Werkzeug zur Auflösung von Konflikten benutzen, statt diese manuell zu lösen. Ich werde demonstrieren, wie man das visuelle Merge Tool von Perforce (P4Merge) installiert, um Diffs und Merges zu bearbeiten. Ich habe P4Merge gewählt, da es ein freies und nettes grafisches Werkzeug ist.
+
+Although Git has an internal implementation of diff, which is what you’ve been using, you can set up an external tool instead. You can also set up a graphical merge conflict–resolution tool instead of having to resolve conflicts manually. I’ll demonstrate setting up the Perforce Visual Merge Tool (P4Merge) to do your diffs and merge resolutions, because it’s a nice graphical tool and it’s free.
+
+Falls Du dies testen willst, sollte es kein Problem sein, da P4Merge auf allen ueblichen Plattformen arbeitet. Ich werde Pfadnamen benutzen, die auf Mac und Linux Systemen funktionieren; fuer Windows musst Du `/usr/local/bin` durch einen Pfad ersetzen, der in der Umgebungsvariablen `PATH` gelistet ist.
+
+If you want to try this out, P4Merge works on all major platforms, so you should be able to do so. I’ll use path names in the examples that work on Mac and Linux systems; for Windows, you’ll have to change `/usr/local/bin` to an executable path in your environment.
+
+Du kannst P4Merge hier herunterladen:
+
+You can download P4Merge here:
+
+ http://www.perforce.com/perforce/downloads/component.html
+
+Als erstes solltes Du einige Wrapper (????) Skripten erstellen, um Deine Befehle auszufuehren. Ich benutze den Mac Pfad fuer die ausfuehrbare Datei; auf anderen Systemen ist dies der Ort, an dem die `p4merge` Binärdatei installiert ist. Erstelle ein Skript namens `extMerge`, das die Binärdatei mit allen angegebenen Argumenten aufruft:
+
+To begin, you’ll set up external wrapper scripts to run your commands. I’ll use the Mac path for the executable; in other systems, it will be where your `p4merge` binary is installed. Set up a merge wrapper script named `extMerge` that calls your binary with all the arguments provided:
+
+ $ cat /usr/local/bin/extMerge
+ #!/bin/sh
+ /Applications/p4merge.app/Contents/MacOS/p4merge $*
+
+Der Diff Wrapper (????) stellt sicher, dass es mit sieben Parametern aufgerufen wird und gibt dann zwei davon an das Merge Skript weiter. Standardmässig uebergibt Git die folgenden Argumente an das diff Programm:
+
+The diff wrapper checks to make sure seven arguments are provided and passes two of them to your merge script. By default, Git passes the following arguments to the diff program:
+
+ path old-file old-hex old-mode new-file new-hex new-mode
+
+Da Du nur die Parameter `old-file` und `new-file` benötigst, wirst Du das Wrapper Skript benutzen, um nur die notwendigen weiterzugeben.
+
+Because you only want the `old-file` and `new-file` arguments, you use the wrapper script to pass the ones you need.
+
+ $ cat /usr/local/bin/extDiff
+ #!/bin/sh
+ [ $# -eq 7 ] && /usr/local/bin/extMerge "$2" "$5"
+
+Du musst ausserdem sicherstellen, dass die Skripten ausfuehrbar sind:
+
+You also need to make sure these tools are executable:
+
+ $ sudo chmod +x /usr/local/bin/extMerge
+ $ sudo chmod +x /usr/local/bin/extDiff
+
+Jetzt kannst Du Git so konfigurieren, dass es deine persönlichen Merge und Diff Werkzeuge benutzt. Dazu sind einige angepasste Einstellungen nötig: `merge.tool`, um Git zu sagen welche Merge Strategie es nutzen soll, `mergetool.*.cmd`, um festzulegen, wie der Befehl auszufuehren ist, `mergetool.trustExitCode`, damit Git weiss ob der Antwortcode des Programms eine erfolgreiche Merge Auflösung anzeigt oder nicht, und `diff.external`, um einzustellen welches Diff Kommando Git benutzen soll. Also kannst Du entweder vier Konfigrationsbefehle ausfuehren
+
+Now you can set up your config file to use your custom merge resolution and diff tools. This takes a number of custom settings: `merge.tool` to tell Git what strategy to use, `mergetool.*.cmd` to specify how to run the command, `mergetool.trustExitCode` to tell Git if the exit code of that program indicates a successful merge resolution or not, and `diff.external` to tell Git what command to run for diffs. So, you can either run four config commands
+
+ $ 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
+
+oder Du editierst Deine `~/.gitconfig` Datei und fuegst dort folgende Zeilen hinzu:
+
+or you can edit your `~/.gitconfig` file to add these lines:
+
+ [merge]
+ tool = extMerge
+ [mergetool "extMerge"]
+ cmd = extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
+ trustExitCode = false
+ [diff]
+ external = extDiff
+
+Wenn all dies eingestellt ist und Du Diff Befehle wie diesen ausfuehrst:
+
+After all this is set, if you run diff commands such as this:
+
+ $ git diff 32d1776b1^ 32d1776b1
+
+wird Git statt einer Diff Ausgabe auf der Kommandozeile P4Merge starten, was ähnlich aussehen wird wie Abbildung 7-1.
+
+Instead of getting the diff output on the command line, Git fires up P4Merge, which looks something like Figure 7-1.
+
+Insert 18333fig0701.png
+Figure 7-1. P4Merge.
+
+Wenn Du versuchst zwei Branches zu Mergen und darauffolgende Merge Konflikte hast, kannst Du den Befehl `git mergetool` ausfuehren; das startet P4Merge und erlaubt Dir, die Konflikte mit dem GUI Werkzeug aufzulösen.
+
+If you try to merge two branches and subsequently have merge conflicts, you can run the command `git mergetool`; it starts P4Merge to let you resolve the conflicts through that GUI tool.
+
+Das Angenehme an diesem Wrapper Ansatz ist, dass Du Deine Diff und Merge Werkzeuge sehr leicht ändern kannst. Wenn Du zum Beispiel Deine `extDiff` und `extMerge` Programme ändern möchtest, um stattdessen KDiff3 zu benutzen, musst Du lediglich Dein `extMerge` Datei ändern:
+
+The nice thing about this wrapper setup is that you can change your diff and merge tools easily. For example, to change your `extDiff` and `extMerge` tools to run the KDiff3 tool instead, all you have to do is edit your `extMerge` file:
+
+ $ cat /usr/local/bin/extMerge
+ #!/bin/sh
+ /Applications/kdiff3.app/Contents/MacOS/kdiff3 $*
+
+Nun wird Git KDiff3 zur Anzeige von Diffs und zur Auflösung von Merge Konflikten verwenden.
+
+Now, Git will use the KDiff3 tool for diff viewing and merge conflict resolution.
+
+Git hat Voreinstellungen, um einige andere Merge-Auflösungswerkzeuge zu verwenden, ohne dass Du die Kommando Konfiguration einstellen musst. Du kannst Dein Merge Werkzeug auf kdiff3, opendiff, tkdiff, meld, xxdiff, emerge, vimdiff, oder gvimdiff einstellen. Wenn Du zum Beispiel nicht daran interessiert bist KDiff3 fuer Diffs zu verwenden, sondern nur zur Auflösung von Merge Konflikten, dann kannst Du den folgenden Befehl ausfuehren, wenn sich kdiff3 im Pfad befindet
+
+Git comes preset to use a number of other merge-resolution tools without your having to set up the cmd configuration. You can set your merge tool to kdiff3, opendiff, tkdiff, meld, xxdiff, emerge, vimdiff, or gvimdiff. If you’re not interested in using KDiff3 for diff but rather want to use it just for merge resolution, and the kdiff3 command is in your path, then you can run
+
+ $ git config --global merge.tool kdiff3
+
+Wenn Du diesen Befehl ausfuehrst statt die `extMerge` und `extDiff` Dateien zu erstellen, dann wird Git KDiff3 fuer Merge Auflösungen verwenden, und das normale Git Diff Werkzeug fuer Diffs.
+
+If you run this instead of setting up the `extMerge` and `extDiff` files, Git will use KDiff3 for merge resolution and the normal Git diff tool for diffs.
+
+### Formatting and Whitespace ###
+### Formatierung und Fuellzeichen ###
+
+Formatierungen und Fuellzeichen -- also Tabulatorzeichen, Leerzeichen und Steuerzeichen fuer Zeilenwechsel (LF) und Zeilen- oder Wagenruecklauf (CR) -- fuehren zu einigen der frustrierendsten und subtilsten Probleme denen viele Entwickler begegnen, wenn sie mit anderen zusammenarbeiten, speziell ueber Plattformgrenzen hinweg. Es kann sehr leicht passieren, dass bei Patches oder anderer gemeinsamer Arbeit kaum merklich Fuellzeichen hinzugefuegt werden, sei es weil ein Entwickler sie unnwissentlich einfuegt, oder weil ein Windows Programmierer bei plattformuebergreifenden Projekten einen Zeilenruecklauf am Zeilenende von Dateien anfuegt. Git hat einige Konfigurationseinstellungen die bei diesen Problemen helfen.
+
+Formatting and whitespace issues are some of the more frustrating and subtle problems that many developers encounter when collaborating, especially cross-platform. It’s very easy for patches or other collaborated work to introduce subtle whitespace changes because editors silently introduce them or Windows programmers add carriage returns at the end of lines they touch in cross-platform projects. Git has a few configuration options to help with these issues.
+
+#### core.autocrlf ####
+
+Falls Du unter Windows programmierst oder ein anderes System benutzt und mit anderen zusammenarbeitest, die unter Windows programmieren, wirst Du sehr wahrscheinlich irgendwann dem Problem der Zeilenenden begegnen. Dies liegt daran, dass Windows sowohl ein CR-Zeichen als auch ein LF-Zeichen zum Signalisieren einer neuen Zeile in einer Datei benutzt, während Mac und Linux nur ein LF-Zeichen benutzen. Dies ist eine kleine aber extrem störende Tatsache beim Arbeiten ueber Plattformgrenzen hinweg.
+
+If you’re programming on Windows or using another system but working with people who are programming on Windows, you’ll probably run into line-ending issues at some point. This is because Windows uses both a carriage-return character and a linefeed character for newlines in its files, whereas Mac and Linux systems use only the linefeed character. This is a subtle but incredibly annoying fact of cross-platform work.
+
+Git kann dies vermeiden, indem es CR-LF Zeichen am Zeilenende automatisch zu LF konvertiert, wenn Du ein Commit machst, und umgekehrt wenn es bei einem Checkout Code mit Deinem lokalen Dateisystem synchronisiert. Du kannst diese Funktionalität mittels der Option `core.autocrlf` aktivieren. Falls Du auf einem Windows System arbeitest, setze sie auf `true` — dies konvertiert LF Zeichen zu CRLF Zeichen, wenn Du Code mit einem Checkout synchronisierst:
+
+Git can handle this by auto-converting CRLF line endings into LF when you commit, and vice versa when it checks out code onto your filesystem. You can turn on this functionality with the `core.autocrlf` setting. If you’re on a Windows machine, set it to `true` — this converts LF endings into CRLF when you check out code:
+
+ $ git config --global core.autocrlf true
+
+Falls Du auf einem Linux oder Mac System arbeitest, das LF Zeilenenden benutzt, dann soll Git keine Dateien automatisch konvertieren, wenn sie per Checkout vom Server kommen; wenn allerdings versehentlich eine Datei mit CR-LF Zeichen auf Dein System gelangt, dann möchtest Du vielleicht, dass Git es fuer Dich repariert. Du kannst Git anweisen CR-LF automatisch in LF Zeichen umzuwandeln, wenn Du ein Commit machst, aber nicht in der anderen Richtung, indem Du `core.autocrlf` auf input setzt:
+
+If you’re on a Linux or Mac system that uses LF line endings, then you don’t want Git to automatically convert them when you check out files; however, if a file with CRLF endings accidentally gets introduced, then you may want Git to fix it. You can tell Git to convert CRLF to LF on commit but not the other way around by setting `core.autocrlf` to input:
+
+ $ git config --global core.autocrlf input
+
+Mit dieser Einstellung solltest Du CR-LF Zeilenenden bei Dateien haben, die auf Windows synchronisiert wurden, und mit LF Zeilenenden auf Mac und Linux Sytemen und im Repository.
+
+This setup should leave you with CRLF endings in Windows checkouts but LF endings on Mac and Linux systems and in the repository.
+
+Falls Du ein Windows Programmierer bist, mit einem Projekt, dass nur unter Windows entwickelt wird, dann kannst Du diese Funktionalität deaktivieren, so dass die CR Zeilenenden im Repository gespeichert werden. Dazu setzt Du diese Option auf `false`:
+
+If you’re a Windows programmer doing a Windows-only project, then you can turn off this functionality, recording the carriage returns in the repository by setting the config value to `false`:
+
+ $ git config --global core.autocrlf false
+
+#### core.whitespace ####
+
+Git ist so voreingestellt, dass es einige Leerzeichen Probleme erkennen und beheben kann. Es kann nach vier vorrangigen Problemen mit Leerzeichen suchen — Zwei davon sind standardmässig aktiviert und kann deaktiviert werden, und zwei sind inaktiv, können aber aktiviert werden.
+
+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.
+
+Die zwei standardmässig aktiven Optionen sind `trailing-space`, das nach Leerzeichen am Ende einer Zeile sucht, und `space-before-tab`, das nach Leerzeichen vor Tabulatoren am Anfang einer Zeile sucht.
+
+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.
+
+Die beiden aktivierbaren, aber normalerweise deaktivierten Optionen sind `indent-with-non-tab`, dass nach Zeilen sucht, die mit acht oder mehr Leerzeichen anstelle von Tabulatoren beginnt, und `cr-at-eol`, wodurch Git angewiesen wird, dass CR Zeichen am Zeilenende in Ordnung sind.
+
+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.
+
+Du kannst Git mitteilen welche dieser Optionen es aktivieren soll, indem Du `core.whitespace` auf die Werte setzt, durch Kommas getrennt, die Du an- oder abgeschaltet haben möchtest. Du kannst Optionen deaktivieren, indem Du sie entweder aus der Parameterliste weglässt, oder ihnen ein `-` Zeichen voranstellst. Wenn Du zum Beispiel alle Optionen ausser `cr-at-eol` aktivieren willst, kannst Du folgendes ausfuehren:
+
+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 wird diese möglichen Problemstellen erkennen, wenn Du einen `git diff` Befehl ausfuehrst, und wird versuchen sie farblich hervorzuheben, damit Du sie vor einem Commit beheben kannst. Git wird diese Einstellungen auch benutzen, um Dir zu helfen, wenn Du mit `git apply` Patches anwendest. Wenn Du Patches ausfuehrst kannst Du Git anweisen eine Warnung auszugeben, falls es beim Patchen die spezifizierten Leerzeichenprobleme erkennt:
+
+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>
+
+Oder Du kannst Git versuchen lassen, diese Probleme automatisch zu beheben, bevor es den Patch anwendet:
+
+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 option 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.
+
+## Git Attributes ##
+
+Some of these settings can also be specified for a path, so that Git applies those settings only for a subdirectory or subset of files. These path-specific settings are called Git attributes and are set either in a `.gitattributes` file in one of your directories (normally the root of your project) or in the `.git/info/attributes` file if you don’t want the attributes file committed with your project.
+
+Using attributes, you can do things like specify separate merge strategies for individual files or directories in your project, tell Git how to diff non-text files, or have Git filter content before you check it into or out of Git. In this section, you’ll learn about some of the attributes you can set on your paths in your Git project and see a few examples of using this feature in practice.
+
+### Binary Files ###
+
+One cool trick for which you can use Git attributes is telling Git which files are binary (in cases it otherwise may not be able to figure out) and giving Git special instructions about how to handle those files. For instance, some text files may be machine generated and not diffable, whereas some binary files can be diffed — you’ll see how to tell Git which is which.
+
+#### Identifying Binary Files ####
+
+Some files look like text files but for all intents and purposes are to be treated as binary data. For instance, Xcode projects on the Mac contain a file that ends in `.pbxproj`, which is basically a JSON (plain text javascript data format) dataset written out to disk by the IDE that records your build settings and so on. Although it’s technically a text file, because it’s all ASCII, you don’t want to treat it as such because it’s really a lightweight database — you can’t merge the contents if two people changed it, and diffs generally aren’t helpful. The file is meant to be consumed by a machine. In essence, you want to treat it like a binary file.
+
+To tell Git to treat all `pbxproj` files as binary data, add the following line to your `.gitattributes` file:
+
+ *.pbxproj -crlf -diff
+
+Now, Git won’t try to convert or fix CRLF issues; nor will it try to compute or print a diff for changes in this file when you run git show or git diff on your project. In the 1.6 series of Git, you can also use a macro that is provided that means `-crlf -diff`:
+
+ *.pbxproj binary
+
+#### Diffing Binary Files ####
+
+In the 1.6 series of Git, you can use the Git attributes functionality to effectively diff binary files. You do this by telling Git how to convert your binary data to a text format that can be compared via the normal diff.
+
+Because this is a pretty cool and not widely known feature, I’ll go over a few examples. First, you’ll use this technique to solve one of the most annoying problems known to humanity: version-controlling Word documents. Everyone knows that Word is the most horrific editor around; but, oddly, everyone uses it. If you want to version-control Word documents, you can stick them in a Git repository and commit every once in a while; but what good does that do? If you run `git diff` normally, you only see something like this:
+
+ $ git diff
+ diff --git a/chapter1.doc b/chapter1.doc
+ index 88839c4..4afcb7c 100644
+ Binary files a/chapter1.doc and b/chapter1.doc differ
+
+You can’t directly compare two versions unless you check them out and scan them manually, right? It turns out you can do this fairly well using Git attributes. Put the following line in your `.gitattributes` file:
+
+ *.doc diff=word
+
+This tells Git that any file that matches this pattern (.doc) should use the "word" filter when you try to view a diff that contains changes. What is the "word" filter? You have to set it up. Here you’ll configure Git to use the `strings` program to convert Word documents into readable text files, which it will then diff properly:
+
+ $ git config diff.word.textconv strings
+
+Now Git knows that if it tries to do a diff between two snapshots, and any of the files end in `.doc`, it should run those files through the "word" filter, which is defined as the `strings` program. This effectively makes nice text-based versions of your Word files before attempting to diff them.
+
+Here’s an example. I put Chapter 1 of this book into Git, added some text to a paragraph, and saved the document. Then, I ran `git diff` to see what changed:
+
+ $ git diff
+ diff --git a/chapter1.doc b/chapter1.doc
+ index c1c8a0a..b93c9e4 100644
+ --- a/chapter1.doc
+ +++ b/chapter1.doc
+ @@ -8,7 +8,8 @@ re going to cover Version Control Systems (VCS) and Git basics
+ re going to cover how to get it and set it up for the first time if you don
+ t already have it on your system.
+ In Chapter Two we will go over basic Git usage - how to use Git for the 80%
+ -s going on, modify stuff and contribute changes. If the book spontaneously
+ +s going on, modify stuff and contribute changes. If the book spontaneously
+ +Let's see if this works.
+
+Git successfully and succinctly tells me that I added the string "Let’s see if this works", which is correct. It’s not perfect — it adds a bunch of random stuff at the end — but it certainly works. If you can find or write a Word-to-plain-text converter that works well enough, that solution will likely be incredibly effective. However, `strings` is available on most Mac and Linux systems, so it may be a good first try to do this with many binary formats.
+
+Another interesting problem you can solve this way involves diffing image files. One way to do this is to run JPEG files through a filter that extracts their EXIF information — metadata that is recorded with most image formats. If you download and install the `exiftool` program, you can use it to convert your images into text about the metadata, so at least the diff will show you a textual representation of any changes that happened:
+
+ $ echo '*.png diff=exif' >> .gitattributes
+ $ git config diff.exif.textconv exiftool
+
+If you replace an image in your project and run `git diff`, you see something like this:
+
+ diff --git a/image.png b/image.png
+ index 88839c4..4afcb7c 100644
+ --- a/image.png
+ +++ b/image.png
+ @@ -1,12 +1,12 @@
+ ExifTool Version Number : 7.74
+ -File Size : 70 kB
+ -File Modification Date/Time : 2009:04:21 07:02:45-07:00
+ +File Size : 94 kB
+ +File Modification Date/Time : 2009:04:21 07:02:43-07:00
+ File Type : PNG
+ MIME Type : image/png
+ -Image Width : 1058
+ -Image Height : 889
+ +Image Width : 1056
+ +Image Height : 827
+ Bit Depth : 8
+ Color Type : RGB with Alpha
+
+You can easily see that the file size and image dimensions have both changed.
+
+### Keyword Expansion ###
+
+SVN- or CVS-style keyword expansion is often requested by developers used to those systems. The main problem with this in Git is that you can’t modify a file with information about the commit after you’ve committed, because Git checksums the file first. However, you can inject text into a file when it’s checked out and remove it again before it’s added to a commit. Git attributes offers you two ways to do this.
+
+First, you can inject the SHA-1 checksum of a blob into an `$Id$` field in the file automatically. If you set this attribute on a file or set of files, then the next time you check out that branch, Git will replace that field with the SHA-1 of the blob. It’s important to notice that it isn’t the SHA of the commit, but of the blob itself:
+
+ $ echo '*.txt ident' >> .gitattributes
+ $ echo '$Id$' > test.txt
+
+The next time you check out this file, Git injects the SHA of the blob:
+
+ $ rm text.txt
+ $ git checkout -- text.txt
+ $ cat test.txt
+ $Id: 42812b7653c7b88933f8a9d6cad0ca16714b9bb3 $
+
+However, that result is of limited use. If you’ve used keyword substitution in CVS or Subversion, you can include a datestamp — the SHA isn’t all that helpful, because it’s fairly random and you can’t tell if one SHA is older or newer than another.
+
+It turns out that you can write your own filters for doing substitutions in files on commit/checkout. These are the "clean" and "smudge" filters. In the `.gitattributes` file, you can set a filter for particular paths and then set up scripts that will process files just before they’re committed ("clean", see Figure 7-2) and just before they’re checked out ("smudge", see Figure 7-3). These filters can be set to do all sorts of fun things.
+
+Insert 18333fig0702.png
+Figure 7-2. The “smudge” filter is run on checkout.
+
+Insert 18333fig0703.png
+Figure 7-3. The “clean” filter is run when files are staged.
+
+The original commit message for this functionality gives a simple example of running all your C source code through the `indent` program before committing. You can set it up by setting the filter attribute in your `.gitattributes` file to filter `*.c` files with the "indent" filter:
+
+ *.c filter=indent
+
+Then, tell Git what the "indent"" filter does on smudge and clean:
+
+ $ git config --global filter.indent.clean indent
+ $ git config --global filter.indent.smudge cat
+
+In this case, when you commit files that match `*.c`, Git will run them through the indent program before it commits them and then run them through the `cat` program before it checks them back out onto disk. The `cat` program is basically a no-op: it spits out the same data that it gets in. This combination effectively filters all C source code files through `indent` before committing.
+
+Another interesting example gets `$Date$` keyword expansion, RCS style. To do this properly, you need a small script that takes a filename, figures out the last commit date for this project, and inserts the date into the file. Here is a small Ruby script that does that:
+
+ #! /usr/bin/env ruby
+ data = STDIN.read
+ last_date = `git log --pretty=format:"%ad" -1`
+ puts data.gsub('$Date$', '$Date: ' + last_date.to_s + '$')
+
+All the script does is get the latest commit date from the `git log` command, stick that into any `$Date$` strings it sees in stdin, and print the results — it should be simple to do in whatever language you’re most comfortable in. You can name this file `expand_date` and put it in your path. Now, you need to set up a filter in Git (call it `dater`) and tell it to use your `expand_date` filter to smudge the files on checkout. You’ll use a Perl expression to clean that up on commit:
+
+ $ git config filter.dater.smudge expand_date
+ $ git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'
+
+This Perl snippet strips out anything it sees in a `$Date$` string, to get back to where you started. Now that your filter is ready, you can test it by setting up a file with your `$Date$` keyword and then setting up a Git attribute for that file that engages the new filter:
+
+ $ echo '# $Date$' > date_test.txt
+ $ echo 'date*.txt filter=dater' >> .gitattributes
+
+If you commit those changes and check out the file again, you see the keyword properly substituted:
+
+ $ git add date_test.txt .gitattributes
+ $ git commit -m "Testing date expansion in Git"
+ $ rm date_test.txt
+ $ git checkout date_test.txt
+ $ cat date_test.txt
+ # $Date: Tue Apr 21 07:26:52 2009 -0700$
+
+You can see how powerful this technique can be for customized applications. You have to be careful, though, because the `.gitattributes` file is committed and passed around with the project but the driver (in this case, `dater`) isn’t; so, it won’t work everywhere. When you design these filters, they should be able to fail gracefully and have the project still work properly.
+
+### Exporting Your Repository ###
+
+Git attribute data also allows you to do some interesting things when exporting an archive of your project.
+
+#### export-ignore ####
+
+You can tell Git not to export certain files or directories when generating an archive. If there is a subdirectory or file that you don’t want to include in your archive file but that you do want checked into your project, you can determine those files via the `export-ignore` attribute.
+
+For example, say you have some test files in a `test/` subdirectory, and it doesn’t make sense to include them in the tarball export of your project. You can add the following line to your Git attributes file:
+
+ test/ export-ignore
+
+Now, when you run git archive to create a tarball of your project, that directory won’t be included in the archive.
+
+#### export-subst ####
+
+Another thing you can do for your archives is some simple keyword substitution. Git lets you put the string `$Format:$` in any file with any of the `--pretty=format` formatting shortcodes, many of which you saw in Chapter 2. For instance, if you want to include a file named `LAST_COMMIT` in your project, and the last commit date was automatically injected into it when `git archive` ran, you can set up the file like this:
+
+ $ echo 'Last commit date: $Format:%cd$' > LAST_COMMIT
+ $ echo "LAST_COMMIT export-subst" >> .gitattributes
+ $ git add LAST_COMMIT .gitattributes
+ $ git commit -am 'adding LAST_COMMIT file for archives'
+
+When you run `git archive`, the contents of that file when people open the archive file will look like this:
+
+ $ cat LAST_COMMIT
+ Last commit date: $Format:Tue Apr 21 08:38:48 2009 -0700$
+
+### Merge Strategies ###
+
+You can also use Git attributes to tell Git to use different merge strategies for specific files in your project. One very useful option is to tell Git to not try to merge specific files when they have conflicts, but rather to use your side of the merge over someone else’s.
+
+This is helpful if a branch in your project has diverged or is specialized, but you want to be able to merge changes back in from it, and you want to ignore certain files. Say you have a database settings file called database.xml that is different in two branches, and you want to merge in your other branch without messing up the database file. You can set up an attribute like this:
+
+ database.xml merge=ours
+
+If you merge in the other branch, instead of having merge conflicts with the database.xml file, you see something like this:
+
+ $ git merge topic
+ Auto-merging database.xml
+ Merge made by recursive.
+
+In this case, database.xml stays at whatever version you originally had.
+
+## Git Hooks ##
+
+Like many other Version Control Systems, Git has a way to fire off custom scripts when certain important actions occur. There are two groups of these hooks: client side and server side. The client-side hooks are for client operations such as committing and merging. The server-side hooks are for Git server operations such as receiving pushed commits. You can use these hooks for all sorts of reasons, and you’ll learn about a few of them here.
+
+### Installing a Hook ###
+
+The hooks are all stored in the `hooks` subdirectory of the Git directory. In most projects, that’s `.git/hooks`. By default, Git populates this directory with a bunch of example scripts, many of which are useful by themselves; but they also document the input values of each script. All the examples are written as shell scripts, with some Perl thrown in, but any properly named executable scripts will work fine — you can write them in Ruby or Python or what have you. For post-1.6 versions of Git, these example hook files end with .sample; you’ll need to rename them. For pre-1.6 versions of Git, the example files are named properly but are not executable.
+
+To enable a hook script, put a file in the `hooks` subdirectory of your Git directory that is named appropriately and is executable. From that point forward, it should be called. I’ll cover most of the major hook filenames here.
+
+### Client-Side Hooks ###
+
+There are a lot of client-side hooks. This section splits them into committing-workflow hooks, e-mail–workflow scripts, and the rest of the client-side scripts.
+
+#### Committing-Workflow Hooks ####
+
+The first four hooks have to do with the committing process. The `pre-commit` hook is run first, before you even type in a commit message. It’s used to inspect the snapshot that’s about to be committed, to see if you’ve forgotten something, to make sure tests run, or to examine whatever you need to inspect in the code. Exiting non-zero from this hook aborts the commit, although you can bypass it with `git commit --no-verify`. You can do things like check for code style (run lint or something equivalent), check for trailing whitespace (the default hook does exactly that), or check for appropriate documentation on new methods.
+
+The `prepare-commit-msg` hook is run before the commit message editor is fired up but after the default message is created. It lets you edit the default message before the commit author sees it. This hook takes a few options: the path to the file that holds the commit message so far, the type of commit, and the commit SHA-1 if this is an amended commit. This hook generally isn’t useful for normal commits; rather, it’s good for commits where the default message is auto-generated, such as templated commit messages, merge commits, squashed commits, and amended commits. You may use it in conjunction with a commit template to programmatically insert information.
+
+The `commit-msg` hook takes one parameter, which again is the path to a temporary file that contains the current commit message. If this script exits non-zero, Git aborts the commit process, so you can use it to validate your project state or commit message before allowing a commit to go through. In the last section of this chapter, I’ll demonstrate using this hook to check that your commit message is conformant to a required pattern.
+
+After the entire commit process is completed, the `post-commit` hook runs. It doesn’t take any parameters, but you can easily get the last commit by running `git log -1 HEAD`. Generally, this script is used for notification or something similar.
+
+The committing-workflow client-side scripts can be used in just about any workflow. They’re often used to enforce certain policies, although it’s important to note that these scripts aren’t transferred during a clone. You can enforce policy on the server side to reject pushes of commits that don’t conform to some policy, but it’s entirely up to the developer to use these scripts on the client side. So, these are scripts to help developers, and they must be set up and maintained by them, although they can be overridden or modified by them at any time.
+
+#### E-mail Workflow Hooks ####
+
+You can set up three client-side hooks for an e-mail–based workflow. They’re all invoked by the `git am` command, so if you aren’t using that command in your workflow, you can safely skip to the next section. If you’re taking patches over e-mail prepared by `git format-patch`, then some of these may be helpful to you.
+
+The first hook that is run is `applypatch-msg`. It takes a single argument: the name of the temporary file that contains the proposed commit message. Git aborts the patch if this script exits non-zero. You can use this to make sure a commit message is properly formatted or to normalize the message by having the script edit it in place.
+
+The next hook to run when applying patches via `git am` is `pre-applypatch`. It takes no arguments and is run after the patch is applied, so you can use it to inspect the snapshot before making the commit. You can run tests or otherwise inspect the working tree with this script. If something is missing or the tests don’t pass, exiting non-zero also aborts the `git am` script without committing the patch.
+
+The last hook to run during a `git am` operation is `post-applypatch`. You can use it to notify a group or the author of the patch you pulled in that you’ve done so. You can’t stop the patching process with this script.
+
+#### Other Client Hooks ####
+
+The `pre-rebase` hook runs before you rebase anything and can halt the process by exiting non-zero. You can use this hook to disallow rebasing any commits that have already been pushed. The example `pre-rebase` hook that Git installs does this, although it assumes that next is the name of the branch you publish. You’ll likely need to change that to whatever your stable, published branch is.
+
+After you run a successful `git checkout`, the `post-checkout` hook runs; you can use it to set up your working directory properly for your project environment. This may mean moving in large binary files that you don’t want source controlled, auto-generating documentation, or something along those lines.
+
+Finally, the `post-merge` hook runs after a successful `merge` command. You can use it to restore data in the working tree that Git can’t track, such as permissions data. This hook can likewise validate the presence of files external to Git control that you may want copied in when the working tree changes.
+
+### Server-Side Hooks ###
+
+In addition to the client-side hooks, you can use a couple of important server-side hooks as a system administrator to enforce nearly any kind of policy for your project. These scripts run before and after pushes to the server. The pre hooks can exit non-zero at any time to reject the push as well as print an error message back to the client; you can set up a push policy that’s as complex as you wish.
+
+#### pre-receive and post-receive ####
+
+The first script to run when handling a push from a client is `pre-receive`. It takes a list of references that are being pushed from stdin; if it exits non-zero, none of them are accepted. You can use this hook to do things like make sure none of the updated references are non-fast-forwards; or to check that the user doing the pushing has create, delete, or push access or access to push updates to all the files they’re modifying with the push.
+
+The `post-receive` hook runs after the entire process is completed and can be used to update other services or notify users. It takes the same stdin data as the `pre-receive` hook. Examples include e-mailing a list, notifying a continuous integration server, or updating a ticket-tracking system — you can even parse the commit messages to see if any tickets need to be opened, modified, or closed. This script can’t stop the push process, but the client doesn’t disconnect until it has completed; so, be careful when you try to do anything that may take a long time.
+
+#### update ####
+
+The update script is very similar to the `pre-receive` script, except that it’s run once for each branch the pusher is trying to update. If the pusher is trying to push to multiple branches, `pre-receive` runs only once, whereas update runs once per branch they’re pushing to. Instead of reading from stdin, this script takes three arguments: the name of the reference (branch), the SHA-1 that reference pointed to before the push, and the SHA-1 the user is trying to push. If the update script exits non-zero, only that reference is rejected; other references can still be updated.
+
+## An Example Git-Enforced Policy ##
+
+In this section, you’ll use what you’ve learned to establish a Git workflow that checks for a custom commit message format, enforces fast-forward-only pushes, and allows only certain users to modify certain subdirectories in a project. You’ll build client scripts that help the developer know if their push will be rejected and server scripts that actually enforce the policies.
+
+I used Ruby to write these, both because it’s my preferred scripting language and because I feel it’s the most pseudocode-looking of the scripting languages; thus you should be able to roughly follow the code even if you don’t use Ruby. However, any language will work fine. All the sample hook scripts distributed with Git are in either Perl or Bash scripting, so you can also see plenty of examples of hooks in those languages by looking at the samples.
+
+### Server-Side Hook ###
+
+All the server-side work will go into the update file in your hooks directory. The update file runs once per branch being pushed and takes the reference being pushed to, the old revision where that branch was, and the new revision being pushed. You also have access to the user doing the pushing if the push is being run over SSH. If you’ve allowed everyone to connect with a single user (like "git") via public-key authentication, you may have to give that user a shell wrapper that determines which user is connecting based on the public key, and set an environment variable specifying that user. Here I assume the connecting user is in the `$USER` environment variable, so your update script begins by gathering all the information you need:
+
+ #!/usr/bin/env ruby
+
+ $refname = ARGV[0]
+ $oldrev = ARGV[1]
+ $newrev = ARGV[2]
+ $user = ENV['USER']
+
+ puts "Enforcing Policies... \n(#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})"
+
+Yes, I’m using global variables. Don’t judge me — it’s easier to demonstrate in this manner.
+
+#### Enforcing a Specific Commit-Message Format ####
+
+Your first challenge is to enforce that each commit message must adhere to a particular format. Just to have a target, assume that each message has to include a string that looks like "ref: 1234" because you want each commit to link to a work item in your ticketing system. You must look at each commit being pushed up, see if that string is in the commit message, and, if the string is absent from any of the commits, exit non-zero so the push is rejected.
+
+You can get a list of the SHA-1 values of all the commits that are being pushed by taking the `$newrev` and `$oldrev` values and passing them to a Git plumbing command called `git rev-list`. This is basically the `git log` command, but by default it prints out only the SHA-1 values and no other information. So, to get a list of all the commit SHAs introduced between one commit SHA and another, you can run something like this:
+
+ $ git rev-list 538c33..d14fc7
+ d14fc7c847ab946ec39590d87783c69b031bdfb7
+ 9f585da4401b0a3999e84113824d15245c13f0be
+ 234071a1be950e2a8d078e6141f5cd20c1e61ad3
+ dfa04c9ef3d5197182f13fb5b9b1fb7717d2222a
+ 17716ec0f1ff5c77eff40b7fe912f9f6cfd0e475
+
+You can take that output, loop through each of those commit SHAs, grab the message for it, and test that message against a regular expression that looks for a pattern.
+
+You have to figure out how to get the commit message from each of these commits to test. To get the raw commit data, you can use another plumbing command called `git cat-file`. I’ll go over all these plumbing commands in detail in Chapter 9; but for now, here’s what that command gives you:
+
+ $ 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
+
+ changed the version number
+
+A simple way to get the commit message from a commit when you have the SHA-1 value is to go to the first blank line and take everything after that. You can do so with the `sed` command on Unix systems:
+
+ $ git cat-file commit ca82a6 | sed '1,/^$/d'
+ changed the version number
+
+You can use that incantation to grab the commit message from each commit that is trying to be pushed and exit if you see anything that doesn’t match. To exit the script and reject the push, exit non-zero. The whole method looks like this:
+
+ $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
+
+Putting that in your `update` script will reject updates that contain commits that have messages that don’t adhere to your rule.
+
+#### Enforcing a User-Based ACL System ####
+
+Suppose you want to add a mechanism that uses an access control list (ACL) that specifies which users are allowed to push changes to which parts of your projects. Some people have full access, and others only have access to push changes to certain subdirectories or specific files. To enforce this, you’ll write those rules to a file named `acl` that lives in your bare Git repository on the server. You’ll have the `update` hook look at those rules, see what files are being introduced for all the commits being pushed, and determine whether the user doing the push has access to update all those files.
+
+The first thing you’ll do is write your ACL. Here you’ll use a format very much like the CVS ACL mechanism: it uses a series of lines, where the first field is `avail` or `unavail`, the next field is a comma-delimited list of the users to which the rule applies, and the last field is the path to which the rule applies (blank meaning open access). All of these fields are delimited by a pipe (`|`) character.
+
+In this case, you have a couple of administrators, some documentation writers with access to the `doc` directory, and one developer who only has access to the `lib` and `tests` directories, and your ACL file looks like this:
+
+ avail|nickh,pjhyett,defunkt,tpw
+ avail|usinclair,cdickens,ebronte|doc
+ avail|schacon|lib
+ avail|schacon|tests
+
+You begin by reading this data into a structure that you can use. In this case, to keep the example simple, you’ll only enforce the `avail` directives. Here is a method that gives you an associative array where the key is the user name and the value is an array of paths to which the user has write access:
+
+ 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
+
+On the ACL file you looked at earlier, this `get_acl_access_data` method returns a data structure that looks like this:
+
+ {"defunkt"=>[nil],
+ "tpw"=>[nil],
+ "nickh"=>[nil],
+ "pjhyett"=>[nil],
+ "schacon"=>["lib", "tests"],
+ "cdickens"=>["doc"],
+ "usinclair"=>["doc"],
+ "ebronte"=>["doc"]}
+
+Now that you have the permissions sorted out, you need to determine what paths the commits being pushed have modified, so you can make sure the user who’s pushing has access to all of them.
+
+You can pretty easily see what files have been modified in a single commit with the `--name-only` option to the `git log` command (mentioned briefly in Chapter 2):
+
+ $ git log -1 --name-only --pretty=format:'' 9f585d
+
+ README
+ lib/test.rb
+
+If you use the ACL structure returned from the `get_acl_access_data` method and check it against the listed files in each of the commits, you can determine whether the user has access to push all of their commits:
+
+ # 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.index(access_path) == 0) # 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
+
+Most of that should be easy to follow. You get a list of new commits being pushed to your server with `git rev-list`. Then, for each of those, you find which files are modified and make sure the user who’s pushing has access to all the paths being modified. One Rubyism that may not be clear is `path.index(access_path) == 0`, which is true if path begins with `access_path` — this ensures that `access_path` is not just in one of the allowed paths, but an allowed path begins with each accessed path.
+
+Now your users can’t push any commits with badly formed messages or with modified files outside of their designated paths.
+
+#### Enforcing Fast-Forward-Only Pushes ####
+
+The only thing left is to enforce fast-forward-only pushes. In Git versions 1.6 or newer, you can set the `receive.denyDeletes` and `receive.denyNonFastForwards` settings. But enforcing this with a hook will work in older versions of Git, and you can modify it to do so only for certain users or whatever else you come up with later.
+
+The logic for checking this is to see if any commits are reachable from the older revision that aren’t reachable from the newer one. If there are none, then it was a fast-forward push; otherwise, you deny it:
+
+ # enforces fast-forward only pushes
+ def check_fast_forward
+ missed_refs = `git rev-list #{$newrev}..#{$oldrev}`
+ missed_ref_count = missed_refs.split("\n").size
+ if missed_ref_count > 0
+ puts "[POLICY] Cannot push a non fast-forward reference"
+ exit 1
+ end
+ end
+
+ check_fast_forward
+
+Everything is set up. If you run `chmod u+x .git/hooks/update`, which is the file you into which you should have put all this code, and then try to push a non-fast-forwarded reference, you get something like this:
+
+ $ 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] Cannot push a non-fast-forward reference
+ 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'
+
+There are a couple of interesting things here. First, you see this where the hook starts running.
+
+ Enforcing Policies...
+ (refs/heads/master) (fb8c72) (c56860)
+
+Notice that you printed that out to stdout at the very beginning of your update script. It’s important to note that anything your script prints to stdout will be transferred to the client.
+
+The next thing you’ll notice is the error message.
+
+ [POLICY] Cannot push a non fast-forward reference
+ error: hooks/update exited with error code 1
+ error: hook declined to update refs/heads/master
+
+The first line was printed out by you, the other two were Git telling you that the update script exited non-zero and that is what is declining your push. Lastly, you have this:
+
+ To git@gitserver:project.git
+ ! [remote rejected] master -> master (hook declined)
+ error: failed to push some refs to 'git@gitserver:project.git'
+
+You’ll see a remote rejected message for each reference that your hook declined, and it tells you that it was declined specifically because of a hook failure.
+
+Furthermore, if the ref marker isn’t there in any of your commits, you’ll see the error message you’re printing out for that.
+
+ [POLICY] Your message is not formatted correctly
+
+Or if someone tries to edit a file they don’t have access to and push a commit containing it, they will see something similar. For instance, if a documentation author tries to push a commit modifying something in the `lib` directory, they see
+
+ [POLICY] You do not have access to push to lib/test.rb
+
+That’s all. From now on, as long as that `update` script is there and executable, your repository will never be rewound and will never have a commit message without your pattern in it, and your users will be sandboxed.
+
+### Client-Side Hooks ###
+
+The downside to this approach is the whining that will inevitably result when your users’ commit pushes are rejected. Having their carefully crafted work rejected at the last minute can be extremely frustrating and confusing; and furthermore, they will have to edit their history to correct it, which isn’t always for the faint of heart.
+
+The answer to this dilemma is to provide some client-side hooks that users can use to notify them when they’re doing something that the server is likely to reject. That way, they can correct any problems before committing and before those issues become more difficult to fix. Because hooks aren’t transferred with a clone of a project, you must distribute these scripts some other way and then have your users copy them to their `.git/hooks` directory and make them executable. You can distribute these hooks within the project or in a separate project, but there is no way to set them up automatically.
+
+To begin, you should check your commit message just before each commit is recorded, so you know the server won’t reject your changes due to badly formatted commit messages. To do this, you can add the `commit-msg` hook. If you have it read the message from the file passed as the first argument and compare that to the pattern, you can force Git to abort the commit if there is no match:
+
+ #!/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
+
+If that script is in place (in `.git/hooks/commit-msg`) and executable, and you commit with a message that isn’t properly formatted, you see this:
+
+ $ git commit -am 'test'
+ [POLICY] Your message is not formatted correctly
+
+No commit was completed in that instance. However, if your message contains the proper pattern, Git allows you to commit:
+
+ $ git commit -am 'test [ref: 132]'
+ [master e05c914] test [ref: 132]
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+Next, you want to make sure you aren’t modifying files that are outside your ACL scope. If your project’s `.git` directory contains a copy of the ACL file you used previously, then the following `pre-commit` script will enforce those constraints for you:
+
+ #!/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
+
+This is roughly the same script as the server-side part, but with two important differences. First, the ACL file is in a different place, because this script runs from your working directory, not from your Git directory. You have to change the path to the ACL file from this
+
+ access = get_acl_access_data('acl')
+
+to this:
+
+ access = get_acl_access_data('.git/acl')
+
+The other important difference is the way you get a listing of the files that have been changed. Because the server-side method looks at the log of commits, and, at this point, the commit hasn’t been recorded yet, you must get your file listing from the staging area instead. Instead of
+
+ files_modified = `git log -1 --name-only --pretty=format:'' #{ref}`
+
+you have to use
+
+ files_modified = `git diff-index --cached --name-only HEAD`
+
+But those are the only two differences — otherwise, the script works the same way. One caveat is that it expects you to be running locally as the same user you push as to the remote machine. If that is different, you must set the `$user` variable manually.
+
+The last thing you have to do is check that you’re not trying to push non-fast-forwarded references, but that is a bit less common. To get a reference that isn’t a fast-forward, you either have to rebase past a commit you’ve already pushed up or try pushing a different local branch up to the same remote branch.
+
+Because the server will tell you that you can’t push a non-fast-forward anyway, and the hook prevents forced pushes, the only accidental thing you can try to catch is rebasing commits that have already been pushed.
+
+Here is an example pre-rebase script that checks for that. It gets a list of all the commits you’re about to rewrite and checks whether they exist in any of your remote references. If it sees one that is reachable from one of your remote references, it aborts the rebase:
+
+ #!/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
+
+This script uses a syntax that wasn’t covered in the Revision Selection section of Chapter 6. You get a list of commits that have already been pushed up by running this:
+
+ git rev-list ^#{sha}^@ refs/remotes/#{remote_ref}
+
+The `SHA^@` syntax resolves to all the parents of that commit. You’re looking for any commit that is reachable from the last commit on the remote and that isn’t reachable from any parent of any of the SHAs you’re trying to push up — meaning it’s a fast-forward.
+
+The main drawback to this approach is that it can be very slow and is often unnecessary — if you don’t try to force the push with `-f`, the server will warn you and not accept the push. However, it’s an interesting exercise and can in theory help you avoid a rebase that you might later have to go back and fix.
+
+## Summary ##
+
+You’ve covered most of the major ways that you can customize your Git client and server to best fit your workflow and projects. You’ve learned about all sorts of configuration settings, file-based attributes, and event hooks, and you’ve built an example policy-enforcing server. You should now be able to make Git fit nearly any workflow you can dream up.
View
324 de/08-git-and-other-scms/01-chapter8.markdown 100755 → 100644
@@ -1,51 +1,61 @@
# Git und andere Versionsverwaltungen #
-The world isn’t perfect. Usually, you can’t immediately switch every project you come in contact with to Git. Sometimes you’re stuck on a project using another VCS, and many times that system is Subversion. You’ll spend the first part of this chapter learning about `git svn`, the bidirectional Subversion gateway tool in Git.
+<!--The world isn’t perfect. Usually, you can’t immediately switch every project you come in contact with to Git. Sometimes you’re stuck on a project using another VCS, and many times that system is Subversion. You’ll spend the first part of this chapter learning about `git svn`, the bidirectional Subversion gateway tool in Git.-->
-Leider ist die Welt nicht perfekt. Normalerweise kannst Du nicht bei jedem Deiner Projekt sofort auf Git umsteigen. Manchmal musst Du in einem Deiner Projekte irgendeine andere Versionsverwaltung nutzen, ziemlich oft ist das Subversion. Im ersten Teil dieses Kapitels werden wir das bidirektionale Gateway zwischen Git und Subversion kennezulernen: `git svn`.
+Leider ist die Welt nicht perfekt. Normalerweise kannst Du nicht bei jedem Deiner Projekt sofort auf Git umsteigen. Manchmal musst Du in einem Deiner Projekte irgendeine andere Versionsverwaltung nutzen, ziemlich oft ist das Subversion. Im ersten Teil dieses Kapitels werden wir das bidirektionale Gateway zwischen Git und Subversion kennenzulernen: `git svn`.
-At some point, you may want to convert your existing project to Git. The second part of this chapter covers how to migrate your project into Git: first from Subversion, then from Perforce, and finally via a custom import script for a nonstandard importing case.
+<!--At some point, you may want to convert your existing project to Git. The second part of this chapter covers how to migrate your project into Git: first from Subversion, then from Perforce, and finally via a custom import script for a nonstandard importing case.-->
Manchmal kommst Du an den Zeitpunkt, zu dem Du ein bestehendes Projekt zu Git konvertieren willst. Der zweite Teil dieses Kapitels zeigt Dir, wie Du Dein Projekt zu Git migrieren kannst. Zunächst behandeln wir Subversion, dann Perforce und zum Schluss verwenden wir ein angepasstes Import-Skript, um einen nicht standard-mäßigen Import abzudecken.
## Git und Subversion ##
-Currently, the majority of open source development projects and a large number of corporate projects use Subversion to manage their source code. It’s the most popular open source VCS and has been around for nearly a decade. It’s also very similar in many ways to CVS, which was the big boy of the source-control world before that.
+<!--Currently, the majority of open source development projects and a large number of corporate projects use Subversion to manage their source code. It’s the most popular open source VCS and has been around for nearly a decade. It’s also very similar in many ways to CVS, which was the big boy of the source-control world before that.-->
Gegenwärtig verwenden die meisten Open Source Entwicklungsprojekte und eine große Anzahl von Projekten in Unternehmen Subversion, um ihren Quellcode zu verwalten. Es ist die populärste Open Source Versionsverwaltung und wird seit fast einem Jahrzehnt eingesetzt. In vielen Bereichen ähnelt es CVS, das vorher der König der Versionsverwaltungen war.
-One of Git’s great features is a bidirectional bridge to Subversion called `git svn`. This tool allows you to use Git as a valid client to a Subversion server, so you can use all the local features of Git and then push to a Subversion server as if you were using Subversion locally. This means you can do local branching and merging, use the staging area, use rebasing and cherry-picking, and so on, while your collaborators continue to work in their dark and ancient ways. It’s a good way to sneak Git into the corporate environment and help your fellow developers become more efficient while you lobby to get the infrastructure changed to support Git fully. The Subversion bridge is the gateway drug to the DVCS world.
+<!--One of Git’s great features is a bidirectional bridge to Subversion called `git svn`. This tool allows you to use Git as a valid client to a Subversion server, so you can use all the local features of Git and then push to a Subversion server as if you were using Subversion locally. This means you can do local branching and merging, use the staging area, use rebasing and cherry-picking, and so on, while your collaborators continue to work in their dark and ancient ways. It’s a good way to sneak Git into the corporate environment and help your fellow developers become more efficient while you lobby to get the infrastructure changed to support Git fully. The Subversion bridge is the gateway drug to the DVCS world.-->
Eines der großartigen Features von Git ist die bi-direktionale Brücke zu Subversion: `git svn`. Diese Tool ermöglicht es, Git als ganz normalen Client für einen Subversion-Server zu benutzen, so dass Du alle lokalen Features von Git nutzen kanns und Deine Änderungen dann auf einen Subversion-Server pushen kannst, so als ob Du Subversion lokal nutzen würdest. Das bedeutet, dass Du lokale Branches anlegen kannst, mergen, die staging area, rebasing, cherry-picking etc. verwenden, während Deine Kollegen weiterhin aus ihre angestaubte Art und Weise arbeiten. Das ist eine gute Gelegenheit, um Git in einem Unternehmen einzuführen und Deinen Entwickler-Kollegen dabei zu helfen, effizienter zu werden während Du an der Unterstützung arbeitest, die Infrastruktur so umzubauen, dass Git voll unterstützt wird. Die Subversion-Bridge von Git ist quasi die Einstiegsdroge in die Welt der verteilten Versionsverwaltungssysteme (distributed version control systems, DVCS).
### git svn ###
-The base command in Git for all the Subversion bridging commands is `git svn`. You preface everything with that. It takes quite a few commands, so you’ll learn about the common ones while going through a few small workflows.
+<!--The base command in Git for all the Subversion bridging commands is `git svn`. You preface everything with that. It takes quite a few commands, so you’ll learn about the common ones while going through a few small workflows.-->
Das Haupt-Kommando in Git für alle Kommandos der Subversion Bridge ist `git svn`. Dieser Befehl wird allen anderen vorangestellt. Er kennt zahlreiche Optionen, daher werde wir jetzt die gebräuchlichsten zusammen anhand von ein paar Beispielen durchspielen.
-It’s important to note that when you’re using `git svn`, you’re interacting with Subversion, which is a system that is far less sophisticated than Git. Although you can easily do local branching and merging, it’s generally best to keep your history as linear as possible by rebasing your work and avoiding doing things like simultaneously interacting with a Git remote repository.
+<!--It’s important to note that when you’re using `git svn`, you’re interacting with Subversion, which is a system that is far less sophisticated than Git. Although you can easily do local branching and merging, it’s generally best to keep your history as linear as possible by rebasing your work and avoiding doing things like simultaneously interacting with a Git remote repository.-->
Es ist wichtig, dass Du im Hinterkopf behältst, dass Du mit dem `git svn` Befehl mit Subversion interagierst, eine System, dass nicht ganz so fortschrittlich ist wie Git. Obwohl Du auch dort ganz einfach Branches erstellen und wieder zusammenführen kannst, ist es üblicherweise am einfachsten, wenn Du die History so geradlinig wie möglich gestaltest, indem Du ein rebase für Deine Arbeit durchfürst und es vermeidest, zum Beispiel mit einem entfernten Git-Repository zu interagieren.
-Don’t rewrite your history and try to push again, and don’t push to a parallel Git repository to collaborate with fellow Git developers at the same time. Subversion can have only a single linear history, and confusing it is very easy. If you’re working with a team, and some are using SVN and others are using Git, make sure everyone is using the SVN server to collaborate — doing so will make your life easier.
+<!--Don’t rewrite your history and try to push again, and don’t push to a parallel Git repository to collaborate with fellow Git developers at the same time. Subversion can have only a single linear history, and confusing it is very easy. If you’re working with a team, and some are using SVN and others are using Git, make sure everyone is using the SVN server to collaborate — doing so will make your life easier.-->
Du solltest auf keinen Fall Deine History neu schreiben und dann versuchen, die Änderungen zu publizieren. Bitte schick Deine Änderungen auch nicht zeitgleich dazu an ein anderes Git-Repository, in dem Du mit Deinen Kollegen zusammenarbeitest, die bereits Git nutzen. Subversion kennt nur eine einzige lineare History für das gesamte Repository und da kommt man schnell mal durcheinander. Wenn Du in einem Team arbeitest, in dem manche Deiner Kollegen SVN und andere schon Git nutzen, dann solltest Du sicherstellen, dass Ihr alle einen SVN-Server zur Zusammenarbeit nutzt, das macht Dein Leben deutlich einfacher.
+<<<<<<< HEAD
### Installation (Setting Up) ###
To demonstrate this functionality, you need a typical SVN repository that you have write access to. If you want to copy these examples, you’ll have to make a writeable copy of my test repository. In order to do that easily, you can use a tool called `svnsync` that comes with more recent versions of Subversion — it should be distributed with at least 1.4. For these tests, I created a new Subversion repository on Google code that was a partial copy of the `protobuf` project, which is a tool that encodes structured data for network transmission.
Um dieses Feature zu demonstrieren, brauchst Du zunächst ein typisches SVN-Repository, in dem Du Schreibzugriff hast. Wenn Du die folgenden Beispiele selbst ausprobieren willst, brauchst Du eine beschreibbare Kopie meines Test-Repositories. Das geht ganz einfach mit einem kleinen Tool namens `svnsync`, das mit den letzten Subversion-Versionen (ab Version 1.4) mitgeliefert wird. Für diese Test habe ich ein neues Subversion Repository auf Google Code angelegt, das einen Teil aus dem `protobuf`-Projekts kopiert, einem Tool, das Datenstrukturen für die Übertragung über ein Netzwerk umwandelt.
To follow along, you first need to create a new local Subversion repository:
+=======
+### Installation ###
+
+<!--To demonstrate this functionality, you need a typical SVN repository that you have write access to. If you want to copy these examples, you’ll have to make a writeable copy of my test repository. In order to do that easily, you can use a tool called `svnsync` that comes with more recent versions of Subversion — it should be distributed with at least 1.4. For these tests, I created a new Subversion repository on Google code that was a partial copy of the `protobuf` project, which is a tool that encodes structured data for network transmission.-->
+
+Um dieses Feature zu demonstrieren, brauchst Du zunächst ein typisches SVN-Repository, in dem Du Schreibzugriff hast. Wenn Du die folgenden Beispiele selbst ausprobieren willst, brauchst Du eine beschreibbare Kopie meines Test-Repositories. Das geht ganz einfach mit einem kleinen Tool namens `svnsync`, das mit den letzten Subversion-Versionen (ab Version 1.4) mitgeliefert wird. Für diese Test habe ich ein neues Subversion Repository auf Google Code angelegt, das einen Teil aus dem `protobuf`-Projekts kopiert, einem Tool, das Datenstrukturen für die Übertragung über ein Netzwerk umwandelt.
+
+<!--To follow along, you first need to create a new local Subversion repository:-->
+>>>>>>> svenfuchs/master
Zunächst einmal musst Du ein neues lokales Subversion-Repository anlegen:
$ mkdir /tmp/test-svn
$ svnadmin create /tmp/test-svn
-Then, enable all users to change revprops — the easy way is to add a pre-revprop-change script that always exits 0:
+<!--Then, enable all users to change revprops — the easy way is to add a pre-revprop-change script that always exits 0:-->
Anschließend gibst Du allen Usern die Möglichkeit, die revprops zu ändern. Am einfachsten geht das, indem wir ein pre-revprop-change Skript erstellen, das immer 0 zurückgibt:
@@ -54,13 +64,13 @@ Anschließend gibst Du allen Usern die Möglichkeit, die revprops zu ändern. Am
exit 0;
$ chmod +x /tmp/test-svn/hooks/pre-revprop-change
-You can now sync this project to your local machine by calling `svnsync init` with the to and from repositories.
+<!--You can now sync this project to your local machine by calling `svnsync init` with the to and from repositories.-->
Jetzt kannst Du dieses Projekt auf Deinen lokalen Rechner mit einem Aufruf von `svnsync init` synchronisieren. Als Optionen gibst Du das Ziel- und das Quell-Repository an.
$ svnsync init file:///tmp/test-svn http://progit-example.googlecode.com/svn/
-This sets up the properties to run the sync. You can then clone the code by running
+<!--This sets up the properties to run the sync. You can then clone the code by running-->
Das richtet die Properties ein, um die Synchronisierung laufen zu lassen. Nun kannst Du den Code klonen:
@@ -72,13 +82,13 @@ Das richtet die Properties ein, um die Synchronisierung laufen zu lassen. Nun ka
Committed revision 3.
...
-Although this operation may take only a few minutes, if you try to copy the original repository to another remote repository instead of a local one, the process will take nearly an hour, even though there are fewer than 100 commits. Subversion has to clone one revision at a time and then push it back into another repository — it’s ridiculously inefficient, but it’s the only easy way to do this.
+<!--Although this operation may take only a few minutes, if you try to copy the original repository to another remote repository instead of a local one, the process will take nearly an hour, even though there are fewer than 100 commits. Subversion has to clone one revision at a time and then push it back into another repository — it’s ridiculously inefficient, but it’s the only easy way to do this.-->
Obwohl diese Operation möglicherweise nur ein paar wenige Minuten in Anspruch nimmt, wird das Kopieren des Quell-Repositories von einem entfernten Repository in ein lokales fast eine Stunde dauern, auch wenn weniger als 100 Commits getätigt wurden. Subversion muss jede Revision einzeln klonen und sie dann in ein anderes Repository schieben - das ist zwar ziemlich ineffizient, aber für uns der einfachste Weg.
### Die ersten Schritte (Getting Started) ###
-Now that you have a Subversion repository to which you have write access, you can go through a typical workflow. You’ll start with the `git svn clone` command, which imports an entire Subversion repository into a local Git repository. Remember that if you’re importing from a real hosted Subversion repository, you should replace the `file:///tmp/test-svn` here with the URL of your Subversion repository:
+<!--Now that you have a Subversion repository to which you have write access, you can go through a typical workflow. You’ll start with the `git svn clone` command, which imports an entire Subversion repository into a local Git repository. Remember that if you’re importing from a real hosted Subversion repository, you should replace the `file:///tmp/test-svn` here with the URL of your Subversion repository:-->
Jetzt, da wir ein beschreibbares Subversion Repository haben, können wir mit einem typischen Workflow loslegen. Du beginnst mit dem `git svn clone`Kommando, das ein komplettes Subversion-Repository in ein lokales Git-Repository importiert. Denk daran, dass Du `file:///tmp/test-svn` im folgenden Beispiel mit der URL Deines eigenen Subversion-Repositorys ersetzt, wenn Du den Import für ein real existierendes Subversion-Repository durchführen willst.
@@ -98,17 +108,17 @@ Jetzt, da wir ein beschreibbares Subversion Repository haben, können wir mit ei
Checked out HEAD:
file:///tmp/test-svn/branches/my-calc-branch r76
-This runs the equivalent of two commands — `git svn init` followed by `git svn fetch` — on the URL you provide. This can take a while. The test project has only about 75 commits and the codebase isn’t that big, so it takes just a few minutes. However, Git has to check out each version, one at a time, and commit it individually. For a project with hundreds or thousands of commits, this can literally take hours or even days to finish.
+<!--This runs the equivalent of two commands — `git svn init` followed by `git svn fetch` — on the URL you provide. This can take a while. The test project has only about 75 commits and the codebase isn’t that big, so it takes just a few minutes. However, Git has to check out each version, one at a time, and commit it individually. For a project with hundreds or thousands of commits, this can literally take hours or even days to finish.-->
Hier werden für die angegebene URL eigentlich zwei Befehle ausgeführt, `git svn init` und anschließend `git svn fetch`. Das kann auch eine Weile dauern. Das Testprojekt hat nur etwa 75 Commits und die Codebase ist nicht so groß, daher benötigen wir nur ein paar Minuten. Da Git aber jede Version einzeln auschecken muss, kann es unter Umständen Stunden oder gar Tage dauern, bis die Ausführung des Befehls fertig ist.
-The `-T trunk -b branches -t tags` part tells Git that this Subversion repository follows the basic branching and tagging conventions. If you name your trunk, branches, or tags differently, you can change these options. Because this is so common, you can replace this entire part with `-s`, which means standard layout and implies all those options. The following command is equivalent:
+<!--The `-T trunk -b branches -t tags` part tells Git that this Subversion repository follows the basic branching and tagging conventions. If you name your trunk, branches, or tags differently, you can change these options. Because this is so common, you can replace this entire part with `-s`, which means standard layout and implies all those options. The following command is equivalent:-->
Die Parameter `-T trunk -b branches -t tags` teilen Git mit, dass das Subversion-Repository den normalen Konventionen bezüglich Branching und Tagging folgt. Wenn Du Deinen Trunk, Deine Branches oder Deine Tags anders benannt hast, kannst Du diese hier anpassen. Da die Angabe aus dem Beispiel für die meisten Repositories gängig ist, kannst Du das ganze auch mit `-s` abkürzen. Diese Option steht für das Standard-Repository-Layount und umfasst die oben genannten Parameter. Der folgende Befehl ist äquivalent zum zuvor genannten:
$ git svn clone file:///tmp/test-svn -s
-At this point, you should have a valid Git repository that has imported your branches and tags:
+<!--At this point, you should have a valid Git repository that has imported your branches and tags:-->
Jetzt solltest Du ein Git-Repository erzeugt haben, in das Deine Branches und Tags übernommen wurden:
@@ -121,7 +131,7 @@ Jetzt solltest Du ein Git-Repository erzeugt haben, in das Deine Branches und Ta
tags/release-2.0.2rc1
trunk
-It’s important to note how this tool namespaces your remote references differently. When you’re cloning a normal Git repository, you get all the branches on that remote server available locally as something like `origin/[branch]` - namespaced by the name of the remote. However, `git svn` assumes that you won’t have multiple remotes and saves all its references to points on the remote server with no namespacing. You can use the Git plumbing command `show-ref` to look at all your full reference names:
+<!--It’s important to note how this tool namespaces your remote references differently. When you’re cloning a normal Git repository, you get all the branches on that remote server available locally as something like `origin/[branch]` - namespaced by the name of the remote. However, `git svn` assumes that you won’t have multiple remotes and saves all its references to points on the remote server with no namespacing. You can use the Git plumbing command `show-ref` to look at all your full reference names:-->
An dieser Stelle soll die wichtige Anmerkung nicht fehlen, dass dieses Tool die Namespaces Deiner entfernten Referenzen unterschiedlich behandelt. Wenn Du ein normales Git-Repository klonst, werden alle Branches auf jenem entfernten Server für Dich lokal verfügbar gemacht, zum Beispiel als `origin/[branch]`, der Namespace entspricht dem Namen des entfernten Branches. `git svn` get allerdings davon aus, dass es nicht mehrere entfernte Repositorys gibt und speichert daher seie Referenzen auf die Bereiche entfernter Server ohne Namespaces. Du kannst das Git-Kommando `show-ref` verwenden, um Dir die vollständigen Namen aller Referenzen anzeigen zu lassen:
@@ -134,7 +144,7 @@ An dieser Stelle soll die wichtige Anmerkung nicht fehlen, dass dieses Tool die
1c4cb508144c513ff1214c3488abe66dcb92916f refs/remotes/tags/release-2.0.2rc1
1cbd4904d9982f386d87f88fce1c24ad7c0f0471 refs/remotes/trunk
-A normal Git repository looks more like this:
+<!--A normal Git repository looks more like this:-->
Ein normales Git-Repository sieht dagegen eher so aus:
@@ -144,25 +154,29 @@ Ein normales Git-Repository sieht dagegen eher so aus:
0a30dd3b0c795b80212ae723640d4e5d48cabdff refs/remotes/origin/master
25812380387fdd55f916652be4881c6f11600d6f refs/remotes/origin/testing
-You have two remote servers: one named `gitserver` with a `master` branch; and another named `origin` with two branches, `master` and `testing`.
+<!--You have two remote servers: one named `gitserver` with a `master` branch; and another named `origin` with two branches, `master` and `testing`.-->
Du hast zwei entfernte Server: einen, der `gitserver` heißt und einen `master`-Branch beinhaltet, und einen weiteren, der `origin` heißt und zwei Branches (`master` und `testing`) enthält.
-Notice how in the example of remote references imported from `git svn`, tags are added as remote branches, not as real Git tags. Your Subversion import looks like it has a remote named tags with branches under it.
+<!--Notice how in the example of remote references imported from `git svn`, tags are added as remote branches, not as real Git tags. Your Subversion import looks like it has a remote named tags with branches under it.-->
Hast Du bemerkt, dass die entfernten Referenzen, die von `git svn` im Beispiel importiert wurden, nicht als echte Git-Tags importiert wurden, sondern als entfernte Branches? Dein Subversion-Import sieht aus als besäße er einen eigenen Remote-Bereich namens `tags` und unterhalb davon einzelne Branches.
+<<<<<<< HEAD
### Änderungen ins Subversion-Repository übernehmen (Committing Back to Subversion) ###
+=======
+### Änderungen ins Subversion-Repository committen ###
+>>>>>>> svenfuchs/master
-Now that you have a working repository, you can do some work on the project and push your commits back upstream, using Git effectively as a SVN client. If you edit one of the files and commit it, you have a commit that exists in Git locally that doesn’t exist on the Subversion server:
+<!--Now that you have a working repository, you can do some work on the project and push your commits back upstream, using Git effectively as a SVN client. If you edit one of the files and commit it, you have a commit that exists in Git locally that doesn’t exist on the Subversion server:-->
Mit unserem funktionierenden Repository können wir nun am Projekt arbeiten und unsere Änderungen commiten; dabei nutzen wir Git als SVN-Client. Wenn du eine der Dateien bearbeitest und sie commitest, hast Du lokal einen Commit in Git, der auf dem Subversion-Server (noch) nicht vorhanden ist:
$ git commit -am 'Adding git-svn instructions to the README'
[master 97031e5] Adding git-svn instructions to the README
1 files changed, 1 insertions(+), 1 deletions(-)
-Next, you need to push your change upstream. Notice how this changes the way you work with Subversion — you can do several commits offline and then push them all at once to the Subversion server. To push to a Subversion server, you run the `git svn dcommit` command:
+<!--Next, you need to push your change upstream. Notice how this changes the way you work with Subversion — you can do several commits offline and then push them all at once to the Subversion server. To push to a Subversion server, you run the `git svn dcommit` command:-->
Als nächsten Schritt wirst Du Deine Änderungen einchecken wollen. Dein Umgang mit Subversion wird sich dabei verändern -- Du kannst eine Vielzahl an Commits lokal durchführen und dann alle zusammen an den Subversion-Server schicken. Um Deine Änderungen auf den Subversion-Server zu pushen, verwendest Du das `git svn dcommit` Kommando:
@@ -175,7 +189,7 @@ Als nächsten Schritt wirst Du Deine Änderungen einchecken wollen. Dein Umgang
No changes between current HEAD and refs/remotes/trunk
Resetting to the latest refs/remotes/trunk
-This takes all the commits you’ve made on top of the Subversion server code, does a Subversion commit for each, and then rewrites your local Git commit to include a unique identifier. This is important because it means that all the SHA-1 checksums for your commits change. Partly for this reason, working with Git-based remote versions of your projects concurrently with a Subversion server isn’t a good idea. If you look at the last commit, you can see the new `git-svn-id` that was added:
+<!--This takes all the commits you’ve made on top of the Subversion server code, does a Subversion commit for each, and then rewrites your local Git commit to include a unique identifier. This is important because it means that all the SHA-1 checksums for your commits change. Partly for this reason, working with Git-based remote versions of your projects concurrently with a Subversion server isn’t a good idea. If you look at the last commit, you can see the new `git-svn-id` that was added:-->
Das bündelt alle Commits, die Du auf Basis des Codes im Subversion-Server durchgeführt hast und und führt für jede Änderung ein Subversion-Commit durch. Anschließend werden Deine lokalen Git-Commits angepasst und jeder von ihnen bekommt einen eindeutigen Identifier. Das bedeutet, dass alle SHA-1 Checksums Deiner Commits verändert werden. Dies ist einer der Gründe, warum das Arbeiten mit Git-basierten entfernten Versionen Deines Projekts und zeitgleich mit einem Subversion-Server keine gute Idee ist. Wenn Du Dir den letzten Commit ansiehst, wirst Du feststellen, dass eine neue `git-svn-id` hinzugefügt wurde.
@@ -188,13 +202,13 @@ Das bündelt alle Commits, die Du auf Basis des Codes im Subversion-Server durch
git-svn-id: file:///tmp/test-svn/trunk@79 4c93b258-373f-11de-be05-5f7a86268029
-Notice that the SHA checksum that originally started with `97031e5` when you committed now begins with `938b1a5`. If you want to push to both a Git server and a Subversion server, you have to push (`dcommit`) to the Subversion server first, because that action changes your commit data.
+<!--Notice that the SHA checksum that originally started with `97031e5` when you committed now begins with `938b1a5`. If you want to push to both a Git server and a Subversion server, you have to push (`dcommit`) to the Subversion server first, because that action changes your commit data.-->
Die SHA-Checksum Deines ursprünglichen Commits begann mit `97031e5`, jetzt fängt sie mit `938b1a5` an. Wenn Du zugleich auf einen Git- und einen Subversion-Server pushen willst, solltest Du zunächst an den Subversion-Server pushen (`dcommit`), da diese Aktion Deine Commit-Daten verändert.
-### Änderungen lokal einarbeiten (Pulling in New Changes) ###
+### Änderungen ins lokale Repository übernehmen ###
-If you’re working with other developers, then at some point one of you will push, and then the other one will try to push a change that conflicts. That change will be rejected until you merge in their work. In `git svn`, it looks like this:
+<!--If you’re working with other developers, then at some point one of you will push, and then the other one will try to push a change that conflicts. That change will be rejected until you merge in their work. In `git svn`, it looks like this:-->
Wenn Du mit anderen Entwicklern zusammenarbeitest, wirst Du irgendwann an den Punkt gelangen an dem einer von Euch Änderungen ins Repository pusht und jemand anderes versuchen wird, ebenfalls seine Änderungen zu pushen und damit einen Konflikt erzeugt. Diese Änderung wird solange zurückgewiesen bis Du die Arbeit des anderen Entwicklers mergt. Mit `git svn` sieht das so aus:
@@ -204,7 +218,7 @@ Wenn Du mit anderen Entwicklern zusammenarbeitest, wirst Du irgendwann an den Pu
out-of-date: resource out of date; try updating at /Users/schacon/libexec/git-\
core/git-svn line 482
-To resolve this situation, you can run `git svn rebase`, which pulls down any changes on the server that you don’t have yet and rebases any work you have on top of what is on the server:
+<!--To resolve this situation, you can run `git svn rebase`, which pulls down any changes on the server that you don’t have yet and rebases any work you have on top of what is on the server:-->
Um diese Situation zu lösen, kannst Du `git svn rebase` laufen lassen. Das zieht alle Änderungen vom Server, die Dir noch fehlen und führt ein rebase Deiner lokalen Kopie durch (auf Basis dessen, was auf dem Server vorhanden ist).
@@ -214,7 +228,7 @@ Um diese Situation zu lösen, kannst Du `git svn rebase` laufen lassen. Das zieh
First, rewinding head to replay your work on top of it...
Applying: first user change
-Now, all your work is on top of what is on the Subversion server, so you can successfully `dcommit`:
+<!--Now, all your work is on top of what is on the Subversion server, so you can successfully `dcommit`:-->
Jetzt sind alle Deine Arbeiten auf der gleichen Ebene wie die auf dem Subversion-Server und nun kannst Du erfolgreich ein `dcommit` absetzen:
@@ -227,7 +241,7 @@ Jetzt sind alle Deine Arbeiten auf der gleichen Ebene wie die auf dem Subversion
No changes between current HEAD and refs/remotes/trunk
Resetting to the latest refs/remotes/trunk
-It’s important to remember that unlike Git, which requires you to merge upstream work you don’t yet have locally before you can push, `git svn` makes you do that only if the changes conflict. If someone else pushes a change to one file and then you push a change to another file, your `dcommit` will work fine:
+<!--It’s important to remember that unlike Git, which requires you to merge upstream work you don’t yet have locally before you can push, `git svn` makes you do that only if the changes conflict. If someone else pushes a change to one file and then you push a change to another file, your `dcommit` will work fine:-->
Es ist wichtig, im Hinterkopf zu behalten, dass `git svn` sich an dieser Stelle anders als Git verhält. Git erwartet von Dir, dass Du upstream-Arbeiten, die Du lokal noch nicht hast, zunächst mergst, bevor Du pushen kannst. Dieses Vorgehen ist bei `git svn` nur nötig, wenn es Konflikte bei den Änderungen gibt. Wenn jemand anderes eine geänderte Datei gepusht hat und Du eine andere geänderte Datei pushst, wird Dein `dcommit` problemlos funktionieren:
@@ -246,23 +260,33 @@ Es ist wichtig, im Hinterkopf zu behalten, dass `git svn` sich an dieser Stelle
First, rewinding head to replay your work on top of it...
Nothing to do.
-This is important to remember, because the outcome is a project state that didn’t exist on either of your computers when you pushed. If the changes are incompatible but don’t conflict, you may get issues that are difficult to diagnose. This is different than using a Git server — in Git, you can fully test the state on your client system before publishing it, whereas in SVN, you can’t ever be certain that the states immediately before commit and after commit are identical.
+<!--This is important to remember, because the outcome is a project state that didn’t exist on either of your computers when you pushed. If the changes are incompatible but don’t conflict, you may get issues that are difficult to diagnose. This is different than using a Git server — in Git, you can fully test the state on your client system before publishing it, whereas in SVN, you can’t ever be certain that the states immediately before commit and after commit are identical.-->
-You should also run this command to pull in changes from the Subversion server, even if you’re not ready to commit yourself. You can run `git svn fetch` to grab the new data, but `git svn rebase` does the fetch and then updates your local commits.
+Das ist darum wichtig, weil der daraus resultierende Projekt-Status auf keinem der Computer existierte als Du die Änderungen gepusht hast. Wenn die Änderungen nicht zueinander kompatibel sind aber keinen Konflikt ergeben, wirst Du Probleme bekommen, die schwer zu diagnostizieren sind. Das ist der Unterschied zu einem Git-Server — mit Git kannst Du den Zustand Deines Client-Systems komplett testen bevor Du ihn veröffentlichst, während Du bei Subversion nie sicher sein kannst, dass der Zustand direkt vor und direkt nach dem Commit identisch sind.
+
+<!--You should also run this command to pull in changes from the Subversion server, even if you’re not ready to commit yourself. You can run `git svn fetch` to grab the new data, but `git svn rebase` does the fetch and then updates your local commits.-->
+
+Du solltest Dieses Kommando auch ausführen um Änderungen vom Subversion-Server zu ziehen, selbst wenn Du noch nicht so weit bist, einen Commit durchzuführen. Du kannst `git svn fetch` ausführen um die neuen Daten zu besorgen aber `git svn rebase` zieht die Daten ebenfalls und aktualisiert Deine lokalen Commits.
$ git svn rebase
M generate_descriptor_proto.sh
r82 = bd16df9173e424c6f52c337ab6efa7f7643282f1 (trunk)
First, rewinding head to replay your work on top of it...
Fast-forwarded master to refs/remotes/trunk.
-Running `git svn rebase` every once in a while makes sure your code is always up to date. You need to be sure your working directory is clean when you run this, though. If you have local changes, you must either stash your work or temporarily commit it before running `git svn rebase` — otherwise, the command will stop if it sees that the rebase will result in a merge conflict.
+<!--Running `git svn rebase` every once in a while makes sure your code is always up to date. You need to be sure your working directory is clean when you run this, though. If you have local changes, you must either stash your work or temporarily commit it before running `git svn rebase` — otherwise, the command will stop if it sees that the rebase will result in a merge conflict.-->
+
+Wenn Du `git svn rebase`ab und an ausführst, stellst Du sicher, dass Dein Code immer up-to-date ist. Du musst Dir aber sicher sein, dass Dein Arbeitsverzeichnis "sauber" ist, bevor Du den Befehl ausführst. Wenn Du lokale Änderungen hast, musst Du Deine Arbeit vor dem `git svn rebase` entweder stashen oder temporär commiten. Anderenfalls wird die Ausführung des Befehls angehalten, wenn das Rebase in einem Merge-Konflikt enden würde.
+
+### Probleme beim Benutzen von Branches ###
-### Git Branching Issues ###
+<!--When you’ve become comfortable with a Git workflow, you’ll likely create topic branches, do work on them, and then merge them in. If you’re pushing to a Subversion server via git svn, you may want to rebase your work onto a single branch each time instead of merging branches together. The reason to prefer rebasing is that Subversion has a linear history and doesn’t deal with merges like Git does, so git svn follows only the first parent when converting the snapshots into Subversion commits.-->
-When you’ve become comfortable with a Git workflow, you’ll likely create topic branches, do work on them, and then merge them in. If you’re pushing to a Subversion server via git svn, you may want to rebase your work onto a single branch each time instead of merging branches together. The reason to prefer rebasing is that Subversion has a linear history and doesn’t deal with merges like Git does, so git svn follows only the first parent when converting the snapshots into Subversion commits.
+Wenn Du Dich an den Git-Workflow gewöhnt hast, wirst Du höchstwahrscheinlich Zweige für Deine Arbeitspakete anlegen, mit ihnen arbeiten und sie anschließend wieder mergen. Wenn Du mit `git svn` auf einen Subversion-Server pushst, führst Du am besten eine Rebase-Operation in einen einzigen Zweig durch anstatt alle Zweige zusammenzufügen. Der Grund dafür, das Rebase zu bevorzugen, liegt darin, dass Subversion eine lineare Historie hat und mit dem Merge-Operationen nicht wie Git es tut. Daher folgt `git svn` nur dem ersten Elternelement, wenn es Snapshots in Subversion-Commits umwandelt.
-Suppose your history looks like the following: you created an `experiment` branch, did two commits, and then merged them back into `master`. When you `dcommit`, you see output like this:
+<!--Suppose your history looks like the following: you created an `experiment` branch, did two commits, and then merged them back into `master`. When you `dcommit`, you see output like this:-->
+
+Angenommen, Deine Historie sieht wie folgt aus: Du hast einen Zweig mit dem Namen `experiment` angelegt, zwei Commits durchgeführt und diese dann anschließen mit `master`zusammengeführt. Führst Du nun ein `dcommit` durch, sieht die Ausgabe wie folgt aus:
$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
@@ -283,17 +307,25 @@ Suppose your history looks like the following: you created an `experiment` branc
No changes between current HEAD and refs/remotes/trunk
Resetting to the latest refs/remotes/trunk
-Running `dcommit` on a branch with merged history works fine, except that when you look at your Git project history, it hasn’t rewritten either of the commits you made on the `experiment` branch — instead, all those changes appear in the SVN version of the single merge commit.
+<!--Running `dcommit` on a branch with merged history works fine, except that when you look at your Git project history, it hasn’t rewritten either of the commits you made on the `experiment` branch — instead, all those changes appear in the SVN version of the single merge commit.-->
+
+Das Ausführen von `dcommit` in einem Zweig mit zusammengeführter Historie funktioniert wunderbar, mit der folgenden Ausnahme: wenn Du Deinen Git-Projekthistorie anschaust, wurden die Commits, die Du im `experiment`-Zweig gemacht hast, nicht neu geschrieben — stattdessen tauchen alle diese Änderungen in der SVN-Version des einzelnen Merge-Commits auf.
+
+<!--When someone else clones that work, all they see is the merge commit with all the work squashed into it; they don’t see the commit data about where it came from or when it was committed.-->
+
+Wenn nun jemand anderes Deine Arbeit klont, ist alles, was er oder sie sieht, der Merge-Commit mit all Deinen Änderungen insgesamt; die Daten zu den einzelnen Commits (den Urpsrung und die Zeit, wann die Commits stattfanden) sehen sie nicht.
-When someone else clones that work, all they see is the merge commit with all the work squashed into it; they don’t see the commit data about where it came from or when it was committed.
+### Subversion-Zweige ###
-### Subversion Branching ###
+<!--Branching in Subversion isn’t the same as branching in Git; if you can avoid using it much, that’s probably best. However, you can create and commit to branches in Subversion using git svn.-->
-Branching in Subversion isn’t the same as branching in Git; if you can avoid using it much, that’s probably best. However, you can create and commit to branches in Subversion using git svn.
+Das Arbeiten mit Zweigen in Subversion ist nicht das gleiche wie mit Zweigen in Git arbeiten; es ist wohl das beste, wenn Du es vermeiden kannst, viel damit zu arbeiten. Dennoch kannst Du mit `git svn` Zweige in Subversion anlegen und Commits darin durchführen.
-#### Creating a New SVN Branch ####
+#### Einen neuen SVN-Zweig anlegen ####
-To create a new branch in Subversion, you run `git svn branch [branchname]`:
+<!--To create a new branch in Subversion, you run `git svn branch [branchname]`:-->
+
+Um einen neuen Zweig in Subversion anzulegen, führst Du `git svn branch [branchname]` aus:
$ git svn branch opera
Copying file:///tmp/test-svn/trunk at r87 to file:///tmp/test-svn/branches/opera...
@@ -304,27 +336,43 @@ To create a new branch in Subversion, you run `git svn branch [branchname]`:
Successfully followed parent
r89 = 9b6fe0b90c5c9adf9165f700897518dbc54a7cbf (opera)
-This does the equivalent of the `svn copy trunk branches/opera` command in Subversion and operates on the Subversion server. It’s important to note that it doesn’t check you out into that branch; if you commit at this point, that commit will go to `trunk` on the server, not `opera`.
+<!--This does the equivalent of the `svn copy trunk branches/opera` command in Subversion and operates on the Subversion server. It’s important to note that it doesn’t check you out into that branch; if you commit at this point, that commit will go to `trunk` on the server, not `opera`.-->
+
+Dieser Befehl macht genau das gleiche wie das `svn copy trunk branches/opera`-Kommando in Subversion und arbeitet auf dem Subversion-Server. Wichtig hierbei ist, dass Du mit Deiner Arbeit nicht automatisch in diesen Zweig wechselst: wenn Du zu diesem Zeitpunkt einen Commit durchführst, wird dieser in `trunk` auf dem Server landen, nicht im `opera`-Zweig.
+
-### Switching Active Branches ###
+### Den aktiven Zweig wechseln ###
-Git figures out what branch your dcommits go to by looking for the tip of any of your Subversion branches in your history — you should have only one, and it should be the last one with a `git-svn-id` in your current branch history.
+<!--Git figures out what branch your dcommits go to by looking for the tip of any of your Subversion branches in your history — you should have only one, and it should be the last one with a `git-svn-id` in your current branch history.-->
-If you want to work on more than one branch simultaneously, you can set up local branches to `dcommit` to specific Subversion branches by starting them at the imported Subversion commit for that branch. If you want an `opera` branch that you can work on separately, you can run
+Git findet heraus, in welchem Zweig Deine `dcommits` abgelegt werden, indem es den tip jedes Subversion-Zweiges in Deiner Historie untersucht — Du solltest nur einen einzigen haben und es sollte der letzte mit einer `git-svn-id` in der aktuellen Historie des Zweiges sein.
+
+<!--If you want to work on more than one branch simultaneously, you can set up local branches to `dcommit` to specific Subversion branches by starting them at the imported Subversion commit for that branch. If you want an `opera` branch that you can work on separately, you can run-->
+
+Wenn Du gleichzeitig mit mehr als einem Zweig arbeiten willst, kannst Du lokale Zweige derart anlegen, dass ein `dcommit` für sie in bestimmte Subversion-Zweige durchgeführt wird. Dazu startest Du diese beim importierten Subversion-Commit für diesen Zweig. Wenn Du einen `opera`-Zweig haben willst, an dem Du separat arbeiten kannst, führst Du
$ git branch opera remotes/opera
-Now, if you want to merge your `opera` branch into `trunk` (your `master` branch), you can do so with a normal `git merge`. But you need to provide a descriptive commit message (via `-m`), or the merge will say "Merge branch opera" instead of something useful.
+<!--Now, if you want to merge your `opera` branch into `trunk` (your `master` branch), you can do so with a normal `git merge`. But you need to provide a descriptive commit message (via `-m`), or the merge will say "Merge branch opera" instead of something useful.-->
+
+aus. Wenn Du jetzt Deinen `opera`-Zweig in `trunk` (Deinen `master`-Zweig) zusammenführen willst , kannst Du das mit einem normalen `git merge` machen. Du solltest allerdings eine aussagekräftige Commit-Beschreibung angeben (mit `-m`) oder sie wird statt etwas Sinnvollem "Merge branch opera" lauten.
+
+<!--Remember that although you’re using `git merge` to do this operation, and the merge likely will be much easier than it would be in Subversion (because Git will automatically detect the appropriate merge base for you), this isn’t a normal Git merge commit. You have to push this data back to a Subversion server that can’t handle a commit that tracks more than one parent; so, after you push it up, it will look like a single commit that squashed in all the work of another branch under a single commit. After you merge one branch into another, you can’t easily go back and continue working on that branch, as you normally can in Git. The `dcommit` command that you run erases any information that says what branch was merged in, so subsequent merge-base calculations will be wrong — the dcommit makes your `git merge` result look like you ran `git merge --squash`. Unfortunately, there’s no good way to avoid this situation — Subversion can’t store this information, so you’ll always be crippled by its limitations while you’re using it as your server. To avoid issues, you should delete the local branch (in this case, `opera`) after you merge it into trunk.-->
-Remember that although you’re using `git merge` to do this operation, and the merge likely will be much easier than it would be in Subversion (because Git will automatically detect the appropriate merge base for you), this isn’t a normal Git merge commit. You have to push this data back to a Subversion server that can’t handle a commit that tracks more than one parent; so, after you push it up, it will look like a single commit that squashed in all the work of another branch under a single commit. After you merge one branch into another, you can’t easily go back and continue working on that branch, as you normally can in Git. The `dcommit` command that you run erases any information that says what branch was merged in, so subsequent merge-base calculations will be wrong — the dcommit makes your `git merge` result look like you ran `git merge --squash`. Unfortunately, there’s no good way to avoid this situation — Subversion can’t store this information, so you’ll always be crippled by its limitations while you’re using it as your server. To avoid issues, you should delete the local branch (in this case, `opera`) after you merge it into trunk.
+Behalte im Hinterkopf, dass dieses Vorgehen kein normaler Git-Merge-Commit ist, auch wenn Du den `git merge`-Befehl verwendes und das Zusammenführen wahrscheinlich wesentlich einfacher ist als es in Subversion gewesen wäre (weil Git automatisch die passende Basis für das Zusammenführen der Zweige für Dich herausfindet=. Du musst diese Daten zurück auf den Subversion-Server schieben, der nicht mit Commits umgehen kann, die mehr als ein Elternelement haben; all Deine Änderungen aus einem anderen Zweig werden in diesem einen Commit zusammengepresst, wenn Du die Änderungen hochschiebst. Nachdem Du einen Zweig mit einem anderen zusammengefügt hast, kannst Du nicht einfach zurückgehen und mit der Arbeit an diesem Zweig weitermachen, wie Du das normalerweise in Git machen würdest. Wenn Du das `dcommit`-Kommando ausführst, löscht es jegliche Information darüber, welcher Zweig hier hineingefügt wurde und als Folge dessen werden künftige merge-base-Berechnungen falsche sein — die `dcommit`-Operation lässt Dein `git merge`-Ergebnis so aussehen als ob Du `git merge --squash` verwendet hättest.
+Unglücklicherweise gibt es kein ideales Mittel, diese Situation zu vermeiden — Subversion kann diese Information einfach nicht speichern, daher wirst Du immer unter seinen beschränkten Möglichkeiten zu leiden haben, so lange Du es als Server verwendest. Um diese Probleme zu vermeiden, solltest Du den lokalen Zweig (in unserem Beispiel `opera`) löschen, nachdem Du ihn mit dem `trunk` zusammengeführt hast.
-### Subversion Commands ###
+### Subversion Befehle ###
-The `git svn` toolset provides a number of commands to help ease the transition to Git by providing some functionality that’s similar to what you had in Subversion. Here are a few commands that give you what Subversion used to.
+<!--The `git svn` toolset provides a number of commands to help ease the transition to Git by providing some functionality that’s similar to what you had in Subversion. Here are a few commands that give you what Subversion used to.-->
-#### SVN Style History ####
+Das `git svn`-Werkzeug bietet eine ganze Reihe von Befehlen an, die Dir helfen, den Übergang zu Git zu vereinfachen, indem sie einige Funktionen bereitstellen, die jeden ähneln, die Du bereits in Subversion kanntest. Hier sind ein paar Befehle, die Dir solche Funktionen bereitstellen wie das Subversion früher für Dich tat:
-If you’re used to Subversion and want to see your history in SVN output style, you can run `git svn log` to view your commit history in SVN formatting:
+#### Historie im SVN-Stil ####
+
+<!--If you’re used to Subversion and want to see your history in SVN output style, you can run `git svn log` to view your commit history in SVN formatting:-->
+
+Wenn Du an Subversion gewöhnt bist und Deine Historie so sehen möchtest, wie SVN sie ausgeben würde, kannst Du `git svn log` ausführen, um Deine Commit-Historie in der SVN-Formatierung anzusehen:
$ git svn log
------------------------------------------------------------------------
@@ -342,11 +390,15 @@ If you’re used to Subversion and want to see your history in SVN output style,
updated the changelog
-You should know two important things about `git svn log`. First, it works offline, unlike the real `svn log` command, which asks the Subversion server for the data. Second, it only shows you commits that have been committed up to the Subversion server. Local Git commits that you haven’t dcommited don’t show up; neither do commits that people have made to the Subversion server in the meantime. It’s more like the last known state of the commits on the Subversion server.
+<!--You should know two important things about `git svn log`. First, it works offline, unlike the real `svn log` command, which asks the Subversion server for the data. Second, it only shows you commits that have been committed up to the Subversion server. Local Git commits that you haven’t dcommited don’t show up; neither do commits that people have made to the Subversion server in the meantime. It’s more like the last known state of the commits on the Subversion server.-->
+
+Du solltest zwei wichtige Dinge über `git svn log`wissen. Erstens: es arbeitet offline, im Gegensatz zum echten `svn log`-Befehl, der den Subversion-Server nach den Daten fragt. Zweitens: es zeigt Dir nur Commits an, die auf den Subversion-Server committet wurden. Lokale Git-Commits die Du nicht mit `dcommit` bestätigt hast, werden nicht aufgeführt, genausowenig wie Commits, die andere in der Zwischenzeit auf dem Subversion-Server gemacht haben. Die Ausgabe zeigt Dir eher den letzten bekannten Zustand der Commits auf dem Subversion-Server.
+
+#### SVN Vermerke (SVN Annotation) ####
-#### SVN Annotation ####
+<!--Much as the `git svn log` command simulates the `svn log` command offline, you can get the equivalent of `svn annotate` by running `git svn blame [FILE]`. The output looks like this:-->
-Much as the `git svn log` command simulates the `svn log` command offline, you can get the equivalent of `svn annotate` by running `git svn blame [FILE]`. The output looks like this:
+Genauso wie das Kommando `git svn log` den `svn log`-Befehl offline simuliert kannst Du das Pendant zu `svn annotate` mit dem Befehl `git svn blame [FILE]` ausführen. Die Ausgabe sieht so aus:
$ git svn blame README.txt
2 temporal Protocol Buffers - Google's data interchange format
@@ -362,11 +414,15 @@ Much as the `git svn log` command simulates the `svn log` command offline, you c
2 temporal Buffer compiler (protoc) execute the following:
2 temporal
-Again, it doesn’t show commits that you did locally in Git or that have been pushed to Subversion in the meantime.
+<!--Again, it doesn’t show commits that you did locally in Git or that have been pushed to Subversion in the meantime.-->
-#### SVN Server Information ####
+Auch dieser Befehl zeigt die Commits nicht an, die Du lokal getätigt hast, genauso wenig wie jene, die in der Zwischenzeit zum Subversion-Server übertragen wurden.
-You can also get the same sort of information that `svn info` gives you by running `git svn info`:
+#### SVN-Server-Informationen ####
+
+<!--You can also get the same sort of information that `svn info` gives you by running `git svn info`:-->
+
+Die selben Informationen wie bei `svn info` bekommst Du, wenn Du `git svn info` ausführst:
$ git svn info
Path: .
@@ -380,56 +436,87 @@ You can also get the same sort of information that `svn info` gives you by runni
Last Changed Rev: 87
Last Changed Date: 2009-05-02 16:07:37 -0700 (Sat, 02 May 2009)
-This is like `blame` and `log` in that it runs offline and is up to date only as of the last time you communicated with the Subversion server.
+<!--This is like `blame` and `log` in that it runs offline and is up to date only as of the last time you communicated with the Subversion server.-->
+
+Genauso wie `blame` und `log` läuft die Ausführung dieses Befehls offline ab und ist nur so aktuell wie zu dem Zeitpunkt, zu dem Du das letzte Mal mit dem Subversion-Server verbunden warst.
+
+#### Ignorieren, was Subversion ignoriert ####
-#### Ignoring What Subversion Ignores ####
+<!--If you clone a Subversion repository that has `svn:ignore` properties set anywhere, you’ll likely want to set corresponding `.gitignore` files so you don’t accidentally commit files that you shouldn’t. `git svn` has two commands to help with this issue. The first is `git svn create-ignore`, which automatically creates corresponding `.gitignore` files for you so your next commit can include them.-->
-If you clone a Subversion repository that has `svn:ignore` properties set anywhere, you’ll likely want to set corresponding `.gitignore` files so you don’t accidentally commit files that you shouldn’t. `git svn` has two commands to help with this issue. The first is `git svn create-ignore`, which automatically creates corresponding `.gitignore` files for you so your next commit can include them.
+Wenn Du ein Subversion-Repository klonst, das irgendwo `svn:ignore` Eigenschaften definiert hat, wirst Du die `.gitignore`-Dateien wahrscheinlich entsprechend setzen, damit Du nicht aus Versehen Dateien committest, bei denen Du das besser nicht tun solltest. `git svn` kennt zwei Befehle, um Dir bei diesem Problem zu helfen. Der erste ist `git svn create-ignore`, der automatisch entsprechende `.gitignore`-Dateien für Dich anlegt, so dass Dein nächster Commit diese beinhalten kann.
-The second command is `git svn show-ignore`, which prints to stdout the lines you need to put in a `.gitignore` file so you can redirect the output into your project exclude file:
+<!--The second command is `git svn show-ignore`, which prints to stdout the lines you need to put in a `.gitignore` file so you can redirect the output into your project exclude file:-->
+
+Der zweite Befehl ist `git svn show-ignore`, der Dir diejenigen Zeilen auf stdout ausgibt, die Du in eine `.gitignore`-Datei einfügen musst. So kannst Du die Ausgabe des Befehls direkt in die Ausnahmedatei umleiten:
$ git svn show-ignore > .git/info/exclude
-That way, you don’t litter the project with `.gitignore` files. This is a good option if you’re the only Git user on a Subversion team, and your teammates don’t want `.gitignore` files in the project.
+<!--That way, you don’t litter the project with `.gitignore` files. This is a good option if you’re the only Git user on a Subversion team, and your teammates don’t want `.gitignore` files in the project.-->
+
+Auf diese Weise müllst Du Dein Projekt nicht mit `.gitignore`-Dateien zu. Das ist eine gute Wahl wenn Du der einzige Git-Benutzer in Deinem Team bist (alle anderen benutzen Subversion) und Deine Kollegen keine `.gitignore`-Dateien im Projekt haben wollen.
+
+### Zusammenfassung von Git-Svn ###
-### Git-Svn Summary ###
+<!--The `git svn` tools are useful if you’re stuck with a Subversion server for now or are otherwise in a development environment that necessitates running a Subversion server. You should consider it crippled Git, however, or you’ll hit issues in translation that may confuse you and your collaborators. To stay out of trouble, try to follow these guidelines:-->
-The `git svn` tools are useful if you’re stuck with a Subversion server for now or are otherwise in a development environment that necessitates running a Subversion server. You should consider it crippled Git, however, or you’ll hit issues in translation that may confuse you and your collaborators. To stay out of trouble, try to follow these guidelines:
+Die `git svn`-Werkzeuge sind sehr nützlich, wenn Du derzeit (noch) an einen Subversion-Server gebunden bist oder Dich anderweitig in einer Entwicklungsumgebung befindest, die nicht auf einen Subversion-Server verzichten kann. Wie auch immer: Du solltest es als eine Art gestutztes Git ansehen. Anderenfalls läufst Du Gefahr, Dich und Deine Kollegen durcheinander zu bringen. Um dieses Kliff zu umschiffen, solltest Du folgende Richtlinien befolgen:
-* Keep a linear Git history that doesn’t contain merge commits made by `git merge`. Rebase any work you do outside of your mainline branch back onto it; don’t merge it in.
-* Don’t set up and collaborate on a separate Git server. Possibly have one to speed up clones for new developers, but don’t push anything to it that doesn’t have a `git-svn-id` entry. You may even want to add a `pre-receive` hook that checks each commit message for a `git-svn-id` and rejects pushes that contain commits without it.
+<!--* Keep a linear Git history that doesn’t contain merge commits made by `git merge`. Rebase any work you do outside of your mainline branch back onto it; don’t merge it in.
+* Don’t set up and collaborate on a separate Git server. Possibly have one to speed up clones for new developers, but don’t push anything to it that doesn’t have a `git-svn-id` entry. You may even want to add a `pre-receive` hook that checks each commit message for a `git-svn-id` and rejects pushes that contain commits without it.-->
-If you follow those guidelines, working with a Subversion server can be more bearable. However, if it’s possible to move to a real Git server, doing so can gain your team a lot more.
+* Versuch, eine "geradlinige" Git-Historie zu führen, die keine von `git merge` durchgeführten Merges enthält. Alle Arbeiten, die Du außerhalb des Hauptzweiges durchführst, solltest Du mit `rebase` in ihn aufnehmen anstatt sie zu mit `merge` zusammenzuführen.
+* Setz keinen zusätzlichen, externen Git-Server auf, mit dem Du arbeiten möchtest. Du kannst einen aufsetzen um die Klone für neue Entwickler zu beschleunigen, aber Du solltest keine Änderungen dorthin pushen, die keine `git-svn-id`-Einträge haben. Du solltest vielleicht sogar darüber nachdenken, einen `pre-receive`-Hook einzusetzen, der jede Commit-Nachricht auf eine `git-svn-id` prüft und bestimmte Pushes ablehnt, bei denen diese IDs fehlt.
-## Migrating to Git ##
+<!--If you follow those guidelines, working with a Subversion server can be more bearable. However, if it’s possible to move to a real Git server, doing so can gain your team a lot more.-->
-If you have an existing codebase in another VCS but you’ve decided to start using Git, you must migrate your project one way or another. This section goes over some importers that are included with Git for common systems and then demonstrates how to develop your own custom importer.
+Wenn Du diese Ratschläge befolgst, werden sie die Arbeit mit dem Subversion-Server erträglich machen. Wenn es Dir irgendwie möglich ist, solltest Du trotzdem zu einem echten Git-Server umziehen, denn davon profitiert Dein Team wesentlich deutlicher.
-### Importing ###
+## Zu Git umziehen ##
-You’ll learn how to import data from two of the bigger professionally used SCM systems — Subversion and Perforce — both because they make up the majority of users I hear of who are currently switching, and because high-quality tools for both systems are distributed with Git.
+<!--If you have an existing codebase in another VCS but you’ve decided to start using Git, you must migrate your project one way or another. This section goes over some importers that are included with Git for common systems and then demonstrates how to develop your own custom importer.-->
+
+Wenn Du bereits Quellcode in einer anderen Versionsverwaltung abgelegt hast, aber Dich nun entschieden hast, von nun an Git zu benutzen, musst Du Dein Projekt so oder so umziehen. Für geläufige Systeme bringt Git einige Importer mit. Anschließend lernen wir, wie Du Deinen eigenen, angepassten Importer entwickeln kann. All das wird im folgenden Abschnitt behandelt.
+
+### Import ###
+
+<!--You’ll learn how to import data from two of the bigger professionally used SCM systems — Subversion and Perforce — both because they make up the majority of users I hear of who are currently switching, and because high-quality tools for both systems are distributed with Git.-->
+
+Jetzt ist es an der Zeit zu lernen, wie Du Daten aus zwei der am meisten benutzten (professionellen) SCM-Systeme importieren kannst: Subversion und Perforce. Ein Großteil der Benutzer, die gegenwärtig zu Git umziehen, arbeiten mit einem von diesen beiden Systemen. Außerdem liefert Git für beide jeweils hochprofessionelle Werkzeuge für den Import mit.
### Subversion ###
-If you read the previous section about using `git svn`, you can easily use those instructions to `git svn clone` a repository; then, stop using the Subversion server, push to a new Git server, and start using that. If you want the history, you can accomplish that as quickly as you can pull the data out of the Subversion server (which may take a while).
+<!--If you read the previous section about using `git svn`, you can easily use those instructions to `git svn clone` a repository; then, stop using the Subversion server, push to a new Git server, and start using that. If you want the history, you can accomplish that as quickly as you can pull the data out of the Subversion server (which may take a while).-->
-However, the import isn’t perfect; and because it will take so long, you may as well do it right. The first problem is the author information. In Subversion, each person committing has a user on the system who is recorded in the commit information. The examples in the previous section show `schacon` in some places, such as the `blame` output and the `git svn log`. If you want to map this to better Git author data, you need a mapping from the Subversion users to the Git authors. Create a file called `users.txt` that has this mapping in a format like this:
+Wenn Du die letzten Abschnitte über `git svn` gelesen hast, kannst Du diese Anleitungen ganz einfach benutzen um mit `git svn clone` ein Repository zu klonen. Anschließend stoppst den Subversion-Server, führst einen Push auf den neuen Git-Server durch und beginnst ihn zu benutzen. Wenn Du an die Historie ran willst, kannst Du das genausoschnell erreichen als ob Du die Daten aus dem Subversion-Server beziehen würdest (was eine Weile dauern könnte).
+
+<!--However, the import isn’t perfect; and because it will take so long, you may as well do it right. The first problem is the author information. In Subversion, each person committing has a user on the system who is recorded in the commit information. The examples in the previous section show `schacon` in some places, such as the `blame` output and the `git svn log`. If you want to map this to better Git author data, you need a mapping from the Subversion users to the Git authors. Create a file called `users.txt` that has this mapping in a format like this:-->
+
+Trotzdem ist der Import nicht perfekt. Und weil das ziemlich lange dauern wird, kannst Du es auch gleich richtig machen. Das erste Problem sind die Informationen über die Autoren. In Subversion besitzt jede Person, die mit dem System arbeitet, einen eigenen User-Account, der in den Commit-Informationen aufgezeichnet wird. Die Beispiele in den vorherigen Abschnitten zeigten dafür manchmal `schacon` an, wie beispielsweise bei der Ausgabe von `blame` und bei `git svn log`. Wenn Du dies näher an die Autoren-Daten von Git binden willst, musst Du Mapping-Informationen für die Subversion-Benutzer und die Git-Autoren anlegen. Erstelle eine Datei mit dem Namen `users.txt`, die folgendes Mapping-Format verwendet:
schacon = Scott Chacon <schacon@geemail.com>
selse = Someo Nelse <selse@geemail.com>
-To get a list of the author names that SVN uses, you can run this:
+<!--To get a list of the author names that SVN uses, you can run this:-->
+
+Um eine Liste der Namen der Autoren bekommen, die SVN benutzen, kannst Du folgendes Kommando ausführen:
$ svn log --xml | grep author | sort -u | perl -pe 's/.>(.?)<./$1 = /'
-That gives you the log output in XML format — you can look for the authors, create a unique list, and then strip out the XML. (Obviously this only works on a machine with `grep`, `sort`, and `perl` installed.) Then, redirect that output into your users.txt file so you can add the equivalent Git user data next to each entry.
+<!--That gives you the log output in XML format — you can look for the authors, create a unique list, and then strip out the XML. (Obviously this only works on a machine with `grep`, `sort`, and `perl` installed.) Then, redirect that output into your users.txt file so you can add the equivalent Git user data next to each entry.-->
+
+Dies erzeugt Dir die Log-Ausgabe im XML-Format — Du suchst damit nach den Autoren, erzeugst eine Liste ohne doppelte Einträge und wirfst anschließend das überflüssige XML weg. Anschließend wird die Ausgabe in die Datei `users.txt` umgeleitet, so dass Du jedem Eintrag den entsprechenden Git-Benutzer zuordnen kannst.
-You can provide this file to `git svn` to help it map the author data more accurately. You can also tell `git svn` not to include the metadata that Subversion normally imports, by passing `--no-metadata` to the `clone` or `init` command. This makes your `import` command look like this:
+<!--You can provide this file to `git svn` to help it map the author data more accurately. You can also tell `git svn` not to include the metadata that Subversion normally imports, by passing `--no-metadata` to the `clone` or `init` command. This makes your `import` command look like this:-->
+
+Du kannst diese Datei dann `git svn` zur Verfügung stellen um das Tool dabei zu unterstützen, die Autoreninformationen besser zu mappen. Du kannst `git svn` ebenfalls mitteilen, dass es die Metadaten nicht einbeziehen soll, die Subversion normalerweise importiert, indem Du dem `clone` oder `init` Kommando die `--no-metadata`-Option mitgibst.
$ git-svn clone http://my-project.googlecode.com/svn/ \
--authors-file=users.txt --no-metadata -s my_project
-Now you should have a nicer Subversion import in your `my_project` directory. Instead of commits that look like this
+<!--Now you should have a nicer Subversion import in your `my_project` directory. Instead of commits that look like this-->
+
+Jetzt solltest Du einen hübscheren Subversion-Import in Deinem `my_project`-Verzeichnis haben. Statt eines Commit, die so aussehen:
commit 37efa680e8473b615de980fa935944215428a35a
Author: schacon <schacon@4c93b258-373f-11de-be05-5f7a86268029>
@@ -439,56 +526,79 @@ Now you should have a nicer Subversion import in your `my_project` directory. In
git-svn-id: https://my-project.googlecode.com/svn/trunk@94 4c93b258-373f-11de-
be05-5f7a86268029
-they look like this:
-
+
+sehen sie jetzt so aus:
+
commit 03a8785f44c8ea5cdb0e8834b7c8e6c469be2ff2
Author: Scott Chacon <schacon@geemail.com>
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
-Not only does the Author field look a lot better, but the `git-svn-id` is no longer there, either.
+<!--Not only does the Author field look a lot better, but the `git-svn-id` is no longer there, either.-->
+
+Nicht nur das Autoren-Feld sieht jetzt wesentlich besser aus. Auch die `git-svn-id wird jetzt nicht mehr gebraucht.
-You need to do a bit of `post-import` cleanup. For one thing, you should clean up the weird references that `git svn` set up. First you’ll move the tags so they’re actual tags rather than strange remote branches, and then you’ll move the rest of the branches so they’re local.
+<!--You need to do a bit of `post-import` cleanup. For one thing, you should clean up the weird references that `git svn` set up. First you’ll move the tags so they’re actual tags rather than strange remote branches, and then you’ll move the rest of the branches so they’re local.-->
-To move the tags to be proper Git tags, run
+Nach dem Import musst Du noch ein wenig aufräumen. Dafür solltest Du all die merkwürdigen Referenzen säubern, die `git svn` angelegt hat. Zuerst verschiebst Du die Tags, damit sie tatsächliche Git-Tags sind statt merkwürdigen Remote-Zweigen. Anschließend verschieben wir den Rest der Zweige, so dass sie lokale Zweige werden.
+
+<!--To move the tags to be proper Git tags, run-->
+
+Um die Tags so zu verschieben, dass sie echte Git-Tags werden, führst Du folgenden Befehl aus:
$ cp -Rf .git/refs/remotes/tags/* .git/refs/tags/
$ rm -Rf .git/refs/remotes/tags
-This takes the references that were remote branches that started with `tag/` and makes them real (lightweight) tags.
+<!--This takes the references that were remote branches that started with `tag/` and makes them real (lightweight) tags.-->
+
+Das nimmt die Referenzen, die vorher Remote-Zweige waren, die mit `tag/` begonnen haben und macht aus ihnen echte (leichtgewichtige) Tags.
-Next, move the rest of the references under `refs/remotes` to be local branches:
+<!--Next, move the rest of the references under `refs/remotes` to be local branches:-->
+
+Als nächstes verschieben wir den Rest der Referenzen aus `refs/remotes` und machen lokale Zweige daraus:
$ cp -Rf .git/refs/remotes/* .git/refs/heads/
$ rm -Rf .git/refs/remotes
-Now all the old branches are real Git branches and all the old tags are real Git tags. The last thing to do is add your new Git server as a remote and push to it. Because you want all your branches and tags to go up, you can run this:
+<!--Now all the old branches are real Git branches and all the old tags are real Git tags. The last thing to do is add your new Git server as a remote and push to it. Because you want all your branches and tags to go up, you can run this:-->
+
+Jetzt sind alle alten Zweige richtige Git-Zweige geworden und alle alten Tags sind echte Git-Tags. Als letztes müssen wir den neuen Git-Server noch als entfernten Server einrichten und unsere Änderungen zu ihm pushen. Da wir alle Zweige und Tags einbeziehen wollen, kannst Du diesen Befehl verwenden:
$ git push origin --all
-All your branches and tags should be on your new Git server in a nice, clean import.
+<!--All your branches and tags should be on your new Git server in a nice, clean import.-->
+
+All Deine Zweige und Tags sollten jetzt in Deinem neuen Git-Server in einem schicken, sauberen Import vorhanden sein.
### Perforce ###
-The next system you’ll look at importing from is Perforce. A Perforce importer is also distributed with Git, but only in the `contrib` section of the source code — it isn’t available by default like `git svn`. To run it, you must get the Git source code, which you can download from git.kernel.org:
+<!--The next system you’ll look at importing from is Perforce. A Perforce importer is also distributed with Git, but only in the `contrib` section of the source code — it isn’t available by default like `git svn`. To run it, you must get the Git source code, which you can download from git.kernel.org:-->
+
+Das nächste System, dass wir zum Importieren anschauen werden, ist Perforce. Ein Import-Werkzeug für Perforce wird ebenfalls mit Git mitgeliefert, allerdings nur im `contrib`-Bereich des Quellcodes — es ist nicht wie `git svn` standardmäßig verfügbar. Um es auszuführen, musst Du den Git-Quellcode von `git.kernel.org` herunterladen:
$ git clone git://git.kernel.org/pub/scm/git/git.git
$ cd git/contrib/fast-import
-In this `fast-import` directory, you should find an executable Python script named `git-p4`. You must have Python and the `p4` tool installed on your machine for this import to work. For example, you’ll import the Jam project from the Perforce Public Depot. To set up your client, you must export the P4PORT environment variable to point to the Perforce depot:
+<!--In this `fast-import` directory, you should find an executable Python script named `git-p4`. You must have Python and the `p4` tool installed on your machine for this import to work. For example, you’ll import the Jam project from the Perforce Public Depot. To set up your client, you must export the P4PORT environment variable to point to the Perforce depot:-->
+
+In diesem `fast-import` Verzeichnis wirst Du ein ausführbares Python-Skript mit dem Namen `git-p4` finden. Du musst Python sowie das `p4`-Werkzeug auf Deiner Maschine installiert haben, damit der Import klappt. Als Beispiel werden wir das Jam-Projekt aus dem Perforce Public Depot verwenden. Um den Client einzurichten, musst Du die P4PORT-Umgebungsvariable exportieren und sie auf das Perforce-Depot einstellen:
$ export P4PORT=public.perforce.com:1666
-Run the `git-p4 clone` command to import the Jam project from the Perforce server, supplying the depot and project path and the path into which you want to import the project:
+<!--Run the `git-p4 clone` command to import the Jam project from the Perforce server, supplying the depot and project path and the path into which you want to import the project:-->
+
+Führe den `git-p4 clone`-Befehl aus, um das Jam-Projekt aus dem Perforce-Server zu importieren. Dazu gibst Du den Depot- und Projekt-Pfad sowie den Pfad an, in den Du das Projekt importieren willst:
$ git-p4 clone //public/jam/src@all /opt/p4import
Importing from //public/jam/src@all into /opt/p4import
Reinitialized existing Git repository in /opt/p4import/.git/
Import destination: refs/remotes/p4/master
Importing revision 4409 (100%)
-If you go to the `/opt/p4import` directory and run `git log`, you can see your imported work:
+<!--If you go to the `/opt/p4import` directory and run `git log`, you can see your imported work:-->
+
+Wenn Du zum `/opt/p4import`-Verzeichnis wechselst und dann `git log` ausführst, kannst Du sehen, dass Dein Import funktioniert hat:
$ git log -2
commit 1fd4ec126171790efd2db83548b85b1bbbc07dc2
@@ -510,15 +620,19 @@ If you go to the `/opt/p4import` directory and run `git log`, you can see your i
[git-p4: depot-paths = "//public/jam/src/": change = 3108]
-You can see the `git-p4` identifier in each commit. It’s fine to keep that identifier there, in case you need to reference the Perforce change number later. However, if you’d like to remove the identifier, now is the time to do so — before you start doing work on the new repository. You can use `git filter-branch` to remove the identifier strings en masse:
+<!--You can see the `git-p4` identifier in each commit. It’s fine to keep that identifier there, in case you need to reference the Perforce change number later. However, if you’d like to remove the identifier, now is the time to do so — before you start doing work on the new repository. You can use `git filter-branch` to remove the identifier strings en masse:-->
+
+Du kannst die `git-p4`-ID bei jedem Commit sehen. Es ist OK, diese ID hier zu behalten, falls Du später noch mal einen Bezug zu der Perforce-Änderung herstellen musst. Falls Du die ID entfernen willst, ist jetzt Zeit dazu — bevor Du mit der Arbeit an dem neuen Repository beginnst. Du kannst `git filter-branch` benutzen um all die IDs zu entfernen:
$ git filter-branch --msg-filter '
sed -e "/^\[git-p4:/d"
'
Rewrite 1fd4ec126171790efd2db83548b85b1bbbc07dc2 (123/123)
Ref 'refs/heads/master' was rewritten
-If you run `git log`, you can see that all the SHA-1 checksums for the commits have changed, but the `git-p4` strings are no longer in the commit messages:
+<!--If you run `git log`, you can see that all the SHA-1 checksums for the commits have changed, but the `git-p4` strings are no longer in the commit messages:-->
+
+Wenn Du `git log` ausführst, kannst Du alle SHA1-Prüfsummen für jene Commits sehen, die sich geändert haben, aber die `git-p4`-Zeichenketten sind nicht mehr in den Commit-Nachrichten vorhanden.
$ git log -2
commit 10a16d60cffca14d454a15c6164378f4082bc5b0
@@ -535,14 +649,20 @@ If you run `git log`, you can see that all the SHA-1 checksums for the commits h
Date: Tue Apr 22 20:51:34 2003 -0800
Update derived jamgram.c
+
+<!--Your import is ready to push up to your new Git server.-->
+
+Dein Import ist jetzt so weit, dass Du ihn auf den neuen Git-Server pushen kannst.
+
+### Ein Import-Tool im Eigenbau ###
-Your import is ready to push up to your new Git server.
+<!--If your system isn’t Subversion or Perforce, you should look for an importer online — quality importers are available for CVS, Clear Case, Visual Source Safe, even a directory of archives. If none of these tools works for you, you have a rarer tool, or you otherwise need a more custom importing process, you should use `git fast-import`. This command reads simple instructions from stdin to write specific Git data. It’s much easier to create Git objects this way than to run the raw Git commands or try to write the raw objects (see Chapter 9 for more information). This way, you can write an import script that reads the necessary information out of the system you’re importing from and prints straightforward instructions to stdout. You can then run this program and pipe its output through `git fast-import`.-->
-### A Custom Importer ###
+Wenn die Versionsverwaltung, die Du verwendest, nicht Subversion oder Perforce ist, solltest Du zunächst einmal online nach einem Import-Tool suchen — gute Import-Tools sind für CVS, Clear Case, Visual Source Sage und sogar für ein Verzeichnis mit Archiven verfügbar. Wenn für Deinen Anwendungsfall keines dieser Werkzeuge passt, Du eine fast schon ausgestorbene Versionsverwaltung verwendest oder Du aus irgendeinem anderen Grund ein angepassteres Vorgehen brauchst, dann solltest Du `git fast-import` verwenden. Dieser Befehl nimmt einfache Anweisungen von `stdin` entgegen um entsprechende Git-Daten zu schreiben. Es ist viel einfacher Git-Objekte auf diese Art zu erzeugen als die blanken Git-Kommandos zu verwenden oder zu versuchen, die Roh-Objekte zu schreiben (weitere Informationen findest Du in Kapitel 9).
-If your system isn’t Subversion or Perforce, you should look for an importer online — quality importers are available for CVS, Clear Case, Visual Source Safe, even a directory of archives. If none of these tools works for you, you have a rarer tool, or you otherwise need a more custom importing process, you should use `git fast-import`. This command reads simple instructions from stdin to write specific Git data. It’s much easier to create Git objects this way than to run the raw Git commands or try to write the raw objects (see Chapter 9 for more information). This way, you can write an import script that reads the necessary information out of the system you’re importing from and prints straightforward instructions to stdout. You can then run this program and pipe its output through `git fast-import`.
+<!--To quickly demonstrate, you’ll write a simple importer. Suppose you work in current, you back up your project by occasionally copying the directory into a time-stamped `back_YYYY_MM_DD` backup directory, and you want to import this into Git. Your directory structure looks like this:-->
-To quickly demonstrate, you’ll write a simple importer. Suppose you work in current, you back up your project by occasionally copying the directory into a time-stamped `back_YYYY_MM_DD` backup directory, and you want to import this into Git. Your directory structure looks like this:
+Um das kurz zu zeigen, schreiben wir einen einfachen Importer. Nehmen wir an, Du arbeitest im Verzeichnis `current` und führst ab und an ein Backup durch, indem Du dieses Verzeichnis in ein Backup-Verzeichnis kopierst und ihm einen anderen Namen mit einem Zeitstempel, z. B. `back_YYYY_MM_DD`, verpasst. Diese Struktur wollen wir jetzt in Git importieren. Dein Verzeichnis sieht also so aus:
$ ls /opt/import_from
back_2009_01_02
@@ -551,11 +671,17 @@ To quickly demonstrate, you’ll write a simple importer. Suppose you work in cu
back_2009_02_03
current
-In order to import a Git directory, you need to review how Git stores its data. As you may remember, Git is fundamentally a linked list of commit objects that point to a snapshot of content. All you have to do is tell `fast-import` what the content snapshots are, what commit data points to them, and the order they go in. Your strategy will be to go through the snapshots one at a time and create commits with the contents of each directory, linking each commit back to the previous one.
+<!--In order to import a Git directory, you need to review how Git stores its data. As you may remember, Git is fundamentally a linked list of commit objects that point to a snapshot of content. All you have to do is tell `fast-import` what the content snapshots are, what commit data points to them, and the order they go in. Your strategy will be to go through the snapshots one at a time and create commits with the contents of each directory, linking each commit back to the previous one.-->
+
+Damit wir ein Git-Verzeichnis importieren können, müssen wir uns zunächst noch einmal anschauen, wie Git seine Daten speichert. Wie Du Dich vielleicht erinnerst, ist Git im Grundsatz eine verlinkte Liste von Commit-Objekten die auf eine Momentaufnahme (Snapshots) des Inhalts zeigt. Jetzt musst Du nur noch `fast-import` mitteilen, was dieses Snapshots sind, welche Commit-Daten zu ihnen zeigen und die Reihenfolge, in die sie gehören. Deine Strategie wir es sein, einen nach dem anderen durch die Snapshots zu gehen und Commits mit dem Inhalt eines jeden Verzeichnisses zu erzeigen und jeden dieser Commits anschließend mit dem vorherigen zu verknüpfen.
+
+<!--As you did in the "An Example Git Enforced Policy" section of Chapter 7, we’ll write this in Ruby, because it’s what I generally work with and it tends to be easy to read. You can write this example pretty easily in anything you’re familiar with — it just needs to print the appropriate information to stdout.-->
+
+Wie wir das schon im Abschnitt "(...)" in Kapitel 7 getan haben, programmieren wir diese Lösung in Ruby, weil es die Sprache ist, mit der ich normalerweise arbeite und weil es recht einfach zu lesen ist. Du kannst das Beispiel in so ziemlich jeder Sprache schreiben, mit der Du vertraut bist — es muss nur die passenden Informationen nach `stdout` schreiben.
-As you did in the "An Example Git Enforced Policy" section of Chapter 7, we’ll write this in Ruby, because it’s what I generally work with and it tends to be easy to read. You can write this example pretty easily in anything you’re familiar with — it just needs to print the appropriate information to stdout.
+<!--To begin, you’ll change into the target directory and identify every subdirectory, each of which is a snapshot that you want to import as a commit. You’ll change into each subdirectory and print the commands necessary to export it. Your basic main loop looks like this:-->
-To begin, you’ll change into the target directory and identify every subdirectory, each of which is a snapshot that you want to import as a commit. You’ll change into each subdirectory and print the commands necessary to export it. Your basic main loop looks like this:
+Zu Beginn musst Du in das Zielverzeichnis wechseln und jedes Unterverzeichnis identifizieren, das ein Snapshot ist, den Du als Commit importieren willst. Du wirst in jedes dieser Unterverzeichnisse wechseln und den entsprechenden Befehl auszugeben um es zu exportieren. Deine Schleife wird etwa so aussehen:
last_mark = nil
View
25 de/NOTES
@@ -1,3 +1,7 @@
+[mhh] = Markus Holtmanns, mholtmanns
+
+[mhh - 2010-01-14] Generelle Frage: Soll der Text in der "Du" Form sein/bleiben, oder soll es einen etwas seriöseren Charakter bekommen, als "Sie" oder "Wir"/neutrale Form ("Wie wir gesehen haben ..." und "Der Benutzer kann dann ...")?
+
"unter Versionskontrolle" » "versioniert"
"für einen Commit markiert" » "für einen Commit vorgemerkt" / "vorgesehen"
@@ -40,32 +44,39 @@ commit, to commit - Commit, committen
committer - Comitter
merge - Merge
history - Historie
-to push - (auf den Server) hochladen, pushen?
-to pull - Änderungen (vom Server) herunterladen/ziehen, pullen?
-checksum, to checksum - Checksumme, Checksumme berechnen
+to push - (auf den Server) hochladen, pushen? - besser Deutsch benutzen [mhh]
+to pull - Änderungen (vom Server) herunterladen/ziehen, pullen? - besser Deutsch [mhh]
+checksum, to checksum - Checksumme, Checksumme berechnen - Pruefsumme [mhh]
hash - Hash
SHA-1 hash - SHA-1 Hash
to stage - stagen, für einen Commit vormerken, zur Staging Area hinzufügen
to unstage - aus der Staging Area entfernen/nehmen
to clone - klonen
checkout, to check in/out - Checkout, ein/auschecken (??)
+ [mhh] es gibt kein checkin; und auschecken ist irrefuehrend, da es ja ein
+ "Entfernen" aus irgendetwas ist (z.B. Hotel). Ich wuerde hier eher die
+ wirkliche Bedeutung der Aktion benutzen, nämlich ein "synchronisieren".
+ Evtl. muss das dann mehr umschrieben werden.
snapshot - Snapshot
Schnappschuß klingt blöd
Speicherauszug sagt Leo http://dict.leo.org/ende?search=Snapshot
+ Abbild des aktuellen Zustands ... klingt zu lang? [mhh]
online/offline - online/offline
-hooks ("you may lose some server-side hooks") - ???
+hooks ("you may lose some server-side hooks") - "... könntest Du den Zugriff auf einige Server Schnittstellen verlieren"
to track a file - Änderungen an einer Datei nachverfolgen, eine Datei versionieren
a tracked file - eine versionierte Datei, eine Datei unter Versionskontrolle, eine Datei deren Änderungen nachverfolgt werden
a tracking branch - Tracking Branch, ein Branch, der einem externen Branch folgt ???
tracking branch information - Tracking Branch Information
-lightweight Tag - leichter Tag (???), schlanker Tag (???)
+
+Tag - Markierung oder Marke
+lightweight Tag - leichter Tag (???), schlanker Tag (???), schwache Markierung, einfache Markierung
annotated Tag - kommentierter Tag (???), annotierter Tag (???)
-tagged - getagged (???)
+tagged - getagged (???), markiert
home directory - Home Verzeichnis (???)
killer feature - "Killer Feature" (???)
to fork - forken
workflow - Workflow
-whitespace errors - Whitespace Fehler
+whitespace errors - Whitespace Fehler - Fehler durch Leerzeichen; Fuellzeichen [mhh]
to maintain a projekt, projekt maintainer - ein Projekt betreiben, Betreiber des Projektes (???)
apply a patch - einen Patch anwenden (???)
contribute to a projekt - zu einem Projekt Änderungen beitragen
View
4 de/STATUS
@@ -7,7 +7,7 @@
| 4 | 1 | wip | Sebastian Ohm |
| 5 | 1 | x | Sven Fuchs |
| 6 | 1 | wip | Sven Fuchs |
-| 7 | 1 | wip | Tim Wattenberg |
+| 7 | 1 | wip | Markus Holtmanns |
| 8 | 1 | wip | Jean Pierre Wenzel |
| 9 | 1 | x | Sven Fuchs |
@@ -32,4 +32,4 @@ Iteration 4: Feinschliff, Übersetzung von Grafiken
Um die Status Tabelle neu zu formatieren eignet sich das Makro "Align Table
-Cells" aus dem Cucumber TextMate Bundle hervorragend :)
+Cells" aus dem Cucumber TextMate Bundle hervorragend :)
View
0 es-es/01-introduction/01-chapter1.markdown → es/01-introduction/01-chapter1.markdown
File renamed without changes.
View
54 es-es/02-git-basics/01-chapter2.markdown → es/02-git-basics/01-chapter2.markdown
@@ -72,7 +72,7 @@ Digamos que añades un nuevo archivo a tu proyecto, un sencillo archivo README.
Puedes ver que tu nuevo archivo README aparece bajo la cabecera “Archivos sin seguimiento” (“Untracked files”) de la salida del comando. Sin seguimiento significa básicamente que Git ve un archivo que no estaba en la instantánea anterior; Git no empezará a incluirlo en las confirmaciones de tus instantáneas hasta que se lo indiques explícitamente. Lo hace para que no incluyas accidentalmente archivos binarios generados u otros archivos que no tenías intención de incluir. Sí que quieres incluir el README, así que vamos a iniciar el seguimiento del archivo.
-### Siguiendo nuevos archivos ###
+### Seguimiento de nuevos archivos ###
Para empezar el seguimiento de un nuevo archivo se usa el comando `git add`. Iniciaremos el seguimiento del archivo README ejecutando esto:
@@ -851,7 +851,7 @@ Si por algún motivo quieres eliminar una referencia —has movido el servidor o
## Creando etiquetas ##
-Como muchos VCSs, Git tiene la habilidad de etiquetar puntos específicos en la historia como importantes. Generalmente la gente usa esta funcionalidad para marcar publicaciones (v1.0 y así). En esta seccion aprenderas como listar las etiquetas disponibles, como crear nuevas etiquetas y cuales son los diferentes tipos de etiquetas
+Como muchos VCSs, Git tiene la habilidad de etiquetar (tag) puntos específicos en la historia como importantes. Generalmente la gente usa esta funcionalidad para marcar puntos donde se ha lanzado alguna versión (v1.0, y así sucesivamente). En esta sección aprenderás cómo listar las etiquetas disponibles, crear nuevas etiquetas y qué tipos diferentes de etiquetas hay-
### Listando tus etiquetas ###
@@ -861,9 +861,9 @@ Listar las etiquetas disponibles en Git es sencillo, Simplemente escribe `git ta
v0.1
v1.3
-Este comando lista las etiquetas en orden alfabético; el orden en el que aparecen no tiene real importancia.
+Este comando lista las etiquetas en orden alfabético; el orden en el que aparecen no es realmente importante.
-También puedes buscar etiquetas que cumplan un patrón particular. El repositorio fuente de Git, por ejemplo, tiene mas de 240 etiquetas. Si solo estas interesado en mirar en la serie 1.4.2, puedes ejecutar esto:
+También puedes buscar etiquetas de acuerdo a un patrón en particular. El repositorio fuente de Git, por ejemplo, contiene mas de 240 etiquetas. Si solo estas interesado en la serie 1.4.2, puedes ejecutar esto:
$ git tag -l 'v1.4.2.*'
v1.4.2.1
@@ -873,19 +873,19 @@ También puedes buscar etiquetas que cumplan un patrón particular. El repositor
### Creando etiquetas ###
-Git usa dos tipos principales de etiquetas: ligeras y anotadas. Una etiqueta ligera es muy parecida a una rama que no cambia —es simplemente un puntero a una confirmación específica—. Las etiquetas anotadas sin embargo, son almacenadas como objetos completos en la base de datos de Git. Tienen suma de comprobación; contienen el nombre del etiquetador, correo electrónico y fecha; tienen mensaje de etiquetado; y pueden ser firmadas y verificadas con GNU Privacy Guard (GPG). Generalmente se recomienda crear etiquetas anotadas para que tengas toda esta información; pero si por alguna razón quieres una etiqueta temporal y no quieres almacenar el resto de información, también tienes las etiquetas ligeras disponibles.
+Git usa dos tipos principales de etiquetas: ligeras y anotadas. Una etiqueta ligera es muy parecida a una rama que no cambia —un puntero a una confirmación específica—. Sin embargo, las etiquetas anotadas son almacenadas como objetos completos en la base de datos de Git. Tienen suma de comprobación; contienen el nombre del etiquetador, correo electrónico y fecha; tienen mensaje de etiquetado; y pueden estar firmadas y verificadas con GNU Privacy Guard (GPG). Generalmente se recomienda crear etiquetas anotadas para disponer de toda esta información; pero si por alguna razón quieres una etiqueta temporal y no quieres almacenar el resto de información, también tiene disponibles las etiquetas ligeras.
### Etiquetas anotadas ###
-Crear una etiqueta anotada en Git es simple. La forma más facil es especificar `-a` cuando ejecutas el comando `tag`:
+Crear una etiqueta anotada en Git es simple. La forma más fácil es especificar `-a` al ejecutar el comando `tag`:
$ git tag -a v1.4 -m 'my version 1.4'
$ git tag
v0.1
v1.3
v1.4
-El parámetro `-m` especifica el mensaje de etiquetado, que es almacenado con la etiqueta. Si no especificas un mensaje para una etiqueta anotada, Git lanza tu editor para que puedas escribirlo en él.
+El parámetro `-m` especifica el mensaje, el cual se almacena con la etiqueta. Si no se especifica un mensaje para la etiqueta anotada, Git lanza tu editor para poder escribirlo.
Puedes ver los datos de la etiqueta junto con la confirmación que fue etiquetada usando el comando `git show`:
@@ -902,18 +902,38 @@ Puedes ver los datos de la etiqueta junto con la confirmación que fue etiquetad
Merge branch 'experiment'
+<<<<<<< HEAD:es-es/02-git-basics/01-chapter2.markdown
Esto muestra la información del autor de la etiqueta, la fecha en la que la confirmación fue etiquetada, y el mensaje de anotación antes de mostrar la información del a confirmación.
### Etiquetas firmadas ###
También puedes firmar tus etiquetas con GPG, asumiendo que tienes una clave privada. Todo lo que tienes que hacer es usar el parámetro `-s` en lugar de `-a`.
+=======
+Esto muestra la información del etiquetador, la fecha en el que el commit fue etiquetado y el mensaje de anotación antes de mostrar la información del commit.
+
+> That shows the tagger information, the date the commit was tagged, and the annotation message before showing the commit information.
+
+
+### Etiquetas firmadas ###
+> ### Signed Tags ###
+
+También puedes firmar tus etiquetas con GPG, siempre que tengas una clave privada. Lo único que debes hacer es usar `-s` en vez de `-a`:
+
+> You can also sign your tags with GPG, assuming you have a private key. All you have to do is use `-s` instead of `-a`:
+>>>>>>> progit/master:es/02-git-basics/01-chapter2.markdown
$ git tag -s v1.5 -m 'my signed 1.5 tag'
You need a passphrase to unlock the secret key for
user: "Scott Chacon <schacon@gee-mail.com>"
1024-bit DSA key, ID F721C45A, created 2009-02-09
+<<<<<<< HEAD:es-es/02-git-basics/01-chapter2.markdown
Si ejecutas `git show` en esta etiqueta, puedes ser tu firma GPG adjuntada:
+=======
+Si ejecutas `git show` en esa etiqueta, puedes ver la firma GPG adjunta a ella:
+
+> If you run `git show` on that tag, you can see your GPG signature attached to it:
+>>>>>>> progit/master:es/02-git-basics/01-chapter2.markdown
$ git show v1.5
tag v1.5
@@ -935,11 +955,25 @@ Si ejecutas `git show` en esta etiqueta, puedes ser tu firma GPG adjuntada:
Merge branch 'experiment'
+<<<<<<< HEAD:es-es/02-git-basics/01-chapter2.markdown
Un poco más tarde aprenderás como verificar etiquetas firmadas.
### Etiquetas ligeras ###
Otra forma de etiquetar confirmaciones es con una etiqueta ligera. Esto es básicamente la suma de comprobación de la confirmación almacenada en un archivo —ninguna otra información es guardada—. Para crear una etiqueta ligera no añadas las opciones `-a`, `-s` o `-m`:
+=======
+Un poco después aprenderás como verificar etiquetas firmadas.
+
+> A bit later, you’ll learn how to verify signed tags.
+
+### Etiquetas ligeras ###
+
+>### Lightweight Tags ###
+
+Otra forma de etiquetar commits es con etiquetas ligeras. Esto es básicamente el checksum del commit almacenado en un fichero - no se guarda ninguna otra información. Para crear una etiqueta ligera, no hay que añadir ninguna de las opciones `-a`, `-s`, or `-m`:
+
+> Another way to tag commits is with a lightweight tag. This is basically the commit checksum stored in a file — no other information is kept. To create a lightweight tag, don’t supply the `-a`, `-s`, or `-m` option:
+>>>>>>> progit/master:es/02-git-basics/01-chapter2.markdown
$ git tag v1.4-lw
$ git tag
@@ -949,7 +983,7 @@ Otra forma de etiquetar confirmaciones es con una etiqueta ligera. Esto es bási
v1.4-lw
v1.5
-Esta vez, si ejecutas el comando `git show` en la etiqueta no verás la información extra. El comando simplemente muestra la confirmación.
+Esta vez, si ejecutas el comando `git show` en la etiqueta, no verás ninguna información extra. El comando simplemente muestra la confirmación.
$ git show v1.4-lw
commit 15027957951b64cf874c3557a0f3547bd83b3ff6
@@ -961,7 +995,7 @@ Esta vez, si ejecutas el comando `git show` en la etiqueta no verás la informac
### Verificando etiquetas ###
-Para verificar una etiqueta firmada, debes usar `git tag -v [tag-name]`. Este comando utiliza GPG para verificar la firma. Necesitas la clave pública del firmante en tu llavero para que esto funcione correctamente.
+Para verificar una etiqueta firmada, debes usar `git tag -v [tag-name]`. Este comando utiliza GPG para verificar la firma. Necesitas la clave pública del autor de la firma en tu llavero para que funcione correctamente.
$ git tag -v v1.4.2.1
object 883653babd8ee7ea23e6a5c392bb739348b1eb61
@@ -977,7 +1011,7 @@ Para verificar una etiqueta firmada, debes usar `git tag -v [tag-name]`. Este co
gpg: aka "[jpeg image of size 1513]"
Primary key fingerprint: 3565 2A26 2040 E066 C9A7 4A7D C0C6 D9A4 F311 9B9A
-If you don’t have the signer’s public key, you get something like this instead:
+Si no tienes la clave pública del autor de la firma, se obtiene algo así:
gpg: Signature made Wed Sep 13 02:08:25 2006 PDT using DSA key ID F3119B9A
gpg: Can't check signature: public key not found
View
0 es-es/03-git-branching/01-chapter3.markdown → es/03-git-branching/01-chapter3.markdown
File renamed without changes.
View
0 es-es/04-git-server/01-chapter4.markdown → es/04-git-server/01-chapter4.markdown
File renamed without changes.
View
0 ...s/05-distributed-git/01-chapter5.markdown → es/05-distributed-git/01-chapter5.markdown
File renamed without changes.
View
0 es-es/06-git-tools/01-chapter6.markdown → es/06-git-tools/01-chapter6.markdown
File renamed without changes.
View
0 ...s/07-customizing-git/01-chapter7.markdown → es/07-customizing-git/01-chapter7.markdown
File renamed without changes.
View
0 ...8-git-and-other-scms/01-chapter8.markdown → ...8-git-and-other-scms/01-chapter8.markdown
File renamed without changes.
View
0 es-es/09-git-internals/01-chapter9.markdown → es/09-git-internals/01-chapter9.markdown
File renamed without changes.
View
0 es-es/NOTES → es/NOTES
File renamed without changes.
View
0 es-es/README → es/README
File renamed without changes.
View
BIN figures/18333fig0309-tn.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
20 fr/01-introduction/01-chapter1.markdown
@@ -1,6 +1,6 @@
# Démarrage rapide #
-Ce chapitre traite du démarrage rapide avec Git. Nous commencerons par expliquer les bases des gestions de version, puis nous parlerons de l'installation de Git sur votre système et finalement comment le paramétrer pour commencer à l'utiliser. A la fin de ce chapitre vous devriez en savoir assez pour comprendre pourquoi on parle beaucoup de Git, pourquoi vous devriez l'utiliser et vous devriez en avoir une installation prête à l'emploi.
+Ce chapitre traite du démarrage rapide avec Git. Nous commencerons par expliquer les bases des gestions de version, puis nous parlerons de l'installation de Git sur votre système et finalement comment le paramétrer pour commencer à l'utiliser. À la fin de ce chapitre vous devriez en savoir assez pour comprendre pourquoi on parle beaucoup de Git, pourquoi vous devriez l'utiliser et vous devriez en avoir une installation prête à l'emploi.
## À propos de la gestion de version ##
@@ -17,11 +17,11 @@ Pour traiter ce problème, les programmeurs ont développé il y a longtemps des
Insert 18333fig0101.png
Figure 1-1. Diagramme des systèmes de gestion de version locaux.
-Un des systèmes les plus populaires était rcs, qui est encore distribué avec de nombreux systèmes d'exploitation aujourd'hui. Même le système d'exploitation populaire Mac OS X inclut le programme rcs lorsqu'on installe les outils de développement logiciel. Cet outil fonctionne en conservant les patch sets (c'est-à-dire la différence entre les fichiers) d'une version à l'autre dans un format spécial sur disque ; il peut alors recréer ce qu'était n'importe quel fichier à n'importe quel instant en ajoutant toutes les différences.
+Un des systèmes les plus populaires était RCS, qui est encore distribué avec de nombreux systèmes d'exploitation aujourd'hui. Même le système d'exploitation populaire Mac OS X inclut le programme RCS lorsqu'on installe les outils de développement logiciel. Cet outil fonctionne en conservant les patch sets (c'est-à-dire la différence entre les fichiers) d'une version à l'autre dans un format spécial sur disque ; il peut alors recréer ce qu'était n'importe quel fichier à n'importe quel instant en ajoutant toutes les différences.
### Les systèmes de gestion de version centralisés ###
-Le problème majeur suivant que les gens rencontrent est qu'ils ont besoin de collaborer avec des développeurs sur d'autres ordinateurs. Pour traiter ce problème, les systèmes de gestion de version centralisés (CVCS en anglais pour Centralized Version Control Systems) furent développés. Ces systèmes tels que CVS, Subversion, et Perforce, mettent en place un serveur central qui contient tous les fichiers sous version, et des clients qui peuvent extraire les fichiers de ce dépot central. Pendant de nombreuses années, celà a été le standard pour la gestion de version (Cf. Figure 1-2).
+Le problème majeur suivant que les gens rencontrent est qu'ils ont besoin de collaborer avec des développeurs sur d'autres ordinateurs. Pour traiter ce problème, les systèmes de gestion de version centralisés (CVCS en anglais pour *Centralized Version Control Systems*) furent développés. Ces systèmes tels que CVS, Subversion, et Perforce, mettent en place un serveur central qui contient tous les fichiers sous version, et des clients qui peuvent extraire les fichiers de ce dépot central. Pendant de nombreuses années, celà a été le standard pour la gestion de version (Cf. Figure 1-2).
Insert 18333fig0102.png
Figure 1-2. Diagramme de la gestion de version centralisée.
@@ -32,7 +32,7 @@ Cependant ce système a aussi de nombreux défauts. Le plus visible est le point
### Les systèmes de gestion de version distribués ###
-C'est à ce moment que les systèmes de gestion de version distribués entrent en jeu (DVCSs en anglais pour Distributed Version Control Systems). Dans un DVCS (tel que Git, Mercurial, Bazaar or Darcs), les clients n'extraient plus seulement la dernière version d'un fichier : il dupliquent complètement le dépot. Ainsi, si le serveur disparaît, et si les systèmes collaboraient via ce serveur, n'importe quel dépot d'un des clients peut être copié sur le serveur pour le restaurer. Chaque extraction devient une sauvegarde complète de toutes les données (Cf. Figure 1-3).
+C'est à ce moment que les systèmes de gestion de version distribués entrent en jeu (DVCSs en anglais pour *Distributed Version Control Systems*). Dans un DVCS (tel que Git, Mercurial, Bazaar or Darcs), les clients n'extraient plus seulement la dernière version d'un fichier : il dupliquent complètement le dépot. Ainsi, si le serveur disparaît, et si les systèmes collaboraient via ce serveur, n'importe quel dépot d'un des clients peut être copié sur le serveur pour le restaurer. Chaque extraction devient une sauvegarde complète de toutes les données (cf. Figure 1-3).
Insert 18333fig0103.png
Figure 1-3. Diagramme de gestion de version de contrôle centralisée.
@@ -41,21 +41,21 @@ De plus, un grand nombre de ces systèmes gère particulièrement bien le fait d
## Une rapide histoire de Git ##
-Comme de nombreuses choses extraordinaires de la vie, Git est né avec une dose de destruction créative et de controverse houleuse. Le kernel Linux est un projet libre de plutôt grande envergure. Pour la plus grande partie de sa vie (1991–2002), les modifications étaient transmises sous forme de patchs et d'archives de fichiers. En 2002, le projet du kernel Linux commença à utiliser un DVCS propriétaire appelé BitKeeper.
+Comme de nombreuses choses extraordinaires de la vie, Git est né avec une dose de destruction créative et de controverse houleuse. Le noyau Linux est un projet libre de grande envergure. Pour la plus grande partie de sa vie (1991–2002), les modifications étaient transmises sous forme de patchs et d'archives de fichiers. En 2002, le projet du kernel Linux commença à utiliser un DVCS propriétaire appelé BitKeeper.
-En 2005, les relations entre la communinauté développant le kernel linux et la société en charge du développement de BitKeeper furent rompues, et le statut de gratuité de l'outil fut révoqué. Celà poussa la communauté du développement de Linux (et plus particulièrement Linus Torvalds, le créateur de Linux) à developper leur propre outil en se basant sur les leçons apprises lors de l'utilisation de BitKeeper. Certains des objectifs du nouveau système étaient les suivants :
+En 2005, les relations entre la communinauté développant le noyau linux et la société en charge du développement de BitKeeper furent rompues, et le statut de gratuité de l'outil fut révoqué. Celà poussa la communauté du développement de Linux (et plus particulièrement Linus Torvalds, le créateur de Linux) à developper leur propre outil en se basant sur les leçons apprises lors de l'utilisation de BitKeeper. Certains des objectifs du nouveau système étaient les suivants :
* Vitesse
* Conception simple
* Support pour les développements non linéaires (milliers de branches parallèles)
* Complètement distribué
-* Capacité à gérer efficacement des projets d'envergure tels que le kernel Linux (vitesse et compacité des données)
+* Capacité à gérer efficacement des projets d'envergure tels que le noyau Linux (vitesse et compacité des données)
-Depuis sa naissance en 2005, Git a évolué et mûri vers une utilisation plus simple, tout en retenant ses qualités initiales. Il est incroyablement rapide, il est très efficace pour de grands projets, et il a un système incroyable de gestion de branches pour le développement non linéaire (Cf. Chapitre 3).
+Depuis sa naissance en 2005, Git a évolé et mûri pour être facile à utiliser mais en conservant cepandant ces qualités initiales. Il est incroyablement rapide, il est très efficace avec de grands projets et il a un incroyable système de branches pour des développements non-linéaires (voir chapitre 3).
## Rudiments de Git ##
-Donc, qu'est-ce que Git en quelques concepts ? Il est important de bien comprendre cette section , parce que si on comprend ce que Git est et les principes sur lesquels il repose, alors utiliser efficacement Git devient simple. Au cours de l'apprentissage de Git, essayer de libérer votre esprit de ce que vous pourriez connaître d'autres VCSs, tels que Subversion et Perforce ; ce faisant, vous vous éviterez de petites confusions à l'utilisation de cet outil. Git sauve et gère l'information très différemment des autres systèmes, même si l'interface utilisateur paraît similaire ; comprendre ses différences vous évitera des confusions à l'utilisation.
+Donc, qu'est-ce que Git en quelques concepts ? Il est important de bien comprendre cette section, parce que si on comprend ce que Git est et les principes sur lesquels il repose, alors utiliser efficacement Git devient simple. Au cours de l'apprentissage de Git, essayez de libérer votre esprit de ce que vous pourriez connaître d'autres VCSs, tels que Subversion et Perforce ; ce faisant, vous vous éviterez de petites confusions à l'utilisation de cet outil. Git sauve et gère l'information très différemment des autres systèmes, même si l'interface utilisateur paraît similaire ; comprendre ses différences vous évitera des confusions à l'utilisation.
### Des instantanés, pas des différences ###
@@ -138,7 +138,7 @@ Quand vous avez toutes les dépendances nécessaires, vous pouvez poursuivre et
http://git-scm.com/download
-Puis, compiler et installer
+Puis, compiler et installer :
$ tar -zxf git-1.6.0.5.tar.gz
$ cd git-1.6.0.5
View
1,122 id/02-git-basics/01-chapter2.markdown
@@ -0,0 +1,1122 @@
+# Dasar-dasar Git #
+
+Jika Anda hanya sempat membaca satu bab untuk dapat bekerja dengan Git, bab inilah yang tepat. Bab ini menjelaskan setiap perintah dasar yang Anda butuhkan untuk menyelesaikan sebagian besar permasalahan yang akan Anda hadapi dalam penggunaan Git. Pada akhir bab, Anda akan dapat mengkonfigurasi dan memulai sebuah repositori, memulai dan mengakhiri pemantauan berkas, dan melakukan staging dan committing perubahannya. Kami juga akan menunjukkan kepada Anda cara menata Git untuk mengabaikan berkas-berkas ataupun pola berkas tertentu, cara untuk membatalkan kesalahan secara cepat dan mudah, cara untuk melihat sejarah perubahan dari proyek dan melihat perubahan-perubahan yang telah terjadi diantara commit, dan cara untuk mendorong dan menarik perubahan dari repositori lain.
+
+## Mengambil Repositori Git ##
+
+Anda dapat mengambil sebuah proyek Git melalui 2 pendekatan utama. Cara pertama adalah dengan mengambil proyek atau direktori tersedia untuk dimasukkan ke dalam Git. Cara kedua adalah dengan melakukan kloning/duplikasi dari repositori Git yang sudah ada dari server.
+
+### Memulai Repository di Direktori Tersedia ###
+
+Jika Anda mulai memantau proyek yang sudah ada menggunakan Git, Anda perlu masuk ke direktori dari proyek tersebut dan mengetikkan
+
+ $ git init
+
+Git akan membuat sebuah subdirektori baru bernama .git yang akan berisi semua berkas penting dari repositori Anda, yaitu kerangka repositori dari Git. Pada titik ini, belum ada apapun dari proyek Anda yang dipantau. (Lihat Bab 9 untuk informasi lebih lanjut mengenai berkas apa saja yang terdapat di dalam direktori `.git` yang baru saja kita buat.)
+
+Jika Anda ingin mulai mengendalikan versi dari berkas tersedia (bukan direktori kosong), Anda lebih baik mulai memantau berkas tersebut dengan melakukan commit awal. Caranya adalah dengan beberapa perintah `git add` untuk merumuskan berkas yang ingin anda pantau, diikuti dengan sebuah commit:
+
+ $ git add *.c
+ $ git add README
+ $ git commit –m 'versi awal proyek'
+
+Kita akan membahas apa yang dilakukan perintah-perintah di atas sebentar lagi. Pada saat ini, Anda sudah memiliki sebuah repositori Git berisi file-file terpantau dan sebuah commit awal.
+
+### Duplikasi Repositori Tersedia ###
+
+Jika Anda ingin membuat salinan dari repositori Git yang sudah tersedia — misalnya, dari sebuah proyek yang Anda ingin ikut berkontribusi di dalamnya — perintah yang Anda butuhkan adalah `git clone`. Jika Anda sudah terbiasa dengan sistem VCS lainnya seperti Subversion, Anda akan tersadar bahwa perintahnya adalah clone dan bukan checkout. Ini adalah pembedaan yang pe