├── .gitignore ├── COPYING ├── Makefile ├── book.css ├── custom-html.xsl ├── de ├── .gitignore ├── Makefile ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── pot │ ├── basic.po │ ├── branch.po │ ├── clone.po │ ├── drawbacks.po │ ├── grandmaster.po │ ├── history.po │ ├── intro.po │ ├── multiplayer.po │ ├── preface.po │ ├── secrets.po │ └── translate.po ├── preface.txt ├── secrets.txt └── translate.txt ├── en ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── translate.txt ├── es ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── spanish.txt ├── find_selflink.js ├── fr ├── TODO.txt ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── translate.txt ├── gitmagic.Rproj ├── it ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── translate.txt ├── ko ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── translate.txt ├── makeover ├── pl ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── translate.txt ├── po4gitmagic ├── Makefile └── README ├── pt_br ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── translate.txt ├── ru ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── translate.txt ├── uk ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── translate.txt ├── vi ├── README ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── translate.txt ├── zh_cn ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── translate.txt └── zh_tw ├── basic.txt ├── branch.txt ├── clone.txt ├── drawbacks.txt ├── grandmaster.txt ├── history.txt ├── intro.txt ├── multiplayer.txt ├── preface.txt ├── secrets.txt └── translate.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.fo 3 | *.aux 4 | *.out 5 | *.pdf 6 | fop-zh* 7 | /book* 8 | /conf 9 | /fop/* 10 | .* 11 | *~ 12 | .Rproj.user 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # The availaible translation languages. 2 | # When starting a new translation, add a language code here. 3 | 4 | TRANSLATIONS = de es fr ko pt_br ru uk vi zh_cn zh_tw it pl 5 | LANGS = en $(TRANSLATIONS) 6 | 7 | .PHONY: all clean $(LANGS) 8 | 9 | all: $(LANGS) 10 | 11 | $(LANGS): %: book-% book-%/default.css book-%.html book-%.pdf book-%.epub 12 | 13 | # The book consists of these text files in the following order: 14 | 15 | TXTFILES := preface.txt intro.txt basic.txt clone.txt branch.txt history.txt \ 16 | multiplayer.txt grandmaster.txt secrets.txt drawbacks.txt translate.txt 17 | 18 | $(foreach l,$(LANGS),book-$(l).xml): book-%.xml: $(addprefix %/,$(TXTFILES)) 19 | # Concatenate the text files and feed to AsciiDoc. 20 | # If a file has not yet been translated for the target language, 21 | # then substitute the English version. 22 | # Kludge to support any translation of "Preface". 23 | echo '[specialsections]' > conf ; \ 24 | if [ $* != ru ]; then \ 25 | sed -n '/^== .* ==$$/p' $*/preface.txt | sed 's/^== \(.*\) ==$$/^\1$$=preface/' >> conf ; \ 26 | else \ 27 | cp lang-ru.conf conf ; fi ; \ 28 | ( for FILE in $^ ; do if [ -f $$FILE ]; then cat $$FILE; else \ 29 | cat en/$$(basename $$FILE); fi; echo ; done ) | \ 30 | asciidoc -a lang=$* -d book -b docbook -f conf - > $@ 31 | 32 | # This rule allows unfinished translations to build. 33 | # Report an error if the English version of the text file is missing. 34 | $(addprefix en/,$(TXTFILES)): 35 | @if [ ! -f $@ ]; then echo English file missing: $@; exit 123; fi 36 | $(foreach l,$(TRANSLATIONS),$(addprefix $(l)/,$(TXTFILES))): 37 | @if [ ! -f $@ ]; then echo $@ missing: using English version; fi 38 | 39 | # Ignore tidy's exit code because Asciidoc generates section IDs beginning with 40 | # "_", which xmlto converts to "id" attributes of tags. The standard 41 | # insists that "id" attributes begin with a letter, which causes tidy to 42 | # print a warning and return a nonzero code. 43 | # 44 | # When Asciidoc 8.3.0+ is widespread, I'll use its idprefix attribute instead 45 | # of ignoring return codes. 46 | 47 | $(foreach l,$(LANGS),book-$(l)): book-%: book-%.xml 48 | xmlto -m custom-html.xsl -o book-$* html book-$*.xml 49 | sed -i'' -e 's/xmlns:fo[^ ]*//g' book-$*/*.html 50 | -ls book-$*/*.html | xargs -n 1 tidy -utf8 -m -i -q 51 | ./makeover $* 52 | 53 | $(foreach l,$(LANGS),book-$(l)/default.css): book-%/default.css: book.css 54 | -mkdir -p book-$* 55 | rsync book.css book-$*/default.css 56 | 57 | $(foreach l,$(LANGS),book-$(l).html): book-%.html: book-%.xml 58 | pandoc -s -f docbook -t html5 -o $@ $^ 59 | 60 | $(foreach l,$(LANGS),book-$(l).pdf): book-%.pdf: book-%.xml 61 | pandoc -s -f docbook -o $@ --pdf-engine=xelatex $^ 62 | 63 | book-ru.pdf: book-ru.xml 64 | pandoc -s -f docbook -o $@ --pdf-engine xelatex -V mainfont='DejaVuSansMono' $^ 65 | 66 | book-uk.pdf: book-uk.xml 67 | pandoc -s -f docbook -o $@ --pdf-engine xelatex -V mainfont='DejaVuSansMono' $^ 68 | 69 | book-ko.pdf: book-ko.xml 70 | pandoc -s -f docbook -o $@ --pdf-engine xelatex -V CJKmainfont='NanumGothic' $^ 71 | 72 | book-zh_cn.pdf: book-zh_cn.xml 73 | pandoc -s -f docbook -o $@ --pdf-engine xelatex -V CJKmainfont='WenQuanYi Micro Hei Mono' $^ 74 | 75 | book-zh_tw.pdf: book-zh_tw.xml 76 | pandoc -s -f docbook -o $@ --pdf-engine xelatex -V CJKmainfont='WenQuanYi Micro Hei Mono' $^ 77 | 78 | $(foreach l,$(LANGS),book-$(l).epub): book-%.epub: book-%.xml 79 | pandoc -s -f docbook -o $@ $^ 80 | 81 | clean: 82 | -rm -rf $(foreach l,$(LANGS),book-$(l).pdf book-$(l).xml book-$(l).html book-$(l)) \ 83 | *.fo *.log *.out *.aux conf 84 | -------------------------------------------------------------------------------- /book.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 95%; 3 | font-family: 'Open Sans', sans-serif; 4 | } 5 | 6 | tt, code, pre, .type { 7 | font-family: andale mono, courier new, courier, monospace; 8 | font-size: 90%; 9 | } 10 | 11 | pre { 12 | color: #0000aa; 13 | } 14 | 15 | ul li p { 16 | margin: 0; 17 | padding: 0; 18 | } 19 | 20 | /* Based on http://phrogz.net/CSS/columns3.html */ 21 | div.toc { 22 | float: left; 23 | margin: 0; 24 | padding: 0; 25 | padding-top: 0.5em; 26 | border: 0; 27 | width: 16em; 28 | 29 | background-color: #f9f9f9; 30 | margin-right:1em; 31 | } 32 | 33 | div.content { 34 | margin: 0; 35 | padding: 0; 36 | 37 | /* won't match if font is smaller in toc */ 38 | border-left: 16em solid #f9f9f9; 39 | padding-left: 1em; 40 | } 41 | 42 | div.content:after { 43 | content:' '; 44 | clear:both; 45 | display:block; 46 | height:0; 47 | overflow:hidden 48 | } 49 | 50 | div.footer { 51 | clear:left; 52 | padding: 0.5em; 53 | /* background-color: #f9f9f9; 54 | border: 1px solid #aaaaaa; */ 55 | font-size: 80%; 56 | margin: 0; 57 | } 58 | 59 | div.toc ul { 60 | list-style: none; 61 | padding: 0; 62 | margin: 0; 63 | } 64 | 65 | div.toc li ul a, li ul span.currentlink 66 | { 67 | font-weight: normal; 68 | font-size: 90%; 69 | padding-left: 2em; 70 | } 71 | 72 | div.toc a, span.currentlink{ 73 | display:block; 74 | text-decoration: none; 75 | padding-left: 0.5em; 76 | color: #0000aa; 77 | } 78 | 79 | span.currentlink { 80 | text-decoration: none; 81 | background-color: #aaaaf9; 82 | } 83 | 84 | div.toc a:visited { 85 | color: #0000aa; 86 | } 87 | 88 | div.toc a:hover { 89 | background-color: #f9f9aa; 90 | } 91 | 92 | .programlisting, .screen { 93 | margin: 0; 94 | border: 1px solid #aaaaaa; 95 | background-color: #f9f9f9; 96 | padding: 0.17em; 97 | margin: 1em; 98 | margin-right: 3em; 99 | } 100 | 101 | .parameter { 102 | font-style: italic; 103 | } 104 | 105 | h1, h2 { 106 | padding-top: 0.5em; 107 | padding-bottom: 0.17em; 108 | margin: 0; 109 | font-weight: normal; 110 | color: black; 111 | border-bottom: 1px solid #aaaaaa; 112 | } 113 | 114 | h1 { 115 | font-size: 188%; 116 | } 117 | 118 | div.chapter h2 { 119 | font-size: 188%; 120 | } 121 | 122 | div.section h2 { 123 | font-size: 150%; 124 | } 125 | -------------------------------------------------------------------------------- /custom-html.xsl: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | ul 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /de/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *~ 3 | -------------------------------------------------------------------------------- /de/Makefile: -------------------------------------------------------------------------------- 1 | ../po4gitmagic/Makefile -------------------------------------------------------------------------------- /de/pot/translate.po: -------------------------------------------------------------------------------- 1 | # Git Magic - A guide to using Git 2 | # This file is distributed under the GNU GENERAL PUBLIC LICENSE Version 3. 3 | # Benn Lynn , 2007. 4 | # Armin Stebich , 2010, 2011. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: Git Magic deutsch\n" 9 | "Report-Msgid-Bugs-To: bennlynn@gmail.com\n" 10 | "POT-Creation-Date: 2011-07-03 23:06+0300\n" 11 | "PO-Revision-Date: 2011-07-07 18:41+0200\n" 12 | "Last-Translator: Armin Stebich \n" 13 | "Language-Team: DE \n" 14 | "Language: de\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: UTF-8\n" 18 | "Plural-Forms: \n" 19 | 20 | #. type: Plain text 21 | #: ../en/translate.txt:2 22 | msgid "== Appendix B: Translating This Guide ==" 23 | msgstr "== Anhang B: Diese Anleitung übersetzen ==" 24 | 25 | #. type: Plain text 26 | #: ../en/translate.txt:6 27 | msgid "" 28 | "I recommend the following steps for translating this guide, so my scripts " 29 | "can quickly produce HTML and PDF versions, and all translations can live in " 30 | "the same repository." 31 | msgstr "" 32 | "Ich empfehle folgende Schritte um diese Anleitung zu übersetzen, damit meine " 33 | "Skripte einfach eine HTML- und PDF-Version erstellen können. Außerdem können " 34 | "so alle Übersetzungen in einem 'Repository' existieren." 35 | 36 | #. type: Plain text 37 | #: ../en/translate.txt:13 38 | msgid "" 39 | "Clone the source, then create a directory corresponding to the target " 40 | "language's IETF tag: see http://www.w3.org/International/articles/language-" 41 | "tags/Overview.en.php[the W3C article on internationalization]. For example, " 42 | "English is \"en\" and Japanese is \"ja\". In the new directory, and " 43 | "translate the +txt+ files from the \"en\" subdirectory." 44 | msgstr "" 45 | "'Clone' die Quelltexte, dann erstelle ein Verzeichnis mit dem Namen des IETF " 46 | "Sprachkürzel der übersetzten Sprache: siehe http://www.w3.org/International/" 47 | "articles/language-tags/Overview.en.php[den W3C Artikel über " 48 | "Internationalisierung]. Zum Beispiel, Englisch ist \"en\", Japanisch ist \"ja" 49 | "\". Kopiere alle +txt+-Dateien aus dem \"en\"-Verzeichnis in das neue " 50 | "Verzeichnis und übersetze diese." 51 | 52 | #. type: Plain text 53 | #: ../en/translate.txt:15 54 | msgid "" 55 | "For instance, to translate the guide into http://en.wikipedia.org/wiki/" 56 | "Klingon_language[Klingon], you might type:" 57 | msgstr "" 58 | "Um zum Beispiel die Anleitung auf http://de.wikipedia.org/wiki/" 59 | "Klingonische_Sprache[Klingonisch] zu übersetzen, mußt du folgendes machen:" 60 | 61 | #. type: Plain text 62 | #: ../en/translate.txt:22 63 | #, no-wrap 64 | msgid "" 65 | " $ git clone git://repo.or.cz/gitmagic.git\n" 66 | " $ cd gitmagic\n" 67 | " $ mkdir tlh # \"tlh\" is the IETF language code for Klingon.\n" 68 | " $ cd tlh\n" 69 | " $ cp ../en/intro.txt .\n" 70 | " $ edit intro.txt # Translate the file.\n" 71 | msgstr "" 72 | " $ git clone git://repo.or.cz/gitmagic.git\n" 73 | " $ cd gitmagic\n" 74 | " $ mkdir tlh # \"tlh\" ist das IETF Sprachkürzel für Klingonisch.\n" 75 | " $ cd tlh\n" 76 | " $ cp ../en/intro.txt .\n" 77 | " $ edit intro.txt # übersetze diese Datei.\n" 78 | 79 | #. type: Plain text 80 | #: ../en/translate.txt:24 81 | msgid "and so on for each text file." 82 | msgstr "und das machst du für jede txt-Datei." 83 | 84 | #. type: Plain text 85 | #: ../en/translate.txt:27 86 | msgid "" 87 | "Edit the Makefile and add the language code to the `TRANSLATIONS` variable. " 88 | "You can now review your work incrementally:" 89 | msgstr "" 90 | "Bearbeite das Makefile und füge das Sprachkürzel zur Variable `TRANSLATIONS` " 91 | "hinzu. Nun kannst Du Deine Arbeit jederzeit wie folgt überprüfen:" 92 | 93 | #. type: Plain text 94 | #: ../en/translate.txt:30 95 | #, no-wrap 96 | msgid "" 97 | " $ make tlh\n" 98 | " $ firefox book-tlh/index.html\n" 99 | msgstr "" 100 | " $ make tlh\n" 101 | " $ firefox book-tlh/index.html\n" 102 | 103 | #. type: Plain text 104 | #: ../en/translate.txt:33 105 | msgid "" 106 | "Commit your changes often, then let me know when they're ready. GitHub has " 107 | "an interface that facilitates this: fork the \"gitmagic\" project, push your " 108 | "changes, then ask me to merge." 109 | msgstr "" 110 | "'Committe' deine Änderungen oft und wenn du fertig bist, gib bitte Bescheid. " 111 | "GitHub hat eine Schnittstelle, die das erleichtert: Erzeuge deine eigene " 112 | "'Fork' vom \"gitmagic\" Projekt, 'pushe' deine Änderungen, dann gib mir " 113 | "Bescheid, deine Änderungen zu 'mergen'." 114 | 115 | #~ msgid "" 116 | #~ "I like to have translations follow the above scheme so my scripts can " 117 | #~ "produce HTML and PDF versions. Also, it conveniently keeps all the " 118 | #~ "translations in the official repository. But please do whatever suits you " 119 | #~ "best: for example, the Chinese translators used Google Docs. I'm happy as " 120 | #~ "long as your work enables more people to access my work." 121 | #~ msgstr "" 122 | #~ "Ich bevorzuge Übersetzungen nach diesem Schema, denn so können meine " 123 | #~ "Skripte HTML und PDF Versionen erstellen. Außerdem hält es alle " 124 | #~ "Übersetzungen bequem im offiziellen 'Repository'. Trotzdem, wähle den " 125 | #~ "Weg, der dir am besten liegt. Die chinesischen Übersetzer zum Beispiel " 126 | #~ "benutzen Google Docs. Ich bin glücklich, so lange deine Arbeit mehr " 127 | #~ "Menschen den Zugang zu meiner Arbeit ermöglicht." 128 | -------------------------------------------------------------------------------- /de/preface.txt: -------------------------------------------------------------------------------- 1 | = Git Magic = Ben Lynn August 2007 2 | 3 | == Vorwort == 4 | 5 | http://git.or.cz/[Git] ist eine Art "Schweizer Taschenmesser" für 6 | Versionsverwaltung. Ein zuverlässiges, vielseitiges 7 | Mehrzweck-Versionsverwaltungswerkzeug, dessen außergewöhnliche Flexibilität 8 | es schwierig zu erlernen macht, ganz zu schweigen davon, es zu meistern. 9 | 10 | Wie Arthur C. Clarke festgestellt hat, ist jede hinreichend fortschrittliche 11 | Technologie nicht von Magie zu unterscheiden. Das ist ein großartiger Ansatz, 12 | um an Git heranzugehen: Anfänger können seine inneren Mechanismen ignorieren 13 | und Git als ein Ding ansehen, dass mit seinen erstaunlichen Fähigkeiten 14 | Freunde verzückt und Gegner zur Weißglut bringt. 15 | 16 | Anstatt die Details aufzudecken, bieten wir grobe Anweisungen für die 17 | jeweiligen Funktionen. Bei regelmäßiger Anwendung wirst Du allmählich 18 | verstehen, wie die Tricks funktionieren und wie Du die Rezepte auf Deinen 19 | Bedarf zuschneiden kannst. 20 | 21 | .Übersetzungen 22 | 23 | - link:/\~blynn/gitmagic/intl/zh_cn/[Vereinfachtes Chinesisch]: von JunJie, 24 | Meng und JiangWei. Zu link:/~blynn/gitmagic/intl/zh_tw/[Traditionellem 25 | Chinesisch] konvertiert via +cconv -f UTF8-CN -t UTF8-TW+. 26 | - link:/~blynn/gitmagic/intl/fr/[Französich]: von Alexandre Garel, Paul 27 | Gaborit, und Nicolas Deram. 28 | - link:/~blynn/gitmagic/intl/de/[Deutsch]: von Benjamin Bellee und Armin 29 | Stebich; Auch gehostet unter http://gitmagic.lordofbikes.de/[Armin's 30 | Website]. 31 | - link:/~blynn/gitmagic/intl/it/[Italienisch]: von Mattia Rigotti. 32 | - http://www.slideshare.net/slide_user/magia-git[Portugiesisch]: von 33 | Leonardo Siqueira Rodrigues 34 | [http://www.slideshare.net/slide_user/magia-git-verso-odt[ODT-Version]]. 35 | - link:/~blynn/gitmagic/intl/ru/[Russisch]: von Tikhon Tarnavsky, Mikhail 36 | Dymskov, und anderen. 37 | - link:/~blynn/gitmagic/intl/es/[Spanisch]: von Rodrigo Toledo und Ariset 38 | Llerena Tapia. 39 | - link:/~blynn/gitmagic/intl/vi/[Vietnamesisch]: von Trần Ngọc Quân; Auch 40 | gehostet unter 41 | http://vnwildman.users.sourceforge.net/gitmagic.html[seiner Website]. 42 | 43 | .Andere Ausgaben 44 | 45 | - link:book.html[Einzelne Webseite]: reines HTML, ohne CSS. 46 | - link:book.pdf[PDF Datei]: druckerfreundlich. 47 | - http://packages.debian.org/gitmagic[Debian Packet], 48 | http:://packages.ubuntu.com/gitmagic[Ubuntu Packet]: Für eine schnelle 49 | und lokale Kopie dieser Seite. Praktisch, 50 | http://csdcf.stanford.edu/status/[wenn dieser Server offline ist]. 51 | - http://www.amazon.com/Git-Magic-Ben-Lynn/dp/1451523343/[Gedrucktes Buch 52 | [Amazon.com]]: 64 Seiten, 15.24cm x 22.86cm, schwarz/weiß. Praktisch, 53 | wenn es keinen Strom gibt. 54 | 55 | === Danke! === 56 | 57 | Ich bin erstaunt, dass so viele Leute an der Übersetzung dieser Seiten 58 | gearbeitet haben. Ich weiß es zu würdigen, dass ich, dank der Bemühungen der 59 | oben genannten, einen größeren Leserkreis erreiche. 60 | 61 | Dustin Sallings, Alberto Bertogli, James Cameron, Douglas Livingstone, 62 | Michael Budde, Richard Albury, Tarmigan, Derek Mahar, Frode Aannevik, Keith 63 | Rarick, Andy Somerville, Ralf Recker, Øyvind A. Holm, Miklos Vajna, 64 | Sébastien Hinderer, Thomas Miedema, Joe Malin, und Tyler Breisacher haben 65 | Korrekturen und Verbesserungen beigesteuert. 66 | 67 | François Marier unterhält das Debian Packet, das ursprünglich von Daniel 68 | Baumann erstellt wurde. 69 | 70 | Meine Dankbarkeit gilt auch vielen anderen für deren Unterstützung und 71 | Lob. Ich war versucht, Euch hier alle aufzuzählen, aber das könnte 72 | Erwartungen in unermesslichem Umfang wecken. 73 | 74 | Wenn ich Dich versehentlich vergessen habe, sag' mir bitte Bescheid oder 75 | schicke mir einfach einen Patch! 76 | 77 | .Kostenloses Git Hosting 78 | 79 | - http://repo.or.cz/[http://repo.or.cz/] hostet freie Projekte. Die 80 | allererste Git Hosting Seite. Gegründet und betrieben von einem der 81 | ersten Git Entwickler. 82 | - http://gitorious.org/[http://gitorious.org/] ist eine andere Git Hosting 83 | Seite, bevorzugt für Open-Source Projekte. 84 | - http://github.com/[http://github.com/] hostet Open-Source Projekte 85 | kostenlos und geschlossene Projekte gegen Gebühr. 86 | 87 | Vielen Dank an alle diese Seiten für das Hosten dieser Anleitung. 88 | 89 | === Lizenz === 90 | 91 | Diese Anleitung ist unter der 92 | http://www.gnu.org/licenses/gpl-3.0.html[GNU General Public License 93 | Version 3] veröffentlicht. Natürlich wird der Quelltext in einem Git 'Repository' gehalten 94 | und kann abgerufen werden durch: 95 | 96 | $ git clone git://repo.or.cz/gitmagic.git # Erstellt "gitmagic" Verzeichnis. 97 | 98 | oder von einem der Mirrorserver: 99 | 100 | $ git clone git://github.com/blynn/gitmagic.git 101 | $ git clone git://gitorious.org/gitmagic/mainline.git 102 | -------------------------------------------------------------------------------- /de/translate.txt: -------------------------------------------------------------------------------- 1 | == Anhang B: Diese Anleitung übersetzen == 2 | 3 | Ich empfehle folgende Schritte, um diese Anleitung zu übersetzen, damit meine 4 | Skripte einfach eine HTML- und PDF-Version erstellen können. Außerdem können 5 | so alle Übersetzungen in einem 'Repository' existieren. 6 | 7 | 'Clone' die Quelltexte, dann erstelle ein Verzeichnis mit dem Namen des IETF 8 | Sprachkürzel der übersetzten Sprache: siehe 9 | http://www.w3.org/International/articles/language-tags/Overview.en.php[den 10 | W3C Artikel über Internationalisierung]. Zum Beispiel, Englisch ist "en", 11 | Japanisch ist "ja". Kopiere alle +txt+-Dateien aus dem "en"-Verzeichnis in 12 | das neue Verzeichnis und übersetze diese. 13 | 14 | Um zum Beispiel die Anleitung auf 15 | http://de.wikipedia.org/wiki/Klingonische_Sprache[Klingonisch] zu 16 | übersetzen, musst du folgendes machen: 17 | 18 | $ git clone git://repo.or.cz/gitmagic.git 19 | $ cd gitmagic 20 | $ mkdir tlh # "tlh" ist das IETF Sprachkürzel für Klingonisch. 21 | $ cd tlh 22 | $ cp ../en/intro.txt . 23 | $ edit intro.txt # übersetze diese Datei. 24 | 25 | und das machst du für jede txt-Datei. 26 | 27 | Bearbeite das Makefile und füge das Sprachkürzel zur Variable `TRANSLATIONS` 28 | hinzu. Nun kannst Du Deine Arbeit jederzeit wie folgt überprüfen: 29 | 30 | $ make tlh 31 | $ firefox book-tlh/index.html 32 | 33 | 'Committe' Deine Änderungen oft, und wenn Du fertig bist, gib bitte 34 | Bescheid. GitHub hat eine Schnittstelle, die das erleichtert: Erzeuge Deinen 35 | eigene 'Fork' vom "gitmagic" Projekt, 'pushe' Deine Änderungen, dann gib mir 36 | Bescheid, Deine Änderungen zu 'mergen'. 37 | -------------------------------------------------------------------------------- /en/intro.txt: -------------------------------------------------------------------------------- 1 | == Introduction == 2 | 3 | I'll use an analogy to introduce version control. See http://en.wikipedia.org/wiki/Revision_control[the Wikipedia entry on revision control] for a saner explanation. 4 | 5 | === Work is Play === 6 | 7 | I've played computer games almost all my life. In contrast, I only started using version control systems as an adult. I suspect I'm not alone, and comparing the two may make these concepts easier to explain and understand. 8 | 9 | Think of editing your code, or document, as playing a game. Once you've made a lot of progress, you'd like to save. To do so, you click on the 'Save' button in your trusty editor. 10 | 11 | But this will overwrite the old version. It's like those old school games which only had one save slot: sure you could save, but you could never go back to an older state. Which was a shame, because your previous save might have been right at an exceptionally fun part of the game that you'd like to revisit one day. Or worse still, your current save is in an unwinnable state, and you have to start again. 12 | 13 | === Version Control === 14 | 15 | When editing, you can 'Save As...' a different file, or copy the file somewhere first before saving if you want to savour old versions. You can compress them too to save space. This is a primitive and labour-intensive form of version control. Computer games improved on this long ago, many of them providing multiple automatically timestamped save slots. 16 | 17 | Let's make the problem slightly tougher. Say you have a bunch of files that go together, such as source code for a project, or files for a website. Now if you want to keep an old version you have to archive a whole directory. Keeping many versions around by hand is inconvenient, and quickly becomes expensive. 18 | 19 | With some computer games, a saved game really does consist of a directory full of files. These games hide this detail from the player and present a convenient interface to manage different versions of this directory. 20 | 21 | Version control systems are no different. They all have nice interfaces to manage a directory of stuff. You can save the state of the directory every so often, and you can load any one of the saved states later on. Unlike most computer games, they're usually smart about conserving space. Typically, only a few files change from version to version, and not by much. Storing the differences instead of entire new copies saves room. 22 | 23 | === Distributed Control === 24 | 25 | Now imagine a very difficult computer game. So difficult to finish that many experienced gamers all over the world decide to team up and share their saved games to try to beat it. Speedruns are real-life examples: players specializing in different levels of the same game collaborate to produce amazing results. 26 | 27 | How would you set up a system so they can get at each other's saves easily? And upload new ones? 28 | 29 | In the old days, every project used centralized version control. A server somewhere held all the saved games. Nobody else did. Every player kept at most a few saved games on their machine. When a player wanted to make progress, they'd download the latest save from the main server, play a while, save and upload back to the server for everyone else to use. 30 | 31 | What if a player wanted to get an older saved game for some reason? Maybe the current saved game is in an unwinnable state because somebody forgot to pick up an object back in level three, and they want to find the latest saved game where the game can still be completed. Or maybe they want to compare two older saved games to see how much work a particular player did. 32 | 33 | There could be many reasons to want to see an older revision, but the outcome is the same. They have to ask the central server for that old saved game. The more saved games they want, the more they need to communicate. 34 | 35 | The new generation of version control systems, of which Git is a member, are known as distributed systems, and can be thought of as a generalization of centralized systems. When players download from the main server they get every saved game, not just the latest one. It's as if they're mirroring the central server. 36 | 37 | This initial cloning operation can be expensive, especially if there's a long history, but it pays off in the long run. One immediate benefit is that when an old save is desired for any reason, communication with the central server is unnecessary. 38 | 39 | === A Silly Superstition === 40 | 41 | A popular misconception is that distributed systems are ill-suited for projects requiring an official central repository. Nothing could be further from the truth. Photographing someone does not cause their soul to be stolen. Similarly, cloning the master repository does not diminish its importance. 42 | 43 | A good first approximation is that anything a centralized version control system can do, a well-designed distributed system can do better. Network resources are simply costlier than local resources. While we shall later see there are drawbacks to a distributed approach, one is less likely to make erroneous comparisons with this rule of thumb. 44 | 45 | A small project may only need a fraction of the features offered by such a 46 | system, but using systems that scale poorly for tiny projects is like using 47 | Roman numerals for calculations involving small numbers. 48 | 49 | Moreover, your project may grow beyond your original expectations. Using Git from the outset is like carrying a Swiss army knife even though you mostly use it to open bottles. On the day you desperately need a screwdriver you'll be glad you have more than a plain bottle-opener. 50 | 51 | === Merge Conflicts === 52 | 53 | For this topic, our computer game analogy becomes too thinly stretched. Instead, let us again consider editing a document. 54 | 55 | Suppose Alice inserts a line at the beginning of a file, and Bob appends one at the end of his copy. They both upload their changes. Most systems will automatically deduce a reasonable course of action: accept and merge their changes, so both Alice's and Bob's edits are applied. 56 | 57 | Now suppose both Alice and Bob have made distinct edits to the same line. Then it is impossible to proceed without human intervention. The second person to upload is informed of a _merge conflict_, and must choose one edit over another, or revise the line entirely. 58 | 59 | More complex situations can arise. Version control systems handle the simpler cases themselves, and leave the difficult cases for humans. Usually their behaviour is configurable. 60 | -------------------------------------------------------------------------------- /en/preface.txt: -------------------------------------------------------------------------------- 1 | = Git Magic = 2 | Ben Lynn 3 | August 2007 4 | 5 | == Preface == 6 | 7 | http://git-scm.com/[Git] is a version control Swiss army knife. A reliable versatile multipurpose revision control tool whose extraordinary flexibility makes it tricky to learn, let alone master. 8 | 9 | As Arthur C. Clarke observed, any sufficiently advanced technology is indistinguishable from magic. This is a great way to approach Git: newbies can ignore its inner workings and view Git as a gizmo that can amaze friends and infuriate enemies with its wondrous abilities. 10 | 11 | Rather than go into details, we provide rough instructions for particular effects. After repeated use, gradually you will understand how each trick works, and how to tailor the recipes for your needs. 12 | 13 | .Translations 14 | 15 | - link:/\~blynn/gitmagic/intl/zh_cn/[Simplified Chinese]: by JunJie, Meng and JiangWei. Converted to link:/~blynn/gitmagic/intl/zh_tw/[Traditional Chinese] via +cconv -f UTF8-CN -t UTF8-TW+. 16 | - link:/~blynn/gitmagic/intl/fr/[French]: by Alexandre Garel, Paul Gaborit, and Nicolas Deram. 17 | - link:/~blynn/gitmagic/intl/de/[German]: by Benjamin Bellee and Armin Stebich; also http://gitmagic.lordofbikes.de/[hosted on Armin's website]. 18 | - link:/~blynn/gitmagic/intl/it/[Italian]: by Mattia Rigotti. 19 | - link:/~blynn/gitmagic/intl/ko/[Korean]: by Jung-Ho (John) Han; also https://sites.google.com/site/drinkhanjohn/useful-links/[hosted on John's website]. 20 | - link:/~blynn/gitmagic/intl/pl/[Polish]: by Damian Michna. 21 | - link:/~blynn/gitmagic/intl/pt_br/[Brazilian Portuguese]: by José Inácio Serafini and Leonardo Siqueira Rodrigues. 22 | - link:/~blynn/gitmagic/intl/ru/[Russian]: by Tikhon Tarnavsky, Mikhail Dymskov, and others. 23 | - link:/~blynn/gitmagic/intl/es/[Spanish]: by Rodrigo Toledo and Ariset Llerena Tapia. 24 | - link:/~blynn/gitmagic/intl/uk/[Ukrainian]: by Volodymyr Bodenchuk. 25 | - link:/~blynn/gitmagic/intl/vi/[Vietnamese]: by Trần Ngọc Quân; also http://vnwildman.users.sourceforge.net/gitmagic/[hosted on his website]. 26 | 27 | .Other Editions 28 | 29 | - link:book.html[Single webpage]: barebones HTML, with no CSS. 30 | - link:book.pdf[PDF file]: printer-friendly. 31 | - link:book.epub[EPUB file]: E-reader-friendly. 32 | - http://packages.debian.org/gitmagic[Debian package], http://packages.ubuntu.com/gitmagic[Ubuntu package]: get a fast and local copy of this site. Handy http://csdcf.stanford.edu/status/[when this server is offline]. 33 | - http://www.amazon.com/Git-Magic-Ben-Lynn/dp/1451523343/[Physical book [Amazon.com]]: 64 pages, 15.24cm x 22.86cm, black and white. Handy when there is no electricity. 34 | 35 | === Thanks! === 36 | 37 | I'm humbled that so many people have worked on translations of these pages. I 38 | greatly appreciate having a wider audience because of the efforts of those 39 | named above. 40 | 41 | Dustin Sallings, Alberto Bertogli, James Cameron, Douglas Livingstone, Michael Budde, Richard Albury, Tarmigan, Derek Mahar, Frode Aannevik, Keith Rarick, Andy Somerville, Ralf Recker, Øyvind A. Holm, Miklos Vajna, Sébastien Hinderer, Thomas Miedema, Joe Malin, Tyler Breisacher, Sonia Hamilton, Julian Haagsma, Romain Lespinasse, Sergey Litvinov, Oliver Ferrigni, David Toca, Сергей Сергеев, Joël Thieffry, and Baiju Muthukadan contributed corrections and improvements. 42 | 43 | François Marier maintains the Debian package originally created by Daniel 44 | Baumann. 45 | 46 | 47 | My gratitude goes to many others for your support and praise. I'm tempted to 48 | quote you here, but it might raise expectations to ridiculous heights. 49 | 50 | If I've left you out by mistake, please tell me or just send me a patch! 51 | 52 | === License === 53 | 54 | This guide is released under http://www.gnu.org/licenses/gpl-3.0.html[the GNU General Public License, version 3] or any later version published by the Free Software Foundation. 55 | 56 | Naturally, the source is kept in a Git repository, and can be obtained by 57 | typing: 58 | 59 | $ git clone git://repo.or.cz/gitmagic.git # Creates "gitmagic" directory. 60 | 61 | or from one of the mirrors: 62 | 63 | $ git clone git://github.com/blynn/gitmagic.git 64 | $ git clone git://git.assembla.com/gitmagic.git 65 | $ git clone git@bitbucket.org:blynn/gitmagic.git 66 | 67 | GitHub, Assembla, and Bitbucket support private repositories, the latter two 68 | for free. 69 | -------------------------------------------------------------------------------- /en/translate.txt: -------------------------------------------------------------------------------- 1 | == Appendix B: Translating This Guide == 2 | 3 | I recommend the following steps for translating this guide, so my scripts can 4 | quickly produce HTML and PDF versions, and all translations can live in the 5 | same repository. 6 | 7 | Clone the source, then create a directory corresponding to the target 8 | language's IETF tag: see 9 | http://www.w3.org/International/articles/language-tags/Overview.en.php[the W3C 10 | article on internationalization]. For example, English is "en" and Japanese is 11 | "ja". In the new directory, and translate the +txt+ files from the "en" 12 | subdirectory. 13 | 14 | For instance, to translate the guide into http://en.wikipedia.org/wiki/Klingon_language[Klingon], you might type: 15 | 16 | $ git clone git://repo.or.cz/gitmagic.git 17 | $ cd gitmagic 18 | $ mkdir tlh # "tlh" is the IETF language code for Klingon. 19 | $ cd tlh 20 | $ cp ../en/intro.txt . 21 | $ edit intro.txt # Translate the file. 22 | 23 | and so on for each text file. 24 | 25 | Edit the Makefile and add the language code to the `TRANSLATIONS` variable. 26 | You can now review your work incrementally: 27 | 28 | $ make tlh 29 | $ firefox book-tlh/index.html 30 | 31 | Commit your changes often, then let me know when they're ready. 32 | GitHub has an interface that facilitates this: fork the "gitmagic" project, 33 | push your changes, then ask me to merge. 34 | -------------------------------------------------------------------------------- /es/clone.txt: -------------------------------------------------------------------------------- 1 | == Clonando == 2 | 3 | En sistemas de control de versiones antiguos, checkout es la operación standard para obtener archivos. Obtienes un conjunto de archivos en el estado guardado que solicitaste. 4 | 5 | En Git, y otros sistemas de control de versiones distribuídos, clonar es la operación standard. Para obtener archivos se crea un clon de un repositorio entero. En otras palabras, prácticamente se crea una copia idéntica del servidor central. Todo lo que se pueda hacer en el repositorio principal, también podrás hacerlo. 6 | 7 | === Sincronizar Computadoras === 8 | 9 | Este es el motivo por el que usé Git por primera vez. Puedo tolerar hacer tarballs o usar *rsync* para backups y sincronización básica. Pero algunas veces edito en mi laptop, otras veces en mi desktop, y ambas pueden no haberse comunicado en el medio. 10 | 11 | Inicializa un repositorio de Git y haz commit de tus archivos en una máquina, luego en la otra: 12 | 13 | $ git clone otra.computadora:/ruta/a/archivos 14 | 15 | para crear una segunda copia de los archivos y el repositorio Git. De ahora en más, 16 | 17 | $ git commit -a 18 | $ git pull otra.computadora:/ruta/a/archivos HEAD 19 | 20 | va a traer (pull) el estado de los archivos desde la otra máquina hacia la que estás trabajando. Si haz hecho cambios que generen conflictos en un archivo, Git te va a avisar y deberías hacer commit luego de resolverlos. 21 | 22 | === Control Clásico de Fuentes === 23 | 24 | Inicializa un repositorio de Git para tus archivos: 25 | 26 | $ git init 27 | $ git add . 28 | $ git commit -m "Commit Inicial" 29 | 30 | En el servidor central, inicializa un repositorio vacío de Git con algún nombre, 31 | y abre el Git daemon si es necesario: 32 | 33 | $ GIT_DIR=proj.git git init 34 | $ git daemon --detach # podría ya estar corriendo 35 | 36 | Algunos servidores públicos, como http://repo.or.cz[repo.or.cz], tienen un método diferente para configurar el repositorio inicialmente vacío de Git, como llenar un formulario en una página. 37 | 38 | Empuja (push) tu proyecto hacia el servidor central con: 39 | 40 | $ git push git://servidor.central/ruta/al/proyecto.git HEAD 41 | 42 | Ya estamos listos. Para copiarse los fuentes, un desarrollador escribe: 43 | 44 | $ git clone git://servidor.central/ruta/al/proyecto.git 45 | 46 | Luego de hacer cambios, el código en envía al servidor central con: 47 | 48 | $ git commit -a 49 | $ git push 50 | 51 | Si hubo actualizaciones en el servidor principal, la última versión debe ser traída antes de enviar lo nuevo. Para sincronizar con la última versión: 52 | 53 | $ git commit -a 54 | $ git pull 55 | 56 | === Bifurcando (fork) un proyecto === 57 | 58 | ¿Harto de la forma en la que se maneja un proyecto?¿Crees que podrías hacerlo mejor? Entonces en tu servidor: 59 | 60 | $ git clone git://servidor.principal/ruta/a/archivos 61 | 62 | Luego avísale a todos de tu fork del proyecto en tu servidor. 63 | 64 | Luego, en cualquier momento, puedes unir (merge) los cambios del proyecto original con: 65 | 66 | $ git pull 67 | 68 | === Respaldos Definitivos === 69 | 70 | ¿Quieres varios respaldos redundantes a prueba de manipulación y geográficamente diversos? Si tu proyecto tiene varios desarrolladores, ¡no hagas nada! Cada clon de tu código es un backup efectivo. No sólo del estado actual, sino que también de la historia completa de tu proyecto. Gracias al hashing criptográfico, si hay corrupción en cualquiera de los clones, va a ser detectado tan pronto como intente comunicarse con otros. 71 | 72 | Si tu proyecto no es tan popular, busca tantos servidores como puedas para hospedar tus clones. 73 | 74 | El verdadero paranoico debería siempre escribir el último hash SHA1 de 20-bytes de su HEAD en algún lugar seguro. Tiene que ser seguro, no privado. Por ejemplo, publicarlo en un diario funcionaría bien, porque es difícil para un atacante el alterar cada copia de un diario. 75 | 76 | === Multitask A La Velocidad De La Luz === 77 | 78 | Digamos que quieres trabajar en varias prestaciones a la vez. Haz commit de tu proyecto y ejecuta: 79 | 80 | $ git clone . /un/nuevo/directorio 81 | 82 | Gracias a los http://es.wikipedia.org/wiki/Enlace_duro[enlaces duros], los clones locales requieren menos tiempo y espacio que un backup plano. 83 | 84 | Ahora podrás trabajar en dos prestaciones independientes de manera simultánea. Por ejemplo, puedes editar un clon mientras el otro está compilando. En cualquier momento, puedes hacer commit y pull de los cambios desde el otro clon. 85 | 86 | $ git pull /el/otro/clon HEAD 87 | 88 | === Control Guerrillero De Versiones === 89 | 90 | ¿Estás trabajando en un proyecto que usa algún otro sistema de control de versiones y extrañas mucho a Git? Entonces inicializa un repositorio de Git en tu directorio de trabajo. 91 | 92 | $ git init 93 | $ git add . 94 | $ git commit -m "Commit Inicial" 95 | 96 | y luego clónalo: 97 | 98 | $ git clone . /un/nuevo/directorio 99 | 100 | Ahora debes trabajar en el nuevo directorio, usando Git como te sea más cómodo. Cada tanto, querrás sincronizar con los demás, en ese caso, ve al directorio original, sincroniza usando el otro sistema de control de versiones y escribe: 101 | 102 | $ git add . 103 | $ git commit -m "Sincronizo con los demás" 104 | 105 | Luego ve al nuevo directorio y escribe: 106 | 107 | $ git commit -a -m "Descripción de mis cambios" 108 | $ git pull 109 | 110 | El procedimiento para pasarle tus cambios a los demás depende de cuál es tu otro sistema de control de versiones. El nuevo directorio contiene los archivos con tus cambios. Ejecuta los comandos que sean necesarios para subirlos al repositorio central del otro sistema de control de versiones. 111 | 112 | El comando *git svn* automatiza lo anterior para repositorios de Subversion, 113 | y también puede ser usado para http://google-opensource.blogspot.com/ncr/2008/05/export-git-project-to-google-code.html[exportar un proyecto de Git a un repositorio de Subversion]. 114 | -------------------------------------------------------------------------------- /es/preface.txt: -------------------------------------------------------------------------------- 1 | = Git Magic = 2 | Ben Lynn 3 | August 2007 4 | 5 | == Prólogo == 6 | 7 | http://git.or.cz/[Git] es la navaja suiza del control de versiones. Una herramienta de control de revisiones confiable, versátil y multipropósito, que por su extraordinaria flexibilidad es complicada de aprender, y más aún de dominar. Estoy documentando lo que he aprendido hasta ahora en estas páginas, porque inicialmente tuve dificultades para comprender http://www.kernel.org/pub/software/scm/git/docs/user-manual.html[el manual de usuario de Git]. 8 | 9 | Tal como observó Arthur C. Clarke, cualquier tecnología suficientemente avanzada, es indistinguible de la magia. Este es un gran modo de acercarse a Git: los novatos pueden ignorar su funcionamiento interno, y ver a Git como un artefacto que puede asombrar a los amigos y enfurecer a los enemigos con sus maravillosas habilidades. 10 | 11 | En lugar de ser detallados, proveemos instrucciones generales para efectos particulares. Luego de un uso reiterado, gradualmente irás entendiendo como funciona cada truco, y como adaptar las recetas a tus necesidades. 12 | 13 | .Otras ediciones 14 | 15 | - link:/~blynn/gitmagic/intl/zh_cn/[Traducción al chino]: por JunJie, Meng y JiangWei. 16 | - link:book.html[Una única página]: HTML simple, sin CSS. 17 | - link:book.pdf[Archivo PDF]: Listo para imprimir. 18 | - http://packages.debian.org/search?searchon=names&keywords=gitmagic[Paquete gitmagic para Debian]: Consigue una copia rápida y local de este sitio. http://packages.ubuntu.com/jaunty/gitmagic[Paquete para Ubuntu (Jaunty Jackalope)] también disponible. Útil http://csdcf.stanford.edu/status/[cuando este servidor está offline para mantenimiento]. 19 | 20 | === Gracias! === 21 | 22 | Agradezco a Dustin Sallings, Alberto Bertogli, James Cameron, Douglas Livingstone, Michael Budde, Richard Albury, Tarmigan, Derek Mahar y Frode Aannevik por sugerencias y mejoras. Gracias a Daniel Baumann por crear y mantener el paquete para Debian. También gracias a JunJie, Meng y JiangWei por la traducción al chino. [Si me olvidé de tí, por favor recuérdamelo, porque suelo olvidarme de actualizar esta sección] 23 | 24 | Estoy muy agradecido por todos los que me han dado apoyo y elogios. Me gustaría que este fuera un libro real impreso, para poder citar sus generosas palabras en la tapa a modo de promoción. Hablando en serio, aprecio enormemente cada mensaje. El leerlos siempre ilumina mi ánimo. 25 | 26 | === Licencia === 27 | 28 | Esta guía se publica bajo la http://www.gnu.org/licenses/gpl-3.0.html[GNU General Public License versión 3]. Naturalmente, los fuentes se guardan en un repositorio Git, y pueden ser obtenidos escribiendo: 29 | 30 | $ git clone git://repo.or.cz/gitmagic.git # Crea el directorio "gitmagic". 31 | 32 | Ver debajo por otros mirrors. 33 | 34 | === Hosting Git gratuito === 35 | 36 | - http://repo.or.cz/[http://repo.or.cz/] hospeda proyectos gratuitos, 37 | http://repo.or.cz/w/gitmagic.git[incluyendo esta guía]. 38 | - http://gitorious.org/[http://gitorious.org/] es un sitio que apunta al hosting de proyectos open-source. 39 | - http://github.com/[http://github.com/] hospeda proyectos open-source gratis, http://github.com/blynn/gitmagic/tree/master[incluyendo esta guía], y proyectos privados por una cuota. 40 | -------------------------------------------------------------------------------- /es/spanish.txt: -------------------------------------------------------------------------------- 1 | === Last revision in which the translation was synchronized === 2 | preface.txt 09751f37469d32da649b1c64862023820e0d0499 3 | intro.txt 09751f37469d32da649b1c64862023820e0d0499 4 | basic.txt 09751f37469d32da649b1c64862023820e0d0499 5 | clone.txt 46c05532226868b8b3b121d9320c0150491fd181 6 | branch.txt 46c05532226868b8b3b121d9320c0150491fd181 7 | multiplayer.txt 8 | history.txt b17fbe91cafc00866c8c82d705920cd6c5a476d3 9 | grandmaster.txt b17fbe91cafc00866c8c82d705920cd6c5a476d3 10 | secrets.txt 11 | drawbacks.txt b17fbe91cafc00866c8c82d705920cd6c5a476d3 12 | translate.txt 13 | -------------------------------------------------------------------------------- /find_selflink.js: -------------------------------------------------------------------------------- 1 | // From my own website(!) 2 | //TODO: only do this for links in the table of contents menu 3 | 4 | function find_selflink() { 5 | var a = document.links; 6 | var i = 0; 7 | while (i < a.length) { 8 | if (a[i].href == document.URL) { 9 | var c; 10 | var j; 11 | var s_new = document.createElement("span"); 12 | s_new.className = "currentlink"; 13 | c = a[i].childNodes; 14 | for (j=0; j 52 | Date: Tue Mar 14 01:59:26 2000 -0800 53 | 54 | Replace printf() with write(). 55 | 56 | commit 82f5ea346a2e651544956a8653c0f58dc151275c 57 | Author: Alice 58 | Date: Thu Jan 1 00:00:00 1970 +0000 59 | 60 | Initial commit. 61 | ---------------------------------- 62 | 63 | Hash 앞의 알파벳 몇 개만으로도 commit을 세분화 설정하실 수 있습니다; 64 | 다른 방법으로는, 아래의 명령어와 같이 hash 전문을 복사/붙여넣기 하는 방법도 있지요: 65 | 66 | $ git reset --hard 766f 67 | 68 | 위 명령어를 입력하시면 설정된 commit으로 돌아갈 수 있으며 그 후의 새로운 commit들은 영구적으로 삭제됩니다. 69 | 70 | 가끔씩은 또 아주 예전의 state로 잠시만 돌아가길 원하실 수 있습니다. 그럴 경우에는: 71 | 72 | $ git checkout 82f5 73 | 74 | 이 명령어는 82f5 이후의 commit들을 보존함과 동시에 과거의 시간으로 잠시 돌아가게 해줍니다. 그러나, SF영화에서 처럼, 과거에 돌아간 상태에서 편집을하고 commit을 한다면 또 다른 시간대의 현실을 만들어가게 되는 것이죠. 왜냐하면 당신의 편집이 과거의 편집과는 다르게 입력이 되었기 때문입니다. 75 | 76 | 이렇게 새롭게 만들어진 대체현실을 'branch (나뭇가지)'라고 부릅니다 <>. 지금 알고계셔야 할 것은 77 | 78 | $ git checkout master 79 | 80 | 이 명령어는 과거에서 현재의 state로 돌아오게 해줄 것입니다. 그리고 Git이 유저에게 푸념을 놓기전에 과거에서 편집했던 사항들이 있다면 81 | master branch로 돌아오기전 commit을 하거나 reset을 한번 실행하시길 바랍니다. 82 | 83 | 게임과 또 다시 비교해본다 하면: 84 | 85 | - *`git reset --hard`*: 예전에 세이브 해뒀던 게임으로 돌아가며, 돌아간 시점 이후의 세이브들을 모두 삭제합니다. 86 | 87 | - *`git checkout`*: 예전에 세이브 해뒀던 게임으로 돌아가며, 돌아간 시점 이후의 게임들은 처음 세이브와 다른 길을 가게 됩니다. 추후의 모든 세이브들은 다른 branch로써 새로운 현실세계를 만들게 됩니다 <>. 88 | 89 | 예전의 파일/하위 디렉토리들을 되돌리고 싶을 때 다음 명령어를 이용함으로써 필요한 파일/하위 디렉토리만을 되돌릴 수 있습니다: 90 | 91 | $ git checkout 82f5 some.file another.file 92 | 93 | 그러나 이 *checkout* 명령어가 다른 파일들을 조용히 덮어씌우기 할 수 있다는 점을 알아두세요! 이러한 사고를 방지하고 싶다면 94 | checkout 명령어를 쓰기전에 commit을 이용하세요. Git을 처음 이용하는 분들은 특히 더 조심하시기 바랍니다. 95 | 대체적으로 파일이 삭제될까 두려우시다면 *git commit -a*를 우선해놓고 생각하세요. 96 | 97 | 긴 hash 전체를 복붙하기 싫으시다고요? 그렇다면: 98 | 99 | $ git checkout :/"My first b" 100 | 101 | 이 명령어를 사용함으로써 이 commit message를 사용해서 commit했었던 state로 돌아갈 수 있습니다. 102 | 그리고 이 다음 명령어로 5번 스텝 전의 state로 돌아갈 수도 있습니다: 103 | 104 | $ git checkout master~5 105 | 106 | === 되돌리기 (Reverting) === 107 | 108 | 법정에서는 어떠한 일에 관해서는 기록에서 지울 수 있습니다. 이런 식으로, Git에서는 원하는 commit을 정해서 없던 일로 할 수 있습니다. 109 | 110 | $ git commit -a 111 | $ git revert 1b6d 112 | 113 | 이렇게 하는 것으로 특정 hash에 대한 commit을 undo 할 수 있습니다. 이렇게 되돌린 state는 새로운 114 | commit으로 인식되어 *git log*에 기록됩니다. 115 | 116 | === 변경기록 만들기 === 117 | 118 | 어떤 프로젝트들은 http://en.wikipedia.org/wiki/Changelog[changelog]. 필요로 합니다. 119 | 다음 명령어를 이용해 변경기록을 만들어 봅시다.: 120 | 121 | $ git log > ChangeLog 122 | 123 | === 파일 다운로드하기 === 124 | 125 | Git으로 관리되는 프로젝트 사본을 얻기위해서는: 126 | 127 | $ git clone git://server/path/to/files 128 | 129 | 예를 들어, 본 웹사이트를 만들기 위해 사용한 파일들을 얻기위해서는: 130 | 131 | $ git clone git://git.or.cz/gitmagic.git 132 | 133 | 곧 *clone* 명령어에 관해 많은 것을 소개하도록 하겠습니다. 134 | 135 | === 최첨단 기술 === 136 | 137 | *git clone* 명령어를 이용해 어떤 프로젝트의 사본을 다운로드 해뒀다면, 다음 명령어를 이용해 그 프로젝트의 최신버전으로 업데이트 할 수 있습니다: 138 | 139 | $ git pull 140 | 141 | === 즉석 발행 === 142 | 143 | 당신이 다른 사람들과 공유하고 싶은 스크립트를 작성했다고 가정합니다. 당신은 그들에게 당신의 컴퓨터에서 다운로드를 받으라고 할 수있지만, 당신 친구들이 만약 당신이 해당 스크립트를 편집하는 도중에 받게된다면, 그들은 예상치 못한 트러블에 걸릴 수 있습니다. 이러한 이유 때문에 릴리스 사이클이란 것이 존재하는 것입니다. 개발자들은 개발 중인 프로젝트 디렉토리에 자주 들락날락 거릴 것이고, 그들은 그들이 한 작업이 다른 사람들 앞에 내놓을 만한 상태로 만들어지기 전까지 남들에게 보여주지 않을겁니다. 144 | 145 | Git으로 릴리스 사이클을 맞추려면, 당신의 스크립트가 들어있는 디렉토리에서: 146 | 147 | $ git init 148 | $ git add . 149 | $ git commit -m "First release" 150 | 151 | 그리고 당신들 친구들에게 다음 명령어를 사용하도록 하십시오: 152 | 153 | $ git clone your.computer:/path/to/script 154 | 155 | 그들이 이렇게하면 당신의 스크립트를 다운로드 할 수 있을 것입니다. 이 작업은 다른 유저들이 ssh 접근을 할수있다고 가정합니다. 그렇지 않다면, 소유주인 당신이 *git daemon* 명령어를 쓴 후 친구들에게 다음 명령어를 쓰라고 하십시오: 156 | 157 | $ git clone git://your.computer/path/to/script 158 | 159 | 이렇게 하고 난 다음부터 당신의 스크립트가 준비되었을 때마다 다음 명령어를 실행하면 됩니다: 160 | 161 | $ git commit -a -m "Next release" 162 | 163 | 당신의 친구들은 다음 명령어를 사용함으로써 가장 최근 버전으로 당신의 스크립트를 보유하고 있을 수 있게 되죠: 164 | 165 | $ git pull 166 | 167 | 그들은 절대로 당신이 보여주고 싶지않은 버전의 스크립트를 보는 일이 없을 것입니다. 168 | 169 | === 제가 도대체 뭘 한거죠? === 170 | 171 | 마지막으로 한 commit으로 부터 어떤 변화가 있었는지 확인하기 위해서는: 172 | 173 | $ git diff 174 | 175 | 어제부터 어떤 변화가 있었는지 확인하기 위해서는: 176 | 177 | $ git diff "@{yesterday}" 178 | 179 | 어떤 특정 버전에서 부터 2번째 전 버전 사이의 변화를 확인하기 위해서는: 180 | 181 | $ git diff 1b6d "master~2" 182 | 183 | 각각의 결과는 *git apply*와 함께 적용할 수 있는 패치가 될 것입니다. 184 | 다음 명령어도 사용해 보세요: 185 | 186 | $ git whatchanged --since="2 weeks ago" 187 | 188 | 저는 윗 방법대신 http://sourceforge.net/projects/qgit[qgit] 를 따로 다운받아서 commit 히스토리를 체크하곤 합니다. 이 프로그램은 깨끗한 그래픽 인터페이스로 구성되어 있어보기 쉽지요. 아니면, http://jonas.nitro.dk/tig/[tig], 텍스트형식 인터페이스 역시 느린 인터넷속도를 가지고 있는 분들에겐 도움이 될 것입니다. 또 다른 방법으로는 웹 서버를 설치한 후 *git instaweb*명령어를 사용하는 방법도 있겠지요. 189 | 190 | === 연습 === 191 | 192 | 우선 A, B, C, D 를 각각 연속된 한 파일에 대한 commit이라고 가정합니다. 그리고 B는 A 에서 몇 개의 파일들이 삭제된 버전으로 가정합니다. 문제는 여기서 그 삭제된 파일들을 D에 더하고 싶을 때 어떻게 하는 것 인가 입니다. 193 | 194 | 적어도 세가지의 방법이 있습니다. 우선 우리가 현재 D에 있다고 생각합시다: 195 | 196 | 1. A와 B의 차이점은 몇 개의 지워진 파일들 뿐입니다. 우리는 이 차이점을 패치로 따로 작성하여 본래의 디렉토리에 적용할 수 있습니다: 197 | 198 | $ git diff B A | git apply 199 | 200 | 2. 우리는 A에 파일을 저장해 두었기에, 그 곳에서 다시 받아올 수 있겠지요: 201 | 202 | $ git checkout A foo.c bar.h 203 | 204 | 3. 또는 A에서 B까지로 갈 때의 변화를 undo한다고 생각하셔도 됩니다: 205 | 206 | $ git revert B 207 | 208 | 어떤 방법이 가장 좋은 해답일까요? 답은 본인이 원하는 것이 곧 해답입니다. Git을 이용한다면 당신이 원하는 것은 쉽게 해낼 수 있고, 그 것을 해내는 방법은 한가지만 있는 것이 아닐겁니다. 209 | -------------------------------------------------------------------------------- /ko/drawbacks.txt: -------------------------------------------------------------------------------- 1 | == 부록 A: Git의 약점들 == 2 | 3 | Git을 소개하면서 저는 Git의 약점들을 몇 개 숨기긴 했습니다. 몇가지 약점들은 script나 hook을 통해 해결할수 있고, 몇가지는 프로젝트를 수정하면서 해결할수 있고, 그 외의 약점들은 현 시점에선 그냥 앉아서 기다리고 있을 수 밖에 없습니다. 그러기 싫으시다면 직접 도와줘보십쇼! 4 | 5 | === SHA1 약점 === 6 | 7 | 시간이 지나면 해커들은 SHA1의 약점들을 더 많이 발견하게 될겁니다. 이미 hash에서의 충돌을 찾아내는 건 8 | 가능한 일이지요. 몇 년 안에는 Git repository를 위해할 수 있는 연산능력을 가진 9 | 일반컴퓨터도 있을 수 있습니다. 10 | 11 | Git이 그런 일이 일어나기전에 hash관련 기능들을 발전할 수 있었으면 좋겠어요. 12 | 13 | === Microsoft Windows === 14 | 15 | Git을 Microsoft Windows에서 사용하는 건 성가실 수 있습니다: 16 | 17 | - http://cygwin.com/[Cygwin], 리눅스와 비슷한 윈도우체제에선 http://cygwin.com/packages/git/[a Windows port of Git] 가 있습니다. 18 | 19 | - https://gitforwindows.org/[Git for Windows] 는 아직 몇몇 허점이 있지만 Windows에서 Git을 효율적으로 쓸수 있게 해줍니다. 20 | 21 | === Git과 연관없는 파일들 === 22 | 23 | 만약에 당신의 프로젝트가 굉장히 크고, 쓸때없는 파일들이 많이 들어있는 상태이고, 상시로 바뀌는 상태라면, Git은 하나의 파일을 트랙킹하지 않기에 다른 VCS보다 유용하지 않을 수 있습니다. Git은 프로젝트 단위로 트랙킹을 하기 때문입니다. 이건 Git의 장점입니다. 24 | 25 | 그래도 만약 하나의 파일만을 트랙킹하기 원하다면 프로젝트를 여러개의 파트로 분리해두는 겁니다. 여러개의 파트로 분리해도 *git submodule* 명령어를 이용하면 하나의 repository를 유지할 수 있을겁니다. 26 | 27 | === 누가 어떤 작업을 하는거지? === 28 | 29 | 몇몇의 VCS는 유저들로 하여금 작업하기전에 파일들을 강제로 마킹 시킵니다. 이러한 강제성은 중앙서버와 연결하는데 귀찮은 절차이지만 두개의 장점이 있습니다: 30 | 31 | 1. 버전의 차이 (Diff)를 체크하는데 매우 빠릅니다. 마킹 된 파일만 검사하면 되니까요. 32 | 33 | 2. 유저는 어떤 사람이 어떤 작업을 하는지 중앙서버를 조회하면 간단히 알아낼 수 있습니다. 34 | 35 | Git으로도 이렇게 하는게 가능합니다. 그러나 그렇게 하기위해선 코딩이 좀 필요하니 프로그래머의 도움이 좀 필요할 수 있겠군요. 36 | 37 | === 파일 히스토리 === 38 | 39 | Git은 프로젝트 전체를 트랙킹하기 때문에 어떤 한 파일의 히스토리를 재건설하는데 다른 (하나의 파일만 트랙킹하는) VCS들보다 느릴 수 있습니다. 40 | 41 | 그렇게 심하게 느려진다는 것은 아니고 오히려 Git의 장점들이 이 하나의 단점을 상쇄하고도 남습니다. 예를 들어 'git checkout'은 'cp -a'보다 빠르고 프로젝트 전체의 변화를 압축화하는 것이 파일 하나하나씩 압축하는 것보다 효율적입니다. 42 | 43 | === 태초의 클론 === 44 | 45 | 만약에 어떠한 프로젝트의 히스토리가 길 경우, 클론을 만드는 것은 다른 VCS들의 'checking out'보다 컴퓨터의 용량을 더 차지할 수 있습니다. 46 | 47 | 그러나 길게보면 클론이 checking out보다 나을 것입니다. 클로닝 이후 다른 명령어들은 매우 빠르고 오프라인으로도 진행이 가능하니까요. 그러나 어떠한 경우에는 좀 더 히스토리가 얕은 클론을 '--depth' 명령어를 통해 만드는 것이 더 나은 선택일 수 있습니다. 이렇게 만들어진 클론은 작업실행 속도가 빠르겠지만 몇몇 기능들이 제외되어 있을 수 있습니다. 48 | 49 | === 불완전한 프로젝트들 === 50 | 51 | Git은 파일에 작업을 더 많이할 수록 그 작업량에 대비해 빠르게 Version Control을 할 수 있도록 하기위해 쓰여진 프로그램입니다. 인간은 하나의 버전에서 다음 버전으로 작업을 할때 소량의 작업만 진행할 수 있죠. 예를들어, 한줄짜리 코드에 있는 버그를 고친다던가, 새로운 기능을 넣는다던가, 코멘트를 코드에 단다거나 말이죠. 그런데 만약 commit과 commit 사이에 작업량이 방대하게 클 경우 그 파일의 히스토리는 비례해서 커질 수 밖에 없겠죠. 52 | 53 | VCS는 이것에 대해 아무것도 할 수 없습니다. 일반 Git 유저들은 그 부풀어진 파일들을 곧대로 받아들일 수 밖에 없겠죠. 54 | 55 | 그러나 왜 방대한 작업량이 필요했는지에 대해 알아볼 필요는 있습니다. 파일 포맷이 바뀌어서 그랬을수도 있죠. 소량의 작업은 소량의 변화를 주기마련입니다. 56 | 57 | 아니면 데이터베이스나 백업자료실를 구축해놓는 것이 이런 방대한 프로젝트들을 진행하는 데에 있어 VCS보다 적합할수도 있습니다. 예를 들어 VCS는 어떤 웹캠에서 주기적으로 찍은 이미지를 관리하는 데에는 적합하지 않습니다. 58 | 59 | 만약에 파일들이 매번 변화하고 있고 각각의 변화에 무조건 버젼번호를 매겨야겠다 한다면 Git을 중앙서버처럼 쓰는 방법밖에 없습니다. 개발자들은 상대적으로 가벼운 클론을 만들면 되죠. 이렇게 일을 진해하면 물론 단점도 있을겁니다. 픽스들을 패치로 배포해야하고 Git tool들이 들어먹지 않을 수도 있어요. 근데 이렇게라도 일을 진행해야하는게 맞는 방법일 수 있습니다. 아무도 히스토리가 매우 긴 프로젝트들을 곧대로 받긴 싫어하거든요. 60 | 61 | 다른 예시로는 큰 바이너리 파일들을 수행하는 펌웨어들에 기반한 프로젝트를 진행할 경우입니다. 펌웨어의 히스토리는 유저들에게 별로 흥미로운 소재는 아니고, 업데이트들은 압축률이 매우 좋지 않습니다. 그래서 펌웨어들을 재구성할떄는 repository의 크기가 매우 커지는 경우가 있죠. 62 | 63 | 이럴때에는 모든 소스코드들이 Git repository에 저장되어 있는 편이 좋고, 바이너리 파일들은 따로 보관되어야 할 것 입니다. 이 일을 좀 더 쉽게 진행하기 위해서 Git 유저가 어떤 파일에 대해 클론을 만들수있고 *rsync*를 할 수 있으며, 가벼운 클론을 만들수있는 코드를 배포하는 것이 좋을 수 있습니다. 64 | 65 | === 글로벌 카운터 === 66 | 67 | 몇몇 중앙관리식 VCS들은 새로운 commit이 받아들여질때마다 임의의 양의정수를 보존합니다. Git은 양의정수보다 나은 hash를 써서 commit을 관리합니다. 68 | 69 | 그러나 어느 사람들은 아직도 양의정수로 commit관리를 하길 추구합니다. 다행히도 Git에 추가프로그래밍을하여 Git repository에서 양의정수를 1씩 더하는 방식으로 commit을 관리할수도 있습니다. 70 | 71 | 어느 클론 파일이나 양의정수를 사용하여 commit을 관리할 수 있습니다. 그러나 이건 아무짝에도 쓸모가 없죠. 중앙 repository만 이 숫자를 쓸꺼니까요. 72 | 73 | === 빈 (empty) 섭디렉토리 === 74 | 75 | 빈 섭디렉토리는 트랙킹되지 않습니다. 그러나 더미 파일을 만들어서 트랙킹하게 편법을 쓸 수 있죠. 76 | 77 | 현 버전의 Git으로써 이 문제점은 Git의 약점입니다. Git이 다시 수면위로 올라가고 더 많은 사람들이 사용하게 될수록 이런 약점도 메꿔나가 지겠죠. 78 | 79 | === 태초의 commit === 80 | 81 | 보통의 컴퓨터공학자들은 숫자를 셀 때 0부터 세지 1부터 세지 않습니다. 하지만 안타깝게도 commit의 횟수를 셀때 git은 컴퓨터공학자들처럼 숫자를 세지 않습니다. Git의 그 많은 명령어들은 commit이 태초적으로 한번 이루어지기 전까지는 실행되지 않을겁니다. Branch들을 rebasing 할때나 이럴 경우에는 예외일 수도 있습니다. 82 | 83 | 애초에 Git은 태초의 commit으로부터 많은 혜택을 받습니다: repostiory가 생성되자마자 HEAD는 20 zero bytes의 스트링으로 자동설정됩니다. 이 특별한 commit은 빈 나무로 표현합니다. 빈 나무는 부모님 commit도 없습니다. 한마디로 근본이 없는 친구를 태초의 commit으로 부릅니다. 84 | 85 | 그리고 태초의 commit후, git log를 로드했을때 Git이 오류를 내지 않고 단순히 commit이 하나도 안 되었다고 알려줄 것입니다. 86 | 87 | 태초의 commit은 한마디로 zero commit의 양자같은 컨셉트입니다. 88 | 89 | 그러나 이런 구성은 가끔 문제를 야기합니다. 여러개의 branch가 모두 태초의 commit을 하고 이제 branch를 병합시켜야 할때, rebasing은 아마 유저 본인이 수동으로 버전청소를 하라고 할수도 있습니다. 90 | 91 | === 별난 인터페이스 === 92 | 93 | A와 B commit이 있을때, "A..B" 와 "A...B" 표현의 차이는 명령어가 두개의 종점이나 범위가 입력되기를 기다리고 있느냐 마느냐입니다. *git help diff* 와 *git help rev-parse*를 참조하십시오. 94 | -------------------------------------------------------------------------------- /ko/intro.txt: -------------------------------------------------------------------------------- 1 | == 도입부 == 2 | 3 | Github에 대해 설명하기 쉽게 비유법을 사용하여 버전 관리 시스템 (Version Control System; 이하 VCS)를 설명해보려 합니다. 제가 하려는 설명에 비해 덜 정신나간 버전의 설명을 원하시면 http://en.wikipedia.org/wiki/Revision_control 를 방문하시길 권장합니다. 4 | 5 | === "일하는 것"은 곧 "노는 것" === 6 | 7 | 저는 거의 평생을 컴퓨터게임을 하며 지냈습니다. 그에 반해, 어른이 되서야 VCS를 사용하기 시작했지요. 이런 건 저 혼자가 아닐 것이라 생각하니, Git을 게임에 비유하며 설명하는 것이 Git을 이해하는 데 도움이 될 것이라 생각합니다. 8 | 9 | 자, 이제 코드나 문서를 편집하는 작업이 게임을 하는 것과 같다고 생각해보세요. 편집을 마친 후에는 세이브하고 싶겠지요? 그렇게 하기 위해서는 당신의 든든한 코딩에디터에서 '세이브' 버튼을 누르면 될 것입니다. 10 | 11 | 그러나 단순히 '세이브'를 누르는 것은 예전 세이브를 덮어쓰는 결과를 초래하죠. 세이브 슬롯이 한 개밖에 없는 옛날 구형 게임을 생각하면 됩니다. 다시 말하자면, 세이브를 할 수는 있지만, 예전 세이브포인트로 돌아갈 수 없는 것 입니다. 마치, 게임 진행하다가 정말 재미있는 파트에 적재적소에 맞게 세이브를 해 놓았는데 그 포인트로 다신 돌아갈 수 없다는 것이죠. 좀 더 심하게 말하자면, 절대로 깰 수 없는 보스 앞에서 세이브를 한 당신은 그 상태에 평생 머무르게 될수도 있다는 것 입니다. 그럴 경우에는 아주 처음부터 다시 시작해야 된다는 말이 되겠지요. 12 | 13 | === 버전 관리 === 14 | 15 | 코드 등을 편집 시, '다른 이름으로 저장' 아니면 사본을 다른 디렉토리에 카피 떠 놓는 방법 등을 이용해 옛 버전의 코드들을 보존할 수는 있습니다. 컴퓨터 용량을 더욱 효율적으로 사용하기 위해서 압축을 할 수도 있죠. 이것은 참 원시적인 버전 컨트롤 방법입니다. 컴퓨터게임은 이런 과정에서 이미 발전해 나간지 오래되었지요. 요즘 게임들은 여러개의 세이브 슬롯에 시간을 기록해가며 세이브를 영리하게 해냅니다. 16 | 17 | 이 문제를 좀 더 꼬아서 바라봅시다. 당신이 어떤 프로젝트나 웹사이트를 구성하는 소스코드와 같이 여러개의 파일을 보유한다고 가정합시다. 현 버전의 프로젝트/웹사이트를 세이브하고 싶다면 모든 디렉토리를 기록해야 한다는 번거로움이 있겠지요. 일일이 그 수 많은 버전들을 수동으로 관리한다는 것은 그리 효율적이지 않을 겁니다. 컴퓨터 용량도 더불어 많이 사용하게 될꺼고요. 18 | 19 | 어떤 컴퓨터게임들은 정말로 모든 디렉토리를 각개 관리하는 형식으로 게임을 세이브하기도 합니다. 이런 게임들은 이런 불필요하게 세부적인 사항들을 게이머들이 보지 못 하게 하고 간편한 인터페이스를 통해 게이머들이 세이브파일들을 관리할 수 있게 해둡니다. 20 | 21 | VCS는 이런 컨셉과 그리 다르지 않습니다. VCS들은 파일 디렉토리들을 관리하기에 아주 편한 인터페이스로 구성되어 있습니다. 원하는 횟수 만큼 세이브를 할 수 있고, 원하는 세이브포인트를 특정지어 불러오기를 실행할 수도 있습니다. 그리고 컴퓨터게임들과는 다르게 용량을 효율적으로 사용하는 데에는 탁월한 성능을 보여주죠. 대부분의 어떤 코드의 버전을 바꿀 때에는 소수의 파일들만 살짝 바꾸게되죠. 코드자체가 아주 많이 바뀌는 경우는 드뭅니다. 디렉토리 전체를 세이브하는 것 보다는 버전과 버전사이의 차이를 세이브하는 것이 용량을 효율적으로 쓰는 VCS의 비밀입니다. 22 | 23 | === 분산 제어 === 24 | 25 | 여러분이 어려운 컴퓨터 게임을 한다고 생각해보세요. 너무 어렵기 때문에 전 세계의 프로게이머들이 팀을 구성해 이 게임을 끝내보겠다고 합니다. 게임을 빨리 끝내는 것에 초점을 두는 스피드런 방식의 게임 스타일이 현실적인 예시 이지요: 각기 다른 특기를 가지고 있는 게이머들이 한 게임 안에서 각자 자신있는 부분을 담당함으로써 성공적인 결과를 만들어내는 것을 예로 들어봅니다. 26 | 27 | 어떻게 시스템을 구축해 두어야 게이머들이 서로의 세이브파일들을 쉽게 업로드 하거나, 바통을 이어 받을 수 있을까요? 28 | 29 | 프로그래밍 프로젝트들은 예전에 중앙 집중식 VCS를 사용하였습니다. 한 개의 서버가 모든 세이브파일을 저장했었지요. 그 서버외에는 아무 것도 그 세이브파일들을 관리할 수 없었습니다. 게임으로 말하자면, 게이머들은 각자의 게임기에 몇 개의 세이브파일들을 가지고 있었고, 게임을 다른 사람으로부터 이어받아 진행하고 싶을 때에는, 모든 세이브파일들이 저장되어있는 중앙서버에서 파일들을 다운로드 받은 후, 게임을 좀 하다가, 다시 다른 게이머들이 진행할 수 있게 그 서버에 업로드 해 놓아야 합니다. 30 | 31 | 만약에 어떤 한 게이머가 예전에 세이브 해두었던 오래된 파일을 불러오고 싶다면 어떻게 될까요? 현재 최신의 세이브 시점은 누군가 게임의 전 단계에서 다음 단계에 필요한 아이템을 주워오지 않아서 아무리 잘 해도 게임을 진행 할수없는 상태로 저장이 되어있을지도 모르고, 그런게 아니라면 그들은 아마도 세이브파일 두 개를 비교하여 한 특정 게이머가 얼마나 진행을 하였는지 알고 싶어할지도 모릅니다. 32 | 33 | 예전 세이브 파일을 불러오고 싶은 이유는 여러가지일 수 있습니다, 그러나 방법은 한 가지일 수 밖에 없지요. 중앙서버에서 불러오는 방법 말입니다. 더 많은 세이브파일을 원할 수록 서버와의 통신이 더 잦아질 수 밖에 없지요. 34 | 35 | (Git을 포함하여) 새로운 세대의 VCS들은 분산 제어를 기본으로 합니다. 예전의 중앙관리 방식의 보편화된 방식이라고 생각하면 되지요. 한 게이머가 서버로부터 (가장 최신) 세이브파일을 받는다해도 그 하나만 받게되는 것이 아니라 모든 예전 버전의 세이브파일까지도 같이 받게 되는 겁니다. 마치 중앙서버를 각자의 컴퓨터에 미러링한다고 보시면 됩니다. 36 | 37 | 그렇기에 처음에는 Git을 셋업할 때 시간이 많이 걸릴 수 있습니다. 특히, 그 세이브파일이 오래되었고, 아주 긴 역사를 가지고 있다면 말이지요. 그러나 이 것은 길게보면 아주 효율적인 방법입니다. 이 방법을 통해 즉시 이득을 볼 수있는 점을 따진다면, 예전 세이브파일을 원할 때 중앙서버와 교신을 하지 않아도 된다는 점이지요. 38 | 39 | === 멍청한 미신 === 40 | 41 | 사람들이 분산 제어 시스템에 대해 일반적으로 오해하는게, 분산 제어 시스템은 공식적인 중앙 저장소가 필요한 프로젝트에는 적합하지 않다고 생각하는 것입니다. 이 것은 말도 안되는 오해이지요. 이 오해는 누군가의 사진을 찍는다는 것은 그 피사체의 영혼을 같이 담아버린다는 말도 안 되는 논리와 같습니다. 다시 말하면, 중앙 저장소의 파일을 카피하여 분산 제어하는 것이 중앙 저장소의 중요성을 훼손한다는 것이 아닙니다. 42 | 43 | 첫번째 이해해야하는 부분이, 중앙 버전 관리 시스템이 할 수 있는 모든 일들은 잘 짜여진 분산 관리 시스템이 더 잘 할수 있다는 것을 인식해야 한다는 것입니다. 네트워크상의 자원들은 기본적으로 로컬상의 자원들보다 시간적으로나 물질적으로 비경제적일 수 밖에 없습니다. 물론, 나중에도 말씀드리겠지만 분산 제어 시스템도 문제점이 없는 시스템은 아닙니다. 그러나 주먹구구식의 생각으로 중앙 관리 시스템과 분산 관리 시스템을 비교하는 일은 없어야 할 것입니다. 다음 인용문이 이것을 대변해 줍니다. 44 | 45 | "규모가 작은 프로젝트들은 시스템의 부분적인 특성만으로도 실행 할 수 있겠지만, 46 | 이런 프로젝트들을 스케일업 할 수 없는 확장성이 낮은 시스템으로 계속 실행하는 것은 마치 47 | 옛 로마숫자를 이용해 계산기를 두드리는 것과 같다." 48 | 49 | 더욱이 당신의 프로젝트는 당신이 처음 생각했던 것보다 더 거대한 일이 될지도 모르는 겁니다. 처음부터 Git을 사용한다는 것은 단순히 병뚜껑을 여는데 스위스아미나이프를 들고 다니는 것과 같은 것입니다. 그러나, 어느 날, 드라이버가 필요할 경우, 당신은 병따개만 들고다니지 않았다는 사실에 안도의 한 숨을 쉬게 될 것입니다. 50 | 51 | === 병합 충돌 === 52 | 53 | 이 주제를 설명하기 위해서는 컴퓨터게임에 비유하는 것은 더 이상 적합하지 않을 수 있습니다. 대신에 여기서는 문서편집에 비유해서 설명드리도록 하죠. 54 | 55 | 다음 예시를 생각해 봅시다. 앨리스(Alice)는 파일을 편집하던 도중에 새로운 줄을 첫 줄로 추가하고, 밥(Bob)은 그 같은 파일의 마지막에 코드 한 줄을 더한다고 가정합시다. 그리고 그들은 편집된 파일을 각자 중앙서버에 업로드 합니다. 대부분의 시스템은 자동으로 두 사람이 각자 한 편집을 받아들이고 병합할 것입니다. 결과적으로는 앨리스와 밥 두 사람의 편집이 모두 한 파일에 적용되겠죠. 56 | 57 | 자 이제 앨리스와 밥이 어떤 파일의 정확히 같은 부분에서 서로 다른 편집을 한다고 가정해 봅시다. 이럴 경우에는 인간의 직접적인 개입없이는 온순한 편집이 불가능 하겠지요? 누가 편집을하던 두번째로 편집하는 사람은 작업을 결합하는 과정에서 오류메세지 ("_merge conflict_")를 볼 수밖에 없겠지요. 이런 오류메세지를 피하기 위해선 한 사람만의 작업을 선택하거나 두 사람의 작업을 아우를 수 있는 새로운 코딩작업을 추가로 해줘야하는 번거로움이 발생하지요. 58 | 59 | 예시보다 더 복잡한 상황이 일어날수도 있습니다. VCS는 간단한 상황들을 알아서 해결해 주고, 어려운 상황은 인간의 손에 맡기지요. 이런 VCS의 행동은 대체적으로 조정가능합니다. 60 | -------------------------------------------------------------------------------- /ko/preface.txt: -------------------------------------------------------------------------------- 1 | = Git Magic = 2 | Ben Lynn 3 | 2007년 8월 4 | 5 | == 서문 == 6 | 7 | http://git-scm.com/[Git] 은 버전 관리계의 스위스아미나이프 정도로 보면 됩니다. 아주 유연하고 믿을 수 있지만 그만큼 배우기는 어려울 수도있는 이 Version Control System을 마스터 해봅시다! 8 | 9 | Arthur C. Clarke는 충분히 발전한 기술은 마술과 같다고 말하였습니다. Git도 마찬가지입니다. 초보자들은 Git이 어떻게 돌아가는지 알 필요가 없으며 Git이라는 간단한 장치가 어떻게 친구들과 적들을 놀라게 하는지만 알면됩니다^^. 10 | 11 | 세부사항들을 설명하는 대신에, 우리는 몇몇 기능들의 대략적인 설명을 하려합니다. 여기에 설명된 기능들을 자주 사용하다 보면 각각의 명령어들이 어떻게 작동하는지 알게 될 것입니다. 그리고 그 명령어들을 적용하여 새로운 일들을 해낼 수 있겠지요. 12 | 13 | .번역판 14 | 15 | - link:/\~blynn/gitmagic/intl/zh_cn/[Simplified Chinese]: by JunJie, Meng and JiangWei. Converted to link:/~blynn/gitmagic/intl/zh_tw/[Traditional Chinese] via +cconv -f UTF8-CN -t UTF8-TW+. 16 | - link:/~blynn/gitmagic/intl/fr/[French]: by Alexandre Garel, Paul Gaborit, and Nicolas Deram. 17 | - link:/~blynn/gitmagic/intl/de/[German]: by Benjamin Bellee and Armin Stebich; also http://gitmagic.lordofbikes.de/[hosted on Armin's website]. 18 | - link:/~blynn/gitmagic/intl/it/[Italian]: by Mattia Rigotti. 19 | - link:/~blynn/gitmagic/intl/ko/ [Korean]: by John J. Han; also https://sites.google.com/site/drinkhanjohn/useful-links/[hosted on John's website]. 20 | - link:/~blynn/gitmagic/intl/pl/[Polish]: by Damian Michna. 21 | - link:/~blynn/gitmagic/intl/pt_br/[Brazilian Portuguese]: by José Inácio Serafini and Leonardo Siqueira Rodrigues. 22 | - link:/~blynn/gitmagic/intl/ru/[Russian]: by Tikhon Tarnavsky, Mikhail Dymskov, and others. 23 | - link:/~blynn/gitmagic/intl/es/[Spanish]: by Rodrigo Toledo and Ariset Llerena Tapia. 24 | - link:/~blynn/gitmagic/intl/uk/[Ukrainian]: by Volodymyr Bodenchuk. 25 | - link:/~blynn/gitmagic/intl/vi/[Vietnamese]: by Trần Ngọc Quân; also http://vnwildman.users.sourceforge.net/gitmagic/[hosted on his website]. 26 | 27 | .그 외의 에디션 28 | 29 | - link:book.html[Single webpage]: CSS 없는 HTML 버전. 30 | - link:book.pdf[PDF file]: 프린팅 버전. 31 | - http://packages.debian.org/gitmagic[Debian package], http://packages.ubuntu.com/gitmagic[Ubuntu package]: 이 웹사이트의 사본. Handy http://csdcf.stanford.edu/status/[when this server is offline]. 32 | - http://www.amazon.com/Git-Magic-Ben-Lynn/dp/1451523343/[Physical book [Amazon.com]]: 64 pages, 15.24cm x 22.86cm, black and white. 전기가 들어오지 않을 때 유용. 33 | 34 | === 고맙습니다! === 35 | 36 | 많은 분들 께서 번역에 힘써주셔서 저는 어떻게 몸둘 바를 모르겠습니다. 이 분들을 통해 37 | 더 많은 독자들을 만날 수 있어서 정말 기쁘고 감사드립니다. 38 | 39 | Dustin Sallings, Alberto Bertogli, James Cameron, Douglas Livingstone, Michael Budde, Richard Albury, Tarmigan, Derek Mahar, Frode Aannevik, Keith Rarick, Andy Somerville, Ralf Recker, Øyvind A. Holm, Miklos Vajna, Sébastien Hinderer, Thomas Miedema, Joe Malin, Tyler Breisacher, Sonia Hamilton, Julian Haagsma, Romain Lespinasse, Sergey Litvinov, Oliver Ferrigni, David Toca, Сергей Сергеев, Joël Thieffry, and Baiju Muthukadan 수정 및 편집에 힘써주셧습니다.. 40 | 41 | François Marier 는 Daniel Baumann이 개발한 Debian 패키지를 관리합니다. 42 | 43 | 44 | 고마워 해야할 사람들이 많지만은 여기에 다 쓸수는 없는 노릇입니다. 45 | 46 | 그래도 만약에 제가 이 웹사이트에 실수로 이름을 개제하지 않았다면 연락을 주시거나 패치를 만들어 주세요! 47 | 48 | === 라이센스 === 49 | 50 | 이 가이드는 http://www.gnu.org/licenses/gpl-3.0.html[the GNU General Public License version 3] 통해 발간되었습니다. 자연스레 소스콛드들은 Git 저장소에 51 | 저장되어있습니다: 52 | 53 | $ git clone git://repo.or.cz/gitmagic.git # Creates "gitmagic" directory. 54 | 55 | 아니면 다음 미러사이트들에도 소스코드가 저장되어 있을겁니다.: 56 | 57 | $ git clone git://github.com/blynn/gitmagic.git 58 | $ git clone git://gitorious.org/gitmagic/mainline.git 59 | $ git clone https://code.google.com/p/gitmagic/ 60 | $ git clone git://git.assembla.com/gitmagic.git 61 | $ git clone git@bitbucket.org:blynn/gitmagic.git 62 | 63 | GitHub, Assembla, Bitbucket은 사적인 저장소를 지지합니다. Assembla와 Bitbucket은 64 | 무료로 제공되고 있습니다. 65 | -------------------------------------------------------------------------------- /ko/translate.txt: -------------------------------------------------------------------------------- 1 | == 부록 B: 이 가이드를 번역하기 == 2 | 3 | 다음 절차들을 따라하셔야 제 프로그램이 자동으로 빠르게 HTML과 PDF 버전의 번역본을 만들수 있습니다. 4 | 5 | 우선 원본이 되는 소스를 클론하시고 폴더를 만드시는데, 폴더명을 IETF에 기재되어 있는 태그를 쓰시기 바랍니다: 6 | 다음 링크에 들어가셔서 확인하세요, 7 | http://www.w3.org/International/articles/language-tags/Overview.en.php[the W3C 8 | article on internationalization]. 예를 들자면, 영어의 태그는 "en"이고, 일본어는 "ja"이며, 국어는 "ko"입니다. 9 | 그리고 새로운 디렉토리에서 "en"에 들어있는 원본 txt를 번역하시면 됩니다. (번역주: 영어를 못하시고 국어를 하실수 있다면 본 가이드를 쓰시면 되겠지만 그럴 확률이 거의 없겠죠) 10 | 11 | 12 | For instance, to translate the guide into http://en.wikipedia.org/wiki/Klingon_language[Klingon], you might type: 13 | 14 | $ git clone git://repo.or.cz/gitmagic.git 15 | $ cd gitmagic 16 | $ mkdir tlh # "tlh" is the IETF language code for Klingon. 17 | $ cd tlh 18 | $ cp ../en/intro.txt . 19 | $ edit intro.txt # Translate the file. 20 | 21 | and so on for each text file. 22 | 23 | Edit the Makefile and add the language code to the `TRANSLATIONS` variable. 24 | You can now review your work incrementally: 25 | 26 | $ make tlh 27 | $ firefox book-tlh/index.html 28 | 29 | Commit your changes often, then let me know when they're ready. 30 | GitHub has an interface that facilitates this: fork the "gitmagic" project, 31 | push your changes, then ask me to merge. 32 | -------------------------------------------------------------------------------- /makeover: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Extract table of contents from index.html and delete preface link. 4 | BOOKDIR=book-$1 5 | TITLE="Git Magic" 6 | case $1 in 7 | ru) 8 | TITLE="Волшебство Git" 9 | ;; 10 | esac 11 | 12 | # Older AsciiDoc versions put newlines in their output. 13 | # To get them to work with the following, first minify the HTML output. 14 | cat $BOOKDIR/index.html \ 15 | | grep -o '
.*' \ 16 | | sed 's!
.*!!' \ 17 | | sed 's!!index.html!g' \ 18 | | sed 's!
  • !
  • '"$TITLE"'
  • &!' \ 19 | > toc.tmp 20 | 21 | # For every file except the index... 22 | for FILE in $BOOKDIR/*.html 23 | do 24 | sed '//a <link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet" type="text/css">' -i $FILE 25 | if [ $FILE != "$BOOKDIR/index.html" ] 26 | then 27 | # Prepend "Git Magic - " to titles of all pages. 28 | sed '/<title>/ s/<title>/&'"$TITLE"' - /' -i $FILE 29 | sed 's/pr01\.html/index.html/g' -i $FILE 30 | # Insert newline after `body` tag. 31 | sed 's/<body[^>]*>/&\n/' -i $FILE 32 | # Paste ToC into beginning and add div section with class content for CSS. 33 | sed '/<body/{r toc.tmp 34 | a <div class="content"> 35 | }' -i $FILE 36 | sed 's!</body>!</div>&!' -i $FILE 37 | fi 38 | done 39 | 40 | # Originally this link was "My Homepage". Since it appears on translations of 41 | # the guide, I changed it to my name so it doesn't have to be translated. 42 | sed '/^<\/body/i </div><div class="footer"><a href="/~blynn/">Ben Lynn</a></div>' -i $BOOKDIR/*.html 43 | 44 | cp $BOOKDIR/pr01.html $BOOKDIR/index.html 45 | rm toc.tmp 46 | -------------------------------------------------------------------------------- /pl/preface.txt: -------------------------------------------------------------------------------- 1 | = Git Magic = 2 | Ben Lynn 3 | Sierpień 2007 4 | 5 | == Przedmowa == 6 | 7 | http://git-scm.com/[Git] to rodzaj scyzoryka szwajcarskiego dla kontroli wersji. To niezawodne, wielostronne narzędzie do kontroli wersji o niezwykłej elastyczności przysprawia trudności już w samym jego poznaniu, nie wspominając o opanowaniu. 8 | 9 | Jak stwierdził Arthur C. Clarke, każda wystarczająco postępowa technologia jest porównywalna z magią. Jest to wspaniałe podejście, by zacząć pracę z Gitem: Początkujący mogą zignorować jego wewnętrzne mechanizmy i ujrzeć jako rzecz, która urzeka przyjaciół swoimi niezwykłymi możliwościami, a przeciwników doprowadza do białej gorączki. 10 | 11 | Zamiast wchodzić w szczegóły, oferujemy proste instrukcje dla osiągnięcia zamierzonych efektów. W miarę regularnego korzystania stopniowo sam zrozumiesz jak każda z tych sztuczek funkcjonuje i jak dopasować podane instrukcje na twoje własne potrzeby. 12 | 13 | .Tłumaczenia 14 | 15 | - link:/\~blynn/gitmagic/intl/zh_cn/[Chiński uproszczony]: od JunJie, Meng i JiangWei. Konwertacja do link:/~blynn/gitmagic/intl/zh_tw/[Tradycjonalnego chińskiego] za pomocą +cconv -f UTF8-CN -t UTF8-TW+. 16 | - link:/~blynn/gitmagic/intl/fr/[Francuski]: od Alexandre Garel, Paul Gaborit, i Nicolas Deram. 17 | - link:/~blynn/gitmagic/intl/de/[Niemiecki]: od Benjamin Bellee i Armin Stebich; również hostowany na http://gitmagic.lordofbikes.de/[stronie Armina]. 18 | - http://www.slideshare.net/slide_user/magia-git[Portugalski]: od Leonardo Siqueira Rodrigues [http://www.slideshare.net/slide_user/magia-git-verso-odt[wersja ODT]]. 19 | - link:/~blynn/gitmagic/intl/ru/[Rosyjski]: od Tikhon Tarnavsky, Mikhail Dymskov, i innych. 20 | - link:/~blynn/gitmagic/intl/es/[Hiszpański]: od Rodrigo Toledo i Ariset Llerena Tapia. 21 | - link:/~blynn/gitmagic/intl/uk/[Ukraiński]: od Volodymyr Bodenchuk. 22 | - link:/~blynn/gitmagic/intl/vi/[Wietnamski]: od Trần Ngọc Quân; również hostowany http://vnwildman.users.sourceforge.net/gitmagic/[na tej stronie]. 23 | 24 | .Inne wydania 25 | 26 | - link:book.html[Jako jedna strona]: uszczuplone HTML, bez CSS. 27 | - link:book.pdf[Wersja PDF]: przyjazna w druku. 28 | - http://packages.debian.org/gitmagic[Pakiet Debiana], http://packages.ubuntu.com/gitmagic[Pakiet Ubuntu]: Pobiera szybką i lokalną kopię tej strony. Przydatne http://csdcf.stanford.edu/status/[gdyby ten serwer był offline]. 29 | - http://www.amazon.com/Git-Magic-Ben-Lynn/dp/1451523343/[Drukowane wydanie [Amazon.com]]: 64 strony, 15.24cm x 22.86cm, czarno-biały. Przyda się, gdy zabraknie prądu. 30 | 31 | 32 | === Podziękowania! === 33 | 34 | Jestem mile zaskoczony, że tak dużo ludzi pracowało nad przetłumaczeniem tych stron. Bardzo cenię, iż dzięki staraniom wyżej wspomnianych osób otrzymałem możliwość dotarcia do większego grona czytelników. 35 | 36 | Dustin Sallings, Alberto Bertogli, James Cameron, Douglas Livingstone, Michael Budde, Richard Albury, Tarmigan, Derek Mahar, Frode Aannevik, Keith Rarick, Andy Somerville, Ralf Recker, Øyvind A. Holm, Miklos Vajna, Sébastien Hinderer, Thomas Miedema, Joe Malin, i Tyler Breisacher przyczynilli się do poprawek i korektur. 37 | 38 | François Marier jest mentorem pakietu Debiana, który uprzednio utworzony został przez Daniela Baumann. 39 | 40 | Chciałbym podziękować również wszystkim innym za ich pomoc i dobre słowo. Chciałbym tu wszystkich wyszczególnić, mogłoby to jednak wzbudzić oczekiwania w szerokim zakresie. 41 | 42 | Gdybym o tobie przypadkowo zapomniał, daj mi znać albo przyślij mi po prostu patch. 43 | 44 | === Licencja === 45 | 46 | Ten poradnik publikowany jest na bazie licencji http://www.gnu.org/licenses/gpl-3.0.html[GNU General Public License Version 3]. Oczywiście, tekst źródłowy znajduje się w repozytorium Git i może zostać pobrany przez: 47 | 48 | $ git clone git://repo.or.cz/gitmagic.git # Utworzy katalog "gitmagic". 49 | 50 | albo z serwerów lustrzanych: 51 | 52 | $ git clone git://github.com/blynn/gitmagic.git 53 | $ git clone git://gitorious.org/gitmagic/mainline.git 54 | $ git clone https://code.google.com/p/gitmagic/ 55 | $ git clone git://git.assembla.com/gitmagic.git 56 | $ git clone git@bitbucket.org:blynn/gitmagic.git 57 | 58 | GitHub, Assembla, i Bitbucket pozwalają na prowadzenie prywatnych repozytoriów, te dwa ostatnie za darmo. 59 | -------------------------------------------------------------------------------- /pl/translate.txt: -------------------------------------------------------------------------------- 1 | == Załącznik B: Przetłumaczyć to HOWTO == 2 | 3 | Aby przetłumaczyć moje HOWTO polecam wykonanie następujących poniżej kroków, wtedy moje skrypty będą w prosty sposób mogły wygenerować wersje HTML i PDF. Poza tym wszystkie tłumaczenia mogą być prowadzone w jednym repozytorium. 4 | 5 | Sklonuj teksty źródłowe, następnie utwórz katalog o nazwie skrótu IETF przetłumaczonego języka: sprawdź http://www.w3.org/International/articles/language-tags/Overview.en.php[Artykuł W3C o internacjonalizacji]. Na przykład, angielski to "en", a japoński to "ja". Skopiuj wszystkie pliki +txt+ z katalogu "en" do nowo utworzonego katalogu. 6 | 7 | Aby przykładowo przetłumaczyć to HOWTO na http://de.wikipedia.org/wiki/Klingonische_Sprache[Klingonisch], musisz wykonać następujące polecenia: 8 | 9 | $ git clone git://repo.or.cz/gitmagic.git 10 | $ cd gitmagic 11 | $ mkdir tlh # "tlh" jest skrótem IETF języka Klingonisch. 12 | $ cd tlh $ cp ../en/intro.txt . 13 | $ edit intro.txt # Przetłumacz ten plik. 14 | 15 | i zrób to z każdą następną daną textową. 16 | 17 | Edytuj Makefile i dodaj skrót języka do zmiennej `TRANSLATIONS`. Teraz możesz swoją pracę w każdej chwili sprawdzić: 18 | 19 | $ make tlh $ firefox book-tlh/index.html 20 | 21 | Używaj często 'commit' a gdy już skończysz, to daj znać. GitHub posiada interfejs, który to ułatwi: utwórz twój własny 'Fork' projektu "gitmagic", 'push' twoje zmiany i daj mi znać, by można było wykonać operację 'merge'. 22 | -------------------------------------------------------------------------------- /po4gitmagic/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile to genereate everything needed for a translation of git-magic using po4a 2 | 3 | SHELL := /bin/bash 4 | 5 | # the possible targets 6 | # 7 | # clean - remove the folder $(POTDIR) and all the .txt files 8 | # gettext - create the folder $(POTDIR) and generate the .po files in there 9 | # translate - create the .txt files from the translated .po files 10 | # for success you must have translated already 80% of a .po file 11 | # update - update the .po files in case the originals has changed 12 | # changed items are marked 'fuzzy' in the .po file to fin them easy 13 | 14 | .PHONY: clean gettext translate update 15 | 16 | # the path to the english original .txt files 17 | ORGDIR := ../en 18 | 19 | # the folder where the .po files will be created 20 | POTDIR := pot 21 | 22 | # the filenames for the .txt and .po files 23 | # must be identical to the english original .txt files 24 | FILES := preface intro basic clone branch history multiplayer grandmaster secrets drawbacks translate 25 | # add the .txt suffix to the filenames for a list of .txt files 26 | TXTFILES := $(addsuffix .txt, $(FILES)) 27 | # add the .po suffix to the filenames for a list of .po files 28 | POTFILES := $(addsuffix .po, $(FILES)) 29 | 30 | # prerequisites for gettext are the .po files 31 | gettext: $(addprefix $(POTDIR)/,$(POTFILES)) 32 | 33 | # prerequisites for translate are the .txt files 34 | translate: $(TXTFILES) 35 | 36 | # no prerequisites to update the translated .po files when the english original .txt has changed 37 | update: 38 | ( for FILE in $(FILES) ; \ 39 | do if [ -f $(ORGDIR)/$$FILE.txt ]; \ 40 | then po4a-updatepo -f text -m $(ORGDIR)/$$FILE.txt -M UTF-8 -p $(POTDIR)/$$FILE.po; echo $$FILE; \ 41 | fi; \ 42 | done ) 43 | 44 | # remove all .po and .txt files 45 | clean: 46 | -rm -rf $(POTDIR) 47 | -rm -rf *.txt 48 | 49 | # prerequisites for the .po files is the existance of the pot folder 50 | $(POTFILES) : | $(POTDIR) 51 | 52 | # create the folder for the .po files 53 | $(POTDIR) : 54 | -mkdir $(POTDIR) 55 | 56 | # rule how to make the .po files from the english original .txt file 57 | $(POTDIR)/%.po : $(ORGDIR)/%.txt 58 | po4a-gettextize -f text -m $< -p $@ -M UTF-8 59 | 60 | # rule how to make the translatets .txt files from the translated .po files 61 | %.txt : $(POTDIR)/%.po 62 | po4a-translate -f text -m ../en/$@ -p $< -M UTF-8 -l $@ 63 | -------------------------------------------------------------------------------- /po4gitmagic/README: -------------------------------------------------------------------------------- 1 | This Makefile should make it easy to translate gitmagic with gettext tools on Linux systems. 2 | To use it, you have to install the po4a package. 3 | 4 | To start, clone the gitmagic project. 5 | 6 | Make the directory corresponding to your language tag and change into it. 7 | mkdir xx 8 | chdir xx 9 | 10 | Create a symlink to this Makefile: 11 | ln -s ../po4gitmagic/Makefile Makefile 12 | 13 | Now run make to create the pot folder and all the .po files in there. 14 | make gettext 15 | 16 | Start translating with your prefered .po file editor (e.g. poedit, gtranslator). 17 | 18 | You need to have 80% of a .po file translated, then you can run: 19 | make translate 20 | 21 | This will create a translated .txt file in your language folder for each .po file that is more than 80% translated. 22 | 23 | To proof your work change in the gitmagic root folder, run: 24 | make xx 25 | where xx is the subdirectory name. 26 | 27 | If something in the original .txt files changed, goto your language folder and run: 28 | make update 29 | 30 | This will update your .po files and mark the changed items as 'fuzzy'. 31 | 32 | Check the .po files for changes, translate them and run again: 33 | make translate 34 | -------------------------------------------------------------------------------- /pt_br/intro.txt: -------------------------------------------------------------------------------- 1 | == Introdução == 2 | 3 | Usaremos uma analogia para falar sobre controle de versões. Veja http://en.wikipedia.org/wiki/Revision_control[o verbete Sistema de Controle de Versões] para uma explicação mais formal. 4 | 5 | === Trabalhar é Divertido === 6 | 7 | Divirto-me com jogos para computador quase a minha vida toda. Em contrapartida, só comecei a usar sistemas de controle de versões quando adulto. Suspeito que não fui o único, e comparar os dois pode tornar estes conceitos mais fáceis de explicar e entender. 8 | 9 | Pense na edição de seu código, documento, ou qualquer outra coisa, como jogar um jogo. Uma vez que tenha feito muitos progressos, e gostaria de de salvá-los. Para isso, você clica em “Salvar” no seu editor preferido. 10 | 11 | Porém, isto vai sobrescrever a versão anterior. É como nos antigos jogos onde você só tinha uma espaço para salvar: você pode salvar, mas nunca mais poderá voltar a um estado salvo anteriormente. O que é um pena, pois o estado anterior era uma parte muito divertida do jogo e você gostaria de poder revisitá-lo outra hora. Ou pior, o último estado salvo é dificílimo e você terá que recomeçar. 12 | 13 | === Controle de Versões === 14 | 15 | Ao editar, você pode “Salvar como ...” num arquivo diferente, ou copiar o arquivo antes de sobrescrevê-lo se você quiser manter as versões anteriores. Pode também comprimí-los para economizar espaço. Isto é uma forma rudimentar e muito trabalhosa de controle de versões. Jogos de computador aperfeiçoaram este método, muitos deles acrescentam automaticamente a data e a hora aos estados salvos. 16 | 17 | Vamos dificultar um pouco. Digamos que são um monte de arquivos juntos, como os fontes do seu projeto, ou arquivos para um website. Agora se quiser manter suas versões anteriores, terá que arquivar todo um diretório ou vários. Manter muitas versões na mão é inconveniente e rapidamente se tornará caro. 18 | 19 | Em alguns jogos de computador, um estado salvo consiste de um diretório cheio de arquivos. Estes jogos escondem estes detalhes do jogador e lhe apresentam uma interface conveniente para gerenciar as diferentes versões neste diretório. 20 | 21 | Sistemas de controle de versões não são diferentes. Todos têm uma boa interface para gerenciar seu diretório de versões. Você pode salvar o diretório sempre que desejar, e pode rever qualquer um dos estados salvos quando quiser. Ao contrário da maioria dos jogos de computador, eles são geralmente mais espertos na economia de espaço. Normalmente, apenas uns poucos arquivos mudam de versão para versão, e com poucas diferenças. Armazenar as diferenças, ao invés de todos os arquivos, economiza espaço. 22 | 23 | === Controle distribuído === 24 | 25 | Agora imagine um jogo de computador muito difícil. Tão difícil de terminar que vários jogadores experientes pelo mundo decidem formar uma equipe e compartilhar seus estados salvos do jogo para tentar vencê-lo. Speedruns são exemplos reais: jogadores especializados em diferentes níveis do mesmo jogo colaboram na produção de resultados incríveis. 26 | 27 | Como você configura um sistema para que todos possam obter facilmente o que os outros salvarem? E salvar novos estados? 28 | 29 | Nos velhos tempos, todos os projetos utilizavam um controle de versões centralizado. Um servidor em algum lugar mantinha os jogos salvos. Ninguém mais teria todos os jogos. Cada jogador mantinha apenas alguns jogos salvos em suas maquinas. Quando algum jogador quiser avançar no jogo, ele pega o ultimo jogo salvo do servidor, joga um pouco, salva e manda de volta para o servidor para que os outros possam usar. 30 | 31 | E se um jogador quiser pegar um jogo antigo salvo por algum motivo? Talvez o jogo atual salvo esteja em um nível impossível de jogar devido alguém ter esquecido um objeto três níveis atrás, e é preciso encontrar o último jogo salvo que está em um nível que pode ser completado com sucesso. Ou talvez queira comparar dois jogos salvos para saber o quanto um jogador avançou. 32 | 33 | Podem existir vários motivos para ver uma versão antiga, mas o modus operandi é o mesmo. Têm que solicitar ao servidor centralizado a versão antiga. E quanto mais jogos salvos forem necessários, maior é o tráfego de informação. 34 | 35 | A nova geração de sistemas de controle de versões, dentre eles o Git, é conhecida como sistemas distribuídos, e pode ser pensada como uma generalização dos sistemas centralizados. Quando os jogadores baixam do servidor principal, eles recebem todos os jogos salvos, e não apenas o mais recente. É como se estivessem espelhando o servidor principal. 36 | 37 | A primeira operação de clonagem pode ser bem demorada, especialmente se há um longo histórico, mas é compensada no longo prazo. Um benefício imediato é que, se por qualquer razão desejar uma antiga versão, o trafego de informação com o servidor é desnecessário. 38 | 39 | === Uma superstição === 40 | 41 | Um equívoco popular é que sistemas distribuídos estão mal adaptados a projetos que exijam um repositório central oficial. Nada poderia estar mais longe da verdade. Fotografar alguém não irá roubar a sua alma. Igualmente, clonar o repositório master não diminui sua importância. 42 | 43 | Uma boa comparação inicial é: qualquer coisa que um sistema centralizado de controle de versões faz, um sistema distribuído de controle de versões bem concebido pode fazer melhor. Recursos de rede são simplesmente mais onerosos que recursos locais. Embora vejamos mais adiante que existem inconvenientes numa abordagem distribuída, é menos provável que alguém faça comparações errôneas com esta regra de ouro. 44 | 45 | Um pequeno projeto pode precisar de apenas uma fração dos recursos oferecidos pelo sistema, mas utilizar um sistema que não permite expansão é como utilizar os algarismos romanos quando calculamos com números pequenos. 46 | 47 | E mais, seu projeto pode crescer além da suas expectativas. Usando Git, desde o inicio é como ter um canivete suíço, embora o use na maioria das vezes para abrir garrafas. No dia que necessitar, desesperadamente, de uma chave de fenda você agradecerá por ter mais do que um abridor de garrafas. 48 | 49 | === Conflitos de mesclagem (Merge) === 50 | 51 | Neste tópico, nossa analogia com jogos de computador torna-se ruim. Em vez disso, vamos considerar novamente a edição de um documento. 52 | 53 | Suponha que Alice insira uma linha no início do arquivo, e Bob uma no final. Ambos enviam suas alterações. A maioria dos sistemas irá de maneira automática e reativa deduzir o plano de ação: aceitando e mesclando as mudanças, assim as alterações de Alice e Bob serão aplicadas. 54 | 55 | Agora suponha que ambos, Alice e Bob, façam alterações distintas na mesma linha. Tornando impossível resolver o conflito sem intervenção humana. A segunda pessoa, entre Alice e Bob, que enviar suas alterações será informado do conflito, e escolherá se aplica sua alteração sobre a do outro, ou revisa a linha para manter ambas as alterações. 56 | 57 | Situações muito mais complexas podem surgir. Sistemas de controle de versões são capazes de resolver os casos mais simples, e deixar os casos mais difíceis para nós resolvermos. Normalmente seu comportamento é configurável. 58 | -------------------------------------------------------------------------------- /pt_br/preface.txt: -------------------------------------------------------------------------------- 1 | = Magia Git = 2 | Ben Lynn 3 | Agosto 2007 4 | 5 | == Prefácio == 6 | 7 | http://git-scm.com/[Git] é um canivete suíço do controle de versões. Uma ferramenta polivalente realmente versátil, cuja extraordinária flexibilidade torna-o complicado de aprender, principalmente sozinho. 8 | 9 | Como Arthur C. Clarke observou, "Qualquer tecnologia suficientemente avançada é considerada mágica”. Esta é uma ótima forma de abordar o Git: novatos podem ignorar seu funcionamento interno e vê-lo como algo divertido que pode agradar aos amigos e enfurecer os inimigos com suas maravilhosas habilidades. 10 | 11 | Ao invés de entrar em detalhes, forneceremos apenas instruções para casos específicos. Após o uso repetido, você gradualmente entenderá como cada truque funciona, e como adaptar as receitas às suas necessidades. 12 | 13 | .Traduções 14 | 15 | - link:/\~blynn/gitmagic/intl/zh_cn/[Simplified Chinese]: by JunJie, Meng and JiangWei. Converted to link:/~blynn/gitmagic/intl/zh_tw/[Traditional Chinese] via +cconv -f UTF8-CN -t UTF8-TW+. 16 | - link:/~blynn/gitmagic/intl/fr/[French]: by Alexandre Garel, Paul Gaborit, and Nicolas Deram. 17 | - link:/~blynn/gitmagic/intl/de/[German]: by Benjamin Bellee and Armin Stebich; also http://gitmagic.lordofbikes.de/[hosted on Armin's website]. 18 | - link:/~blynn/gitmagic/intl/pt-BR/[Portuguese-Brazilian]: by J.I.Serafini and Leonardo Siqueira Rodrigues. 19 | - link:/~blynn/gitmagic/intl/ru/[Russian]: by Tikhon Tarnavsky, Mikhail Dymskov, and others. 20 | - link:/~blynn/gitmagic/intl/es/[Spanish]: by Rodrigo Toledo and Ariset Llerena Tapia. 21 | - link:/~blynn/gitmagic/intl/uk/[Ukrainian]: by Volodymyr Bodenchuk. 22 | - link:/~blynn/gitmagic/intl/vi/[Vietnamese]: by Trần Ngọc Quân; also http://vnwildman.users.sourceforge.net/gitmagic/[hosted on his website]. 23 | 24 | .Outras Edições 25 | 26 | - link:book.html[Single webpage]: barebones HTML, with no CSS. 27 | - link:book.pdf[PDF file]: printer-friendly. 28 | - http://packages.debian.org/gitmagic[Debian package], http://packages.ubuntu.com/gitmagic[Ubuntu package]: get a fast and local copy of this site. Handy http://csdcf.stanford.edu/status/[when this server is offline]. 29 | - http://www.amazon.com/Git-Magic-Ben-Lynn/dp/1451523343/[Physical book [Amazon.com]]: 64 pages, 15.24cm x 22.86cm, black and white. Handy when there is no electricity. 30 | 31 | === Agradecimentos! === 32 | 33 | É com grande orgulho que vejo o grande número de pessoas que trabalho na tradução deste livro. Eu realmente agradeço pela grande audiência permitida pelos esforços dos tradutores citados a seguir. 34 | 35 | Dustin Sallings, Alberto Bertogli, James Cameron, Douglas Livingstone, Michael Budde, Richard Albury, Tarmigan, Derek Mahar, Frode Aannevik, Keith Rarick, Andy Somerville, Ralf Recker, Øyvind A. Holm, Miklos Vajna, Sébastien Hinderer, Thomas Miedema, Joe Malin, Tyler Breisacher, Sonia Hamilton, Julian Haagsma, Romain Lespinasse, Sergey Litvinov, Oliver Ferrigni, David Toca, Сергей Сергеев, Joël Thieffry, e Baiju Muthukadan contribuiram com correções e melhorias. 36 | 37 | François Marier mantém o pacote Debian criado originalmente por Daniel Baumann. 38 | 39 | 40 | My gratitude goes to many others for your support and praise. I'm tempted to 41 | quote you here, but it might raise expectations to ridiculous heights. 42 | 43 | If I've left you out by mistake, please tell me or just send me a patch! 44 | 45 | === Licença === 46 | 47 | Este guia é regido pelos termos da http://www.gnu.org/licenses/gpl-3.0.html[a Licença Publica Geral GNU Versão 3]. Naturalmente, os fontes estão num repositório Git, e podem ser obtido digitando: 48 | 49 | $ git clone git://repo.or.cz/gitmagic.git # Cria um diretório "gitmagic". 50 | 51 | ou a partir de algum desses mirrors: 52 | 53 | $ git clone git://github.com/blynn/gitmagic.git 54 | $ git clone git://gitorious.org/gitmagic/mainline.git 55 | $ git clone https://code.google.com/p/gitmagic/ 56 | $ git clone git://git.assembla.com/gitmagic.git 57 | $ git clone git@bitbucket.org:blynn/gitmagic.git 58 | 59 | GitHub, Assembla, e Bitbucket suportam repositórios privados, os dois últimos são grátis. 60 | -------------------------------------------------------------------------------- /pt_br/translate.txt: -------------------------------------------------------------------------------- 1 | == Apendice B: Traduzindo esse guia == 2 | 3 | Recomendo os seguintes passos para a tradução desse guia, de modo que meus scripts produzam a versão HTML e PDF, e que todas as traduções possam conviver em um mesmo repositório. 4 | 5 | Faça um clone do fonte, e então crie um diretório correspondente a tag IETF da idioma alvo: veja 6 | http://www.w3.org/International/articles/language-tags/Overview.en.php[o artigo da W3C sobre internacionalização]. Por exemplo, Ingles (English) é "en" e Japonês é "ja". No novo diretório, traduza os arquivos .txt a partir do subdiretorio "en". 7 | 8 | Por exemplo, para traduzir este guia para a língua http://en.wikipedia.org/wiki/Klingon_language[Klingon], você deve digitar: 9 | 10 | $ git clone git://repo.or.cz/gitmagic.git 11 | $ cd gitmagic 12 | $ mkdir tlh # "tlh" is the IETF language code for Klingon. 13 | $ cd tlh 14 | $ cp ../en/intro.txt . 15 | $ edit intro.txt # Translate the file. 16 | 17 | e assim por diante, para cada arquivo .txt 18 | 19 | Edite o Makefile e adicione o código do idioma na variável `TRANSLATIONS`. Você poderá então rever seu trabalho de forma incremental: 20 | 21 | $ make tlh 22 | $ firefox book-tlh/index.html 23 | 24 | Faça frequentes commits de suas alterações, e me avise quando o trabalho estiver pronto. O GitHub tem uma interface que facilita isso: faça um fork do projeto "gitmagic", faça um push de suas alterações, e então me peça para fazer um merge. 25 | -------------------------------------------------------------------------------- /ru/preface.txt: -------------------------------------------------------------------------------- 1 | = Волшебство Git = 2 | Ben Lynn 3 | Август 2007 4 | 5 | == От редактора перевода == 6 | 7 | Не буду долго вас задерживать перед интересным чтением, лишь дам небольшие пояснения по переводу терминологии. 8 | 9 | Приводя текст к единому стилю, я старался в первую очередь сохранить его цельность и легкость восприятия, а уже затем следовать чистоте языка. Поэтому на русский переведены лишь устоявшиеся термины; в тех случаях, когда общепринятого русского слова нет, была оставлена калька с английского. Например, используется слово «каталог» вместо «директория»; «хранилище» вместо «репозиторий» или «репозитарий»; «слияние» вместо «мерж»; и «ветка» вместо «бранч». Обратные примеры: «коммит», а не «фиксация»; «хук», а не «крюк»; «патч», а не «заплатка». Единственное исключение сделано для фразы «буферная зона» вместо «область стейджинг» и, соответственно, слова «буфер» вместо «стейдж»: поскольку здесь уже не только перевод, но и калька не есть общеупотребительные термины, то лучше было попытаться объяснить смысл понятия. 10 | 11 | Надеюсь, эти краткие пояснения не оставят для вас неровностей в переводе и позволят погрузиться в текст книги без помех. Приятного чтения. 12 | 13 | == Предисловие == 14 | 15 | http://git.or.cz/[Git] это швейцарский нож управления версиями — надежный универсальный многоцелевой инструмент, чья черезвычайная гибкость делает его сложным в изучении даже для многих профессионалов. 16 | 17 | Как говорил Артур Кларк, любая достаточно развитая технология неотличима от волшебства. Это отличный подход к Git: новички могут игнорировать принципы его внутренней работы и рассматривать Git как нечто восхищающее друзей и приводящее в бешенство врагов своими чудесными способностями. 18 | 19 | Вместо того, чтобы вдаваться в подробности, мы предоставим приблизительные инструкции для получения конкретных результатов. При частом использовании вы постепенно поймете, как работает каждый трюк и как приспосабливать рецепты под ваши нужды. 20 | 21 | .Переводы 22 | 23 | - link:/~blynn/gitmagic/intl/zh_cn/[Китайский (упрощенный)]: JunJie, Meng и JiangWei. 24 | - link:/~blynn/gitmagic/intl/es/[Испанский]: Rodrigo Toledo. 25 | - link:/~blynn/gitmagic/intl/de/[Немецкий]: Benjamin Bellee и Armin Stebich. Armin также разместил http://gitmagic.lordofbikes.de/[немецкий перевод на его сайте]. 26 | - link:/~blynn/gitmagic/intl/ru/[Русский]: Тихон Тарнавский, Михаил Дымсков и другие. 27 | - link:/~blynn/gitmagic/intl/uk/[Украинский]: Владимир Боденчук. 28 | - link:/~blynn/gitmagic/intl/fr/[Французский]: Alexandre Garel. 29 | - http://www.slideshare.net/slide_user/magia-git[Португальский]: Leonardo Siqueira Rodrigues [http://www.slideshare.net/slide_user/magia-git-verso-odt[в формате ODT]]. 30 | 31 | .Другие варианты 32 | 33 | - link:book.html[HTML одной страницей]: чистый HTML без CSS. 34 | - link:book.pdf[PDF файл]: для печати. 35 | - http://packages.debian.org/gitmagic[Пакет Debian], http://packages.ubuntu.com/gitmagic[пакет Ubuntu]: получите локальную копию этого сайта. Придется кстати, http://csdcf.stanford.edu/status/[если этот сервер будет недоступен]. 36 | 37 | === Благодарности === 38 | 39 | Я очень ценю, что столь многие люди работали над переводами этих строк. Я благодарен названным выше людям за их усилия, расширившие мою аудиторию. 40 | 41 | Dustin Sallings, Alberto Bertogli, James Cameron, Douglas Livingstone, Michael Budde, Richard Albury, Tarmigan, Derek Mahar, Frode Aannevik, Keith Rarick, Andy Somerville, Ralf Recker, Øyvind A. Holm, Miklos Vajna, Sébastien Hinderer, Thomas Miedema, Joe Malin и Tyler Breisacher содействовали в правках и доработках. 42 | 43 | François Marier сопровождает пакет Debian, изначально созданный Daniel Baumann. 44 | 45 | Мои благодарности остальным за вашу поддержку и похвалы. Мне очень хотелось процитировать вас здесь, но это могло бы возвысить ваше тщеславие до невообразимых высот. 46 | 47 | Если я случайно забыл упомянуть вас, пожалуйста, напомните мне или просто вышлите патч. 48 | 49 | .Бесплатные хостинги Git 50 | 51 | - http://repo.or.cz/[http://repo.or.cz/] хостинг свободных проектов. Первый сайт Git-хостинга. Основан и поддерживается одним из первых разработчиков Git. 52 | - http://gitorious.org/[http://gitorious.org/] другой сайт Git-хостинга, нацеленный на проекты с открытым кодом. 53 | - http://github.com/[http://github.com/] хостинг для проектов с открытым кодом; а также для закрытых проектов (на платной основе). 54 | 55 | Большое спасибо каждому из этих сайтов за размещение этого руководства. 56 | 57 | === Лицензия === 58 | 59 | Это руководство выпущено под http://www.gnu.org/licenses/gpl-3.0.html[GNU General Public License 3-й версии]. Естественно, исходный текст находится в хранилище Git и может быть получен командой: 60 | 61 | $ git clone git://repo.or.cz/gitmagic.git # Создаст каталог "gitmagic". 62 | 63 | или с одного из зеркал: 64 | 65 | $ git clone git://github.com/blynn/gitmagic.git 66 | $ git clone git://gitorious.org/gitmagic/mainline.git 67 | -------------------------------------------------------------------------------- /ru/translate.txt: -------------------------------------------------------------------------------- 1 | == Приложение B: Перевод этого руководства == 2 | 3 | Я советую следующий способ для перевода этого руководства, чтобы мои скрипты могли быстро создавать HTML и PDF версии, а все переводы находились в одном хранилище. 4 | 5 | Клонируйте исходные тексты, затем создайте каталог, отвечающий тегу IETF целевого языка: смотрите 6 | http://www.w3.org/International/articles/language-tags/Overview.en.php[статью W3C по интернационализации]. К примеру, английский язык это «en», а японский — «ja». Скопируйте в каталог файлы +txt+ из каталога «en» и переведите их. 7 | 8 | К примеру, для перевода руководства на http://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B8%D0%BD%D0%B3%D0%BE%D0%BD%D1%81%D0%BA%D0%B8%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA[клингонский язык], вы можете набрать: 9 | 10 | $ git clone git://repo.or.cz/gitmagic.git 11 | $ cd gitmagic 12 | $ mkdir tlh # «tlh» — языковой код IETF клингонского языка. 13 | $ cd tlh 14 | $ cp ../en/intro.txt . 15 | $ edit intro.txt # Переведите файл. 16 | 17 | и так с каждым файлом. 18 | 19 | Отредактируйте Makefile и добавьте код языка в переменную TRANSLATIONS. Теперь вы сможете просматривать вашу работу по ходу дела: 20 | 21 | $ make tlh 22 | $ firefox book.html 23 | 24 | Почаще делайте коммиты, а когда ваш перевод будет готов, сообщите мне об этом. На GitHub есть веб-интерфейс, облегчающий описанные действия: сделайте форк проекта «gitmagic», залейте ваши изменения и попросите меня сделать слияние. 25 | -------------------------------------------------------------------------------- /uk/intro.txt: -------------------------------------------------------------------------------- 1 | == Вступне слово == 2 | 3 | Щоб пояснити, що таке керування версіями, я буду використовувати аналогії. Якщо потрібно більш точне пояснення, зверніться до http://uk.wikipedia.org/wiki/Система_керування_версіями[статті вікіпедії]. 4 | 5 | === Робота – це гра === 6 | 7 | Я грав в комп’ютерні ігри майже все своє життя. А ось використовувати системи керування версіями почав вже будучи дорослим. Вважаю, я такий не один, і порівняння цих двох занять може допомогти поясненню і розумінню концепції. 8 | 9 | Уявіть, що редагування коду або документа – гра. Просунувшись далеко, ви захочете зберегтися. Для цього ви натиснете на кнопку „Зберегти“ у вашому улюбленому редакторі. 10 | 11 | Але це перезапише стару версію. Це як в стародавніх іграх, де був тільки один слот для збереження: звичайно, ви можете зберегтися, але ви більше ніколи не зможете повернутися до попереднього стану. Це прикро, оскільки попереднє збереження могло вказувати на одне з дуже цікавих місць у грі і, можливо, одного разу ви захочете повернутися до нього. Або, що ще гірше, ви зараз перебуваєте у безвиграшному становищі і змушені починати заново. 12 | 13 | === Керування версіями === 14 | 15 | Під час редагування ви можете „Зберегти як ...“ в інший файл або скопіювати файл куди-небудь перед збереженням, щоб уберегти більш старі версії. Можливо, заархівувавши їх для економії місця на диску. Це найпримітивніший вид керування версіями, до того ж він вимагає інтенсивної ручної роботи. Комп'ютерні ігри пройшли цей етап давно, у більшості з них є безліч слотів для збереження з автоматичними тимчасовими мітками. 16 | 17 | Давайте трохи ускладнимо умови. Нехай у вас є кілька файлів, використовуваних разом, наприклад, вихідний код проекту або файли для вебсайту. Тепер, щоб зберегти стару версію, ви повинні скопіювати весь каталог. Підтримка безлічі таких версій вручну незручна і швидко стає дорогим задоволенням. 18 | 19 | У деяких іграх збереження – це і є каталог з купою файлів всередині. Ігри приховують деталі від гравця і надають зручний інтерфейс для керування різними версіями цього каталогу. 20 | 21 | У системах керування версіями все точно так само. У всіх них є приємний інтерфейс для керування каталогом з вашим скарбом. Можете зберігати стан каталога так часто, як забажаєте, а потім відновити будь-яку з попередніх збережених версій. Але, на відміну від комп'ютерних ігор, вони істотно економлять дисковий простір. Зазвичай від версії до версії змінюється тільки кілька файлів і то ненабагато. Зберігання лише відмінностей замість повних копій потребує менше місця. 22 | 23 | === Розподілене керування === 24 | 25 | А тепер уявіть дуже складну комп’ютерну гру. Її настільки складно пройти, що безліч досвідчених гравців по всьому світу вирішили об'єднатися і використовувати загальні збереження, щоб спробувати виграти. Проходження на швидкість — живий приклад. Гравці, що спеціалізуються на різних рівнях гри, об’єднуються, щоб в результаті отримати приголомшливий результат. 26 | 27 | Як би ви організували таку систему, щоб гравці змогли легко отримувати збереження інших? А завантажувати свої? 28 | 29 | У минулі часи кожен проект використовував централізоване керування версіями. Який-небудь сервер зберігав всі збережені ігри. І ніхто більше. Кожен тримав лише кілька збережень на своїй машині. Коли гравець хотів пройти трохи далі, він завантажував останнє збереження з головного сервера, грав небагато, зберігався і вивантажував вже своє збереження назад на сервер, щоб інші могли ним скористатися. 30 | 31 | А що якщо гравець з якоїсь причини захотів використовувати більш стару збережену гру? Можливо, нинішнє збереження безвиграшне, бо хтось забув взяти якийсь ігровий предмет ще на третьому рівні, і потрібно знайти останнє збереження, де гру все ще можна закінчити. Або, можливо, хочеться порівняти дві більш старі збережені гри, щоб встановити внесок конкретного гравця. 32 | 33 | Може бути багато причин повернутися до більш старої версії, але вихід один: потрібно запросити ту стару збережену гру у центрального сервера. Чим більше збережених ігор потрібно, тим більше знадобиться зв’язуватися з сервером. 34 | 35 | Системи керування версіями нового покоління, до яких відноситься Git, відомі як розподілені системи, їх можна розуміти як узагальнення централізованих систем. Коли гравці завантажуються з головного сервера, вони отримують кожну збережену гру, а не тільки останню. Вони як би дзеркалюють центральний сервер. 36 | 37 | Ці початкові операції клонування можуть бути ресурсоємними, особливо при довгій історії, але сповна окупаються при тривалій роботі. Найбільш очевидна пряма вигода полягає в тому, що якщо вам навіщось потрібна більш стара версія, взаємодія з сервером не знадобиться. 38 | 39 | === Дурні забобони === 40 | 41 | Широко поширена помилка полягає в тому, що розподілені системи непридатні для проектів, які потребують офіційного централізованого сховища. Ніщо не може бути більш далеким від істини. Отримання фотознімку не призводить до того, що ми крадемо чиюсь душу. Точно так само клонування головного сховища не зменшує його важливість. 42 | 43 | У першому наближенні можна сказати, що все, що робить централізована система керування версіями, добре сконструйована розподілена система може зробити краще. Мережеві ресурси просто дорожчі локальних. Хоча далі ми побачимо, що в розподіленому підході є свої недоліки, ви навряд чи помилитеся у виборі, керуючись цим наближеним правилом. 44 | 45 | Невеликому проектом може знадобитися лише частинка функціоналу, пропонованого такою системою. Але використання погано масштабованої системи для маленьких проектів подібно використанню римських цифр в розрахунках з невеликими числами. 46 | 47 | Крім того, проект може вирости понад початкові очікування. Використовувати Git з самого початку — це як тримати напоготові швейцарський ніж, навіть якщо ви всього лише відкриваєте ним пляшки. Одного разу вам шалено знадобиться викрутка і ви будете раді, що під рукою є щось більше, ніж проста відкривачка. 48 | 49 | === Конфлікти при злитті === 50 | 51 | Для цієї теми аналогія з комп'ютерною грою стає занадто натягнутою. Замість цього, давайте повернемося до редагування документа. 52 | 53 | Отже, припустимо, що Марічка вставила рядок на початку файлу, а Іван — в кінці. Обоє вони закачують свої зміни. Більшість систем автоматично зробить розумний висновок: прийняти і об'єднати їх зміни так, щоб обидві правки — і Марічки, і Івана — були застосовані. 54 | 55 | Тепер припустимо, що і Марічка, і Іван внесли різні зміни в один і той же рядок. У цьому випадку неможливо продовжити без втручання людини. Той із них, хто другим закачає на сервер зміни, буде поінформований про _конфлікте злиття_ (_merge conflict_), і повинен або віддати перевагу одній змінні перед іншою, або скорегувати увесь рядок. 56 | 57 | Можуть траплятися і більш складні ситуації. Системи керування версіями вирішують прості ситуації самі і залишають складні для людини. Зазвичай таку їхню поведінку можна налаштовувати. 58 | -------------------------------------------------------------------------------- /uk/preface.txt: -------------------------------------------------------------------------------- 1 | = Магія Git = 2 | Ben Lynn 3 | Серпень 2007 4 | 5 | == Передмова == 6 | 7 | http://git.or.cz/[Git] — це швейцарський ніж керування версіями — надійний універсальний багатоцільовий інструмент, чия надзвичайна гнучкість робить його складним у вивченні навіть для багатьох професіоналів. 8 | 9 | Як говорив Артур Кларк, будь-яка досить розвинена технологія не відрізняється від чаклунства. Це відмінний підхід до Git: новачки можуть ігнорувати принципи його внутрішньої роботи і розглядати Git як щось, що викликає захоплення у друзів і доводить до сказу ворогів своїми чудовими здібностями. 10 | 11 | Замість того, щоб вдаватися в подробиці, ми дамо приблизні інструкції для одержання конкретних результатів. При частому використанні ви поступово зрозумієте, як працює кожен трюк і як пристосовувати рецепти під ваші потреби. 12 | 13 | .Переклади 14 | 15 | - link:/~blynn/gitmagic/intl/vi/[В'єтнамська]: Trần Ngọc Quân; також http://vnwildman.users.sourceforge.net/gitmagic/[розміщено на його вебсайті]. 16 | - link:/~blynn/gitmagic/intl/es/[Іспанська]: Rodrigo Toledo та Ariset Llerena Tapia. 17 | - link:/\~blynn/gitmagic/intl/zh_cn/[Китайська (спрощена)]: JunJie, Meng та JiangWei. Конвертовано у link:/~blynn/gitmagic/intl/zh_tw/[Традиційна китайська] via +cconv -f UTF8-CN -t UTF8-TW+. 18 | - link:/~blynn/gitmagic/intl/de/[Німецька]: Benjamin Bellee і Armin Stebich. Armin також розмістив http://gitmagic.lordofbikes.de/[німецький переклад на своєму сайті]. 19 | - http://www.slideshare.net/slide_user/magia-git[Португальська]: Leonardo Siqueira Rodrigues [http://www.slideshare.net/slide_user/magia-git-verso-odt[в форматі ODT]]. 20 | - link:/~blynn/gitmagic/intl/ru/[Російська]: Тихон Тарнавский, Михаил Дымсков і інші. 21 | - link:/~blynn/gitmagic/intl/uk/[Українська]: Володимир Боденчук. 22 | - link:/~blynn/gitmagic/intl/fr/[Французька]: Alexandre Garel, Paul Gaborit, та Nicolas Deram. 23 | 24 | .Інші варіанти 25 | 26 | - link:book.html[HTML однією сторінкою]: чистий HTML без CSS. 27 | - link:book.pdf[PDF файл]: для друку. 28 | - http://packages.debian.org/gitmagic[пакунок Debian], http://packages.ubuntu.com/gitmagic[пакунок Ubuntu]: отримайте локальну копію цього сайту. Стане у нагоді, http://csdcf.stanford.edu/status/[якщо цей сервер буде недоступним]. 29 | - http://www.amazon.com/Git-Magic-Ben-Lynn/dp/1451523343/[друкована версія [Amazon.com]]: 64 сторінок, 15.24cm x 22.86cm, чорно-біле зображення. Стане у нагоді у випадку відсутності електроенергії. 30 | 31 | === Подяки === 32 | 33 | Я дуже ціную, що так багато людей працювали над перекладами цих рядків. Я вдячний названим вище людям за їхні зусилля, які розширили мою аудиторію. 34 | 35 | Dustin Sallings, Alberto Bertogli, James Cameron, Douglas Livingstone, Michael Budde, Richard Albury, Tarmigan, Derek Mahar, Frode Aannevik, Keith Rarick, Andy Somerville, Ralf Recker, Øyvind A. Holm, Miklos Vajna, Sébastien Hinderer, Thomas Miedema, Joe Malin, Tyler Breisacher, Sonia Hamilton, Julian Haagsma, Romain Lespinasse, Sergey Litvinov, Oliver Ferrigni, David Toca, Сергей Сергеев, Joël Thieffry та Baiju Muthukadan сприяли в правках і доробках. 36 | 37 | François Marier супроводжує пакунок Debian, спочатку створений Daniel Baumann. 38 | 39 | 40 | Мої подяки іншим за вашу підтримку і похвалу. Мені дуже хотілося процитувати вас тут, але це могло б підняти ваше марнославство до неймовірних висот. 41 | 42 | Якщо я випадково забув згадати вас, будь ласка, нагадайте мені або просто вишліть патч. 43 | 44 | === Ліцензія === 45 | 46 | Це керівництво випущено під http://www.gnu.org/licenses/gpl-3.0.html[GNU General Public License 3-ї версії]. Природньо, вихідний текст знаходиться в сховищі Git і може бути отриманий за допомогою команди: 47 | 48 | $ git clone git://repo.or.cz/gitmagic.git # Створить каталог "gitmagic". 49 | 50 | або з одного із дзеркал: 51 | 52 | $ git clone git://github.com/blynn/gitmagic.git 53 | $ git clone git://gitorious.org/gitmagic/mainline.git 54 | $ git clone https://code.google.com/p/gitmagic/ 55 | $ git clone git://git.assembla.com/gitmagic.git 56 | $ git clone git@bitbucket.org:blynn/gitmagic.git 57 | 58 | GitHub, Assembla, і Bitbucket підтримують приватні сховища, останні два 59 | безкоштовно. 60 | -------------------------------------------------------------------------------- /uk/translate.txt: -------------------------------------------------------------------------------- 1 | == Додаток B: Переклад цього керівництва == 2 | 3 | Я раджу наступний спосіб для перекладу цього керівництва, щоб мої скрипти могли швидко створювати HTML і PDF версії, а всі переклади знаходилися в одному сховищі. 4 | 5 | Клонуйте вихідні тексти, потім створіть каталог, що відповідає тегу IETF цільової мови: дивіться 6 | http://www.w3.org/International/articles/language-tags/Overview.en.php[статтю W3C по інтернаціоналізації]. Наприклад, англійська мова це „en“, а японська — „ja“. Скопіюйте в каталог файли +txt+ з каталогу „en“ і перекладіть їх. 7 | 8 | Наприклад, для перекладу посібника на http://uk.wikipedia.org/wiki/Клінгонська_мова[клінгонську мову], ви можете набрати: 9 | 10 | $ git clone git://repo.or.cz/gitmagic.git 11 | $ cd gitmagic 12 | $ mkdir tlh # «tlh» — мовний код IETF клінгонської мови. 13 | $ cd tlh 14 | $ cp ../en/intro.txt . 15 | $ edit intro.txt # Перекладіть файл. 16 | 17 | і так із кожним файлом. 18 | 19 | Відредагуйте Makefile і додайте код мови в змінну TRANSLATIONS. Тепер ви зможете переглядати вашу роботу по ходу справи: 20 | 21 | $ make tlh 22 | $ firefox book.html 23 | 24 | Почастіше робіть комміти, а коли ваш переклад буде готовий, повідомте мені про це. На GitHub є веб-інтерфейс, що полегшує описані дії: зробіть форк проекту „gitmagic“, залийте ваші зміни і попросіть мене зробити злиття. 25 | -------------------------------------------------------------------------------- /vi/README: -------------------------------------------------------------------------------- 1 | This project translate GitMagic ebook into Vietnamese. 2 | License: GPL-3 3 | Copyleft: 2010-2011 GitMagic team. 4 | First transalted by: Trần Ngọc Quân. 5 | Personal website: vnwildman.users.sourceforge.net 6 | Project's SCM address: https://github.com/vnwildman/gitmagic.git 7 | 8 | Special thanks: 9 | -Clytie Siddall. 10 | -GitHub.com 11 | -------------------------------------------------------------------------------- /vi/preface.txt: -------------------------------------------------------------------------------- 1 | = Git Magic = 2 | Ben Lynn 3 | Tháng Tám, 2007 4 | 5 | == Lời nói đầu == 6 | 7 | http://git-scm.com/[Git] là công cụ quản lý mã nguồn vạn năng. Đây là một công cụ quản lý mã nguồn tin cậy, ổn định, đa dụng và cực kỳ mềm dẻo và chính sự mềm dẻo của Git làm cho việc học nó trở nên khó khăn, tất nhiên là không nói đến những người đã tạo ra nó. 8 | 9 | Theo quan sát của Arthur C. Clarke, bất kể công nghệ tiên tiến nào cũng không thể phân biệt rạch ròi là nó có kỳ diệu hay không. Đây cũng là cách hay đề đề cập đến Git: những người mới sử dụng không cần quan tâm đến bên trong Git làm việc như thế nào mà hãy xem khả năng thần kỳ của nó như là một điệu gizmo có thể làm những người coi nó là bạn sửng sốt và làm điên đầu những người đối lập. 10 | 11 | Thay vì đi sâu vào chi tiết, chúng tôi đưa ra phác thảo cách làm việc của các hiệu ứng chuyên biệt. Sau khi sử dụng lặp lại nhiều lần, từ từ bạn sẽ hiểu từng mẹo một và thực hiện được những việc mà mình muốn làm. 12 | 13 | .Bản dịch 14 | 15 | - link:/\~blynn/gitmagic/intl/zh_cn/[Tiếng Trung Giản thể]: dịch bởi JunJie, Meng và JiangWei. Đã chuyển đổi sang: link:/~blynn/gitmagic/intl/zh_tw/[Tiếng Trung Phồn thể] thông qua lệnh +cconv -f UTF8-CN -t UTF8-TW+. 16 | - link:/~blynn/gitmagic/intl/fr/[Tiếng Pháp]: dịch bởi Alexandre Garel. 17 | - link:/~blynn/gitmagic/intl/de/[Tiếng Đức]: dịch bởi Benjamin Bellee và Armin Stebich; và đồng thời xuất bản http://gitmagic.lordofbikes.de/[trên website của Armin]. 18 | - link:/~blynn/gitmagic/intl/it/[Tiếng Ý]: dịch bởi Mattia Rigotti. 19 | - link:/~blynn/gitmagic/intl/ko/[Tiếng Hàn Quốc]: dịch bởi Jung-Ho (John) Han; đồng thời https://sites.google.com/site/drinkhanjohn/useful-links/[xuất bản trên trang web của John]. 20 | - link:/~blynn/gitmagic/intl/pl/[Tiếng Ba Lan]: dịch bởi Damian Michna. 21 | - link:/~blynn/gitmagic/intl/pt_br/[Tiếng Bồ Đào Nha Bra-xin]: dịch bởi José Inácio Serafini và Leonardo Siqueira Rodrigues. 22 | - link:/~blynn/gitmagic/intl/ru/[Tiếng Nga]: dịch bởi Tikhon Tarnavsky, Mikhail Dymskov và một số người khác. 23 | - link:/~blynn/gitmagic/intl/es/[Tiếng Tây Ban Nha]: dịch bởi Rodrigo Toledo và Ariset Llerena Tapia. 24 | - link:/~blynn/gitmagic/intl/uk/[Ukrainian]: dịch bởi Volodymyr Bodenchuk. 25 | - link:/~blynn/gitmagic/intl/vi/[Tiếng Việt]: dịch bởi Trần Ngọc Quân và đồng thời xuất bản bản dịch này trên http://vnwildman.users.sourceforge.net/gitmagic/[trang Web cá nhân của mình]. 26 | 27 | .Các định dạng khác 28 | 29 | - link:book.html[Trang web đơn]: dạng HTML đơn giản, không được định dạng bằng CSS. 30 | - link:book.pdf[Định dạng PDF]: thuận tiện cho việc in ấn. 31 | - http://packages.debian.org/gitmagic[Gói dành cho Debian], http://packages.ubuntu.com/gitmagic[gói dành cho Ubuntu]: tải về đĩa cứng từ các địa chỉ này. Tiện lợi http://csdcf.stanford.edu/status/[khi máy chủ này không kết nối mạng hay không hoạt động]. 32 | - http://www.amazon.com/Git-Magic-Ben-Lynn/dp/1451523343/[Sách giấy [Amazon.com]]: 64 trang, 15.24cm x 22.86cm, đen trắng. Rất tiện sử dụng vì chẳng cần đến điện. 33 | 34 | === Lời cảm ơn! === 35 | 36 | Tôi gửi lời cảm ơn đến những người đã dịch quyển sách này. 37 | Tôi rất cảm kích vì có được số lượng độc giả rộng lớn có được bởi những người 38 | đã được nêu tên ở trên. 39 | 40 | Dustin Sallings, Alberto Bertogli, James Cameron, Douglas Livingstone, Michael Budde, Richard Albury, Tarmigan, Derek Mahar, Frode Aannevik, Keith Rarick, Andy Somerville, Ralf Recker, Øyvind A. Holm, Miklos Vajna, Sébastien Hinderer, Thomas Miedema, Joe Malin, Tyler Breisacher, Sonia Hamilton, Julian Haagsma, Romain Lespinasse, Sergey Litvinov, Oliver Ferrigni, David Toca, Сергей Сергеев, Joël Thieffry và Baiju Muthukadan đã đóng góp trong việc sửa chữa và cải tiến nội dung. 41 | 42 | François Marier đã bảo trì gói Debian do Daniel 43 | Baumann khởi xướng. 44 | 45 | 46 | Tôi cũng gửi lời cảm ơn tới sự giúp đỡ và sự tán dương của các bạn. Tôi muốn 47 | trích dẫn những lời đó ra đây, nhưng làm như thế có vẻ hơi lố bịch, tự cao tự đại. 48 | 49 | Nếu tôi có sai sót gì, xin hãy thông tin hay gửi bản vá cho tôi! 50 | 51 | === Giấy phép sử dụng === 52 | 53 | Hướng dẫn này được phát hành dựa trên http://www.gnu.org/licenses/gpl-3.0.html[Giấy Ghép Công phiên bản 3]. Đương nhiên, nội dung của quyển sách được quản lý bằng Git, 54 | và bạn có thể dễ dàng có được nó bằng cách gõ: 55 | 56 | $ git clone git://repo.or.cz/gitmagic.git # Tạo ra thư mục "gitmagic". 57 | 58 | hay từ các máy chủ khác: 59 | 60 | $ git clone git://github.com/blynn/gitmagic.git 61 | $ git clone git://gitorious.org/gitmagic/mainline.git 62 | $ git clone https://code.google.com/p/gitmagic/ 63 | $ git clone git://git.assembla.com/gitmagic.git 64 | $ git clone git@bitbucket.org:blynn/gitmagic.git 65 | 66 | GitHub, Assembla, và Bitbucket có hỗ trợ các kho có tính riêng tư, hai địa sau 67 | là miễn phí. 68 | 69 | -------------------------------------------------------------------------------- /vi/translate.txt: -------------------------------------------------------------------------------- 1 | == Phụ lục B: Dịch cuốn sách này == 2 | 3 | Tôi khuyến nghị các bạn làm theo các bước sau để thực hiện việc dịch thuật, 4 | làm như vậy thì các đoạn kịch bản của tôi có thể 5 | nhanh chóng tạo ra các tài liệu ở định dạng HTML và PDF, 6 | và tất cả các bản dịch có thể ở trong cùng một kho chứa. 7 | 8 | Lấy một bản sao của mã nguồn, sau đó tạo một thư mục tương ứng với ngôn ngữ bạn dịch http://www.iana.org/assignments/language-subtag-registry[language's IETF tag]: xem tại 9 | http://www.w3.org/International/articles/language-tags/Overview.en.php[the W3C article on internationalization]. 10 | Ví dụ, tiếng Anh là "en", Nhật là "ja", tiếng Trung Quốc Phồn thể là "zh-Hant". 11 | Trong thư mục mới đó, và dịch tập tin +txt+ từ thư mục con "en". 12 | 13 | Một ví dụ cụ thể là để dịch phần hướng dẫn này thành ngôn ngữ http://en.wikipedia.org/wiki/Klingon_language[Klingon], bạn hãy gõ vào: 14 | 15 | $ git clone git://repo.or.cz/gitmagic.git 16 | $ cd gitmagic 17 | $ mkdir tlh # "tlh" là mã ngôn ngữ IETF dành cho Klingon. 18 | $ cd tlh 19 | $ cp ../en/intro.txt . 20 | $ edit intro.txt # Dịch tập tin này. 21 | 22 | và cứ như thế cho những tập tin còn lại. 23 | 24 | Chỉnh sửa lại Makefile và thêm mã ngôn ngữ cho biến `TRANSLATIONS`. 25 | Bạn có thể xem thử kết quả công việc của mình như sau: 26 | 27 | $ make tlh 28 | $ firefox book-tlh/index.html 29 | 30 | Hãy chuyển giao công việc của bạn thường xuyên, và cho tôi biết khi nào thì chúng sẵn sàng để sử dụng. 31 | GitHub.com có giao diện thuận lợi như sau: rẽ nhánh dự án "gitmagic", 32 | 'push' các thay đổi của bạn lên, sau đó thông báo với tôi để tôi trộn. 33 | 34 | -------------------------------------------------------------------------------- /zh_cn/basic.txt: -------------------------------------------------------------------------------- 1 | == 基本技巧 == 2 | 3 | 与其一头扎进Git命令的海洋中,不如来点基本的例子试试手。它们简单而且实用。实际 4 | 上,在开始使用Git的头几个月,我所用的从来没超出本章介绍的内容。 5 | 6 | === 保存状态 === 7 | 8 | 要不来点猛的?在做之前,先为当前目录所有文件做个快照,使用: 9 | 10 | $ git init 11 | $ git add . 12 | $ git commit -m "My first backup" 13 | 14 | 现在如果你的编辑乱了套,恢复之前的版本可以使用: 15 | 16 | $ git reset --hard 17 | 18 | 再次保存状态: 19 | 20 | $ git commit -a -m "Another backup" 21 | 22 | === 添加、删除、重命名 === 23 | 24 | 以上命令将只跟踪你第一次运行 *git add* 命令时就已经存在的文件。如果要添加新文 25 | 件或子目录,你需要告诉Git: 26 | 27 | $ git add readme.txt Documentation 28 | 29 | 类似,如果你想让Git忘记某些文件: 30 | 31 | $ git rm kludge.h obsolete.c 32 | $ git rm -r incriminating/evidence/ 33 | 34 | 这些文件如果还没被从系统中删除,Git将会删除它们。 35 | 36 | 重命名文件同删除旧文件,并同时添加新文件一样。也有一个快捷方式 *git mv* ,和 37 | *mv* 命令的用法一样。例如: 38 | 39 | $ git mv bug.c feature.c 40 | 41 | === 进阶撤销/重做 === 42 | 43 | 有时候你只想把某个时间点之后的所有改动都回滚掉,因为这些的改动是不正确的。那 44 | 么使用这个命令: 45 | 46 | $ git log 47 | 48 | 来显示最近提交列表,以及查看他们的SHA1哈希值: 49 | 50 | ---------------------------------- 51 | commit 766f9881690d240ba334153047649b8b8f11c664 52 | Author: Bob <bob@example.com> 53 | Date: Tue Mar 14 01:59:26 2000 -0800 54 | 55 | Replace printf() with write(). 56 | 57 | commit 82f5ea346a2e651544956a8653c0f58dc151275c 58 | Author: Alice <alice@example.com> 59 | Date: Thu Jan 1 00:00:00 1970 +0000 60 | 61 | Initial commit. 62 | ---------------------------------- 63 | 64 | 哈希值的前几个字符足够确定一个提交;也可以拷贝粘贴完整的哈希值,输入: 65 | 66 | $ git reset --hard 766f 67 | 68 | 来恢复到一个指定的提交状态,并从记录里永久抹掉所有比该记录新一些的提交。 69 | 70 | 另一些时候你想简单地回朔到某一个旧状态。这种情况,键入: 71 | 72 | $ git checkout 82f5 73 | 74 | 这个操作将把你带回过去,同时也保留较新提交。然而,像科幻电影里时光旅行一样, 75 | 如果你这时编辑并提交的话,你将身处另一个现实里,因为你的动作与开始时相比是不 76 | 同的。 77 | 78 | 这另一个现实叫作“分支”(branch),之后 <<branch,我们会对这点多讨论一些>>。 79 | 至于现在,只要记住: 80 | 81 | $ git checkout master 82 | 83 | 会把你带到当下来就可以了。另外,为避免Git的抱怨,应该在每次运行checkout之前提 84 | 交(commit)或重置(reset)你的改动。 85 | 86 | 还以电脑游戏作为类比: 87 | 88 | - *`git reset --hard`*: 加载一个旧记录并删除所有比之新的记录。 89 | 90 | - *`git checkout`*: 加载一个旧记录,但如果你在这个记录上玩,游戏状态将偏离第 91 | 一轮的较新状态。你现在打的所有游戏记录会在你刚进入的、代表另一个真实的分支 92 | 里。<<branch,我们稍后论述>>。 93 | 94 | 你可以选择只恢复特定文件和目录,这将通过将其加在命令之后来实现: 95 | 96 | $ git checkout 82f5 some.file another.file 97 | 98 | 小心,这种形式的 *checkout* 会不声不响地覆盖当前文件。为防止意外发生,在运行任何 99 | checkout命令之前做提交,尤其在初学Git的时候。通常,任何时候你觉得对运行某个命 100 | 令不放心,无论Git命令还是不是Git命令,就先运行一下 *git commit -a* 。 101 | 102 | 不喜欢拷贝旧提交的哈希值?那就用: 103 | 104 | $ git checkout :/"My first b" 105 | 106 | 来跳到以特定字符串开头的提交。你也可以回到倒数第五个保存状态: 107 | 108 | $ git checkout master~5 109 | 110 | === 撤销 === 111 | 112 | 在法庭上,事件可以从法庭记录里敲出来。同样,你可以检出特定提交以撤销。 113 | 114 | $ git commit -a 115 | $ git revert 1b6d 116 | 117 | 将撤销给定哈希值的提交。本撤销被记录为一个新的提交,你可以通过运行 *git log* 118 | 来确认这一点。 119 | 120 | === 变更日志生成 === 121 | 122 | 一些项目要求生成变更日志http://en.wikipedia.org/wiki/Changelog[changelog]. 若 123 | 要生成一个变更日志,可以键入: 124 | 125 | $ git log > ChangeLog 126 | 127 | 来实现。 128 | 129 | === 下载文件 === 130 | 131 | 得到一个由Git管理的项目的拷贝,则键入: 132 | 133 | $ git clone git://server/path/to/files 134 | 135 | 例如,得到我用来创建该站的所有文件: 136 | 137 | $ git clone git://git.or.cz/gitmagic.git 138 | 139 | 我们很快会对 *clone* 命令谈的很多。 140 | 141 | === 到最新 === 142 | 143 | 如果你已经使用 *git clone* 命令得到了一个项目的一份拷贝,你可以更新到最新版, 144 | 通过: 145 | 146 | $ git pull 147 | 148 | 149 | === 快速发布 === 150 | 151 | 假设你写了一个脚本,想和他人分享。你可以只告诉他们从你的计算机下载,但如果此 152 | 时你正在改进你的脚本,或加入了试验性质的改动,他们下载了你的脚本,他们可能因 153 | 此陷入困境。当然,这就是发布周期存在的原因。开发人员可能频繁进行项目修改,但 154 | 他们只在他们觉得代码可以见人的时候才择时发布。 155 | 156 | 用Git来完成这项,需要进入你的脚本所在目录: 157 | 158 | $ git init 159 | $ git add . 160 | $ git commit -m "First release" 161 | 162 | 然后告诉你的用户去运行: 163 | 164 | $ git clone your.computer:/path/to/script 165 | 166 | 来下载你的脚本。这要假定他们有ssh访问权限。如果没有,需要运行 *git daemon* 并 167 | 告诉你的用户去运行: 168 | 169 | $ git clone git://your.computer/path/to/script 170 | 171 | 从现在开始,每次你的脚本准备好发布时,就运行: 172 | 173 | $ git commit -a -m "Next release" 174 | 175 | 而你的用户则可以进入包含你脚本的目录,并键入下列命令,来更新他们的版本: 176 | 177 | $ git pull 178 | 179 | 你的用户永远也不会取到你不想让他们看到的脚本版本。显然这个技巧对所有代码库都 180 | 适用,而不仅仅局限于脚本。 181 | 182 | 183 | === 我们已经做了什么? === 184 | 185 | 找出自从上次提交之后你已经做了什么改变: 186 | 187 | $ git diff 188 | 189 | 或者自昨天的改变: 190 | 191 | $ git diff "@{yesterday}" 192 | 193 | 或者一个特定版本与倒数第二个变更之间: 194 | 195 | $ git diff 1b6d "master~2" 196 | 197 | 输出结果都是补丁格式,可以用 *git apply* 来把补丁打上。也可以试一下: 198 | 199 | $ git whatchanged --since="2 weeks ago" 200 | 201 | 我也经常用http://sourceforge.net/projects/qgit[qgit] 浏览历史, 因为他的图形界 202 | 面很养眼,或者 http://jonas.nitro.dk/tig/[tig] ,一个文本界面的东西,很慢的网 203 | 络状况下也可以工作的很好。也可以安装web 服务器,运行 *git instaweb* ,就可以用 204 | 任意浏览器浏览了。 205 | 206 | === 练习 === 207 | 208 | 比方A,B,C,D是四个连续的提交,其中B与A一样,除了一些文件删除了。我们想把这 209 | 些删除的文件加回D。我们如何做到这个呢? 210 | 211 | 至少有三个解决方案。假设我们在D: 212 | 213 | 1. A与B的差别是那些删除的文件。我们可以创建一个补丁代表这些差别,然后把补丁 214 | 打上: 215 | 216 | $ git diff B A | git apply 217 | 218 | 2. 既然这些文件存在A,我们可以把它们拿出来: 219 | 220 | $ git checkout A foo.c bar.h 221 | 222 | 3. 我们可以把从A到B的变化视为可撤销的变更: 223 | 224 | $ git revert B 225 | 226 | 哪个选择最好?这取决于你的喜好。利用Git满足自己需求是容易,经常还有多个方法。 227 | -------------------------------------------------------------------------------- /zh_cn/branch.txt: -------------------------------------------------------------------------------- 1 | == 分支巫术 == 2 | 3 | 即时分支合并是Git最给力的杀手锏。 4 | 5 | *问题* :外部因素要求必须切换场景。不如说,在发布版本中突然蹦出个严重缺陷;某 6 | 个特性完成的截至日期就要来临;在项目关键部分可以提供帮助的一个开发正打算离 7 | 职。所有情况逼迫你停下所有手头工作,全力扑到到这个完全不同的任务上。 8 | 9 | 打断思维的连续性会使你的生产力大大降低,并且切换上下文越麻烦,潜在的损失也越 10 | 大。如果使用中心版本控制,我们就必须从中心服务器下载一个新的工作拷贝。分布式 11 | 系统的情况就好多了,因为我们能够在本地克隆所需要的版本。 12 | 13 | 但是克隆仍然需要拷贝整个工作目录,还有直到给定点的整个历史记录。尽管Git使用文 14 | 件共享和硬链接减少了花费,项目文件自身还是必须在新的工作目录里重建。 15 | 16 | *方案* :Git有一个更好的工具对付这种情况,比克隆快多了而且节省空间: *git 17 | branch* 。 18 | 19 | 使用这个魔咒,目录里的文件突然从一个版本变到另一个。除了只是在历史记录里上跳 20 | 下窜外,这个转换还可以做更多。你的文件可以从上一个发布版变到实验版本到当前开 21 | 发版本到你朋友的版本等等。 22 | 23 | === 老板键 === 24 | 25 | 曾经玩过那样的游戏吗?按一个键(“老板键”),屏幕立即显示一个电子表格或别的? 26 | 那么如果老板走进办公室,而你正在玩游戏,就可以快速将游戏藏起来。 27 | 28 | 在某个目录: 29 | 30 | $ echo "I'm smarter than my boss" > myfile.txt 31 | $ git init 32 | $ git add . 33 | $ git commit -m "Initial commit" 34 | 35 | 我们已经创建了一个Git仓库,该仓库保存了一个包含特定信息的文件。现在我们键入: 36 | 37 | $ git checkout -b boss # 之后似乎没啥变化 38 | $ echo "My boss is smarter than me" > myfile.txt 39 | $ git commit -a -m "Another commit" 40 | 41 | 看起来我们刚刚只是覆盖了原来的文件并提交了它。但这是个错觉。键入: 42 | 43 | $ git checkout master # 切到文件的原先版本 44 | 45 | 嘿真快!这个文件就恢复了。并且如果老板决定窥视这个目录,键入: 46 | 47 | $ git checkout boss # 切到适合老板看的版本 48 | 49 | 你可以在两个版本之间相切多少次就切多少次,而且每个版本都可以独立提交。 50 | 51 | === 肮脏的工作 === 52 | 53 | [[branch]] 54 | 55 | 比如你正在开发某个特性,并且由于某种原因,你需要回退三个版本,临时加进几行打 56 | 印语句来,来看看一些东西是如何工作的。那么: 57 | 58 | $ git commit -a 59 | $ git checkout HEAD~3 60 | 61 | 现在你可以到处加丑陋的临时代码。你甚至可以提交这些改动。当你做完的时候, 62 | 63 | $ git checkout master 64 | 65 | 来返回到你原来的工作。看,所有未提交变更都结转了。 66 | 67 | 如果你后来想保存临时变更怎么办?简单: 68 | 69 | $ git checkout -b dirty 70 | 71 | 只要在切换到主分支之前提交就可以了。无论你什么时候想回到脏的变更,只需键入: 72 | 73 | $ git checkout dirty 74 | 75 | 我们在前面章节讨论加载旧状态的时候,曾经接触过这个命令。最终我们把故事说全: 76 | 文件改变成请求的状态,但我们必须离开主分支。从现在开始的任何提交都会将你的文 77 | 件提交到另一条不同的路,这个路可以之后命名。 78 | 79 | 换一个说法,在checkout一个旧状态之后,Git自动把你放到一个新的,未命名的分支, 80 | 这个分支可以使用 *git checkout -b* 来命名和保存。 81 | 82 | === 快速修订 === 83 | 84 | 你正在做某件事的当间,被告知先停所有的事情,去修理一个新近发现的臭虫,这个臭 85 | 虫在提交 `1b6d...`: 86 | 87 | $ git commit -a 88 | $ git checkout -b fixes 1b6d 89 | 90 | 那么一旦你修正了这个臭虫: 91 | 92 | $ git commit -a -m "Bug fixed" 93 | $ git checkout master 94 | 95 | 并可以继续你原来的任务。你甚至可以“合并”到最新修订: 96 | 97 | $ git merge fixes 98 | 99 | === 合并 === 100 | 101 | 一些版本控制系统,创建分支很容易,但把分支合并回来很难。使用Git,合并简直是家 102 | 常便饭,以至于甚至你可能对其发生没有察觉。 103 | 104 | 我们很久之前就遇到合并了。 *pull* 命令取出提交并合并它们到你的当前分支。如果 105 | 你没有本地变更,那这个合并就是一个“快进”,相当于中心式版本控制系统里的一个 106 | 弱化的获取最新版本操作。但如有本地变更,Git将自动合并,并报告任何冲突。 107 | 108 | 通常,一个提交只有一个“父提交”,也叫前一个提交。合并分支到一起产生一个至少 109 | 有两个父的提交。这就引出了问题: `HEAD~10` 真正指哪个提交?一个提交可能有多个 110 | 父,那我们跟哪个呢? 111 | 112 | 原来这个表示每次选择第一个父。这是可取的,因为在合并时候当前分支成了第一个父; 113 | 多数情况下我们只关注我们在当前分支都改了什么,而不是从其他分支合并来的变更。 114 | 115 | 你可以用插入符号来特别指定父。比如,显示来自第二个父的日志: 116 | 117 | $ git log HEAD^2 118 | 119 | 你可以忽略数字以指代第一个父。比如,显示与第一个父的差别: 120 | 121 | $ git diff HEAD^ 122 | 123 | 你可以结合其他类型使用这个记号。比如: 124 | 125 | $ git checkout 1b6d^^2~10 -b ancient 126 | 127 | 开始一个新分支 ``ancient'' ,表示第一个父的第二个父的倒数第十次提交的状态。 128 | 129 | === 不间断工作流 === 130 | 131 | 经常在硬件项目里,计划的第二步必须等第一步完成才能开始。待修的汽车傻等在车库 132 | 里,直到特定的零件从工厂运来。一个原型在其可以构建之前,可能要苦等芯片成型。 133 | 134 | 软件项目可能也类似。新功能的第二部分不得不等待,直到第一部分发布并通过测试。 135 | 一些项目要求你的代码需要审批才能接受,因此你可能需要等待第一部分得到批准,才 136 | 能开始第二部分。 137 | 138 | 多亏了无痛分支合并,我们可以不必遵循这些规则,在第一部分正式准备好前开始第二 139 | 部分的工作。假设你已经将第一部分提交并发去审批,比如说你现在在主分支。那么分 140 | 岔: 141 | 142 | $ git checkout -b part2 143 | 144 | 接下来,做第二部分,随时可以提交变更。只要是人就可能犯错误,经常你将回到第一 145 | 部分在修修补补。如果你非常幸运,或者超级棒,你可能不必做这几行: 146 | 147 | $ git checkout master # 回到第一部分 148 | $ 修复问题 149 | $ git commit -a # 提交变更 150 | $ git checkout part2 # 回到第二部分 151 | $ git merge master # 合并这些改动 152 | 153 | 最终,第一部分获得批准: 154 | 155 | $ git checkout master # 回到第一部分 156 | $ submit files # 对世界发布 157 | $ git merge part2 # 合并第二部分 158 | $ git branch -d part2 # 删除分支“part2” 159 | 160 | 现在你再次处在主分支,第二部分的代码也在工作目录。 161 | 162 | 很容易扩展这个技巧,应用到任意数目的部分。它也很容易追溯分支:假如你很晚才意 163 | 识到你本应在7次提交前就创建分支。那么键入: 164 | 165 | $ git branch -m master part2 # 重命名“master”分支为“part2”。 166 | $ git branch master HEAD~7 # 以七次前提交建一个新的“master”。 167 | 168 | 分支 `master` 只有第一部分内容,其他内容在分支 `part2` 。 我们现在后一个分支; 169 | 我们创建了 `master` 分支还没有切换过去,因为我们想继续在分支 `part2` 上工作。这 170 | 是不寻常的。直到现在,我们已经在创建之后切换到分支,如: 171 | 172 | $ git checkout HEAD~7 -b master # 创建分支,并切换过去。 173 | 174 | === 重组杂乱 === 175 | 176 | 或许你喜欢在同一个分支下完成工作的方方面面。你想为自己保留工作进度并希望其他 177 | 人只能看到你仔细整理过后的提交。开启一对分支: 178 | 179 | $ git branch sanitized # 为干净提交创建分支 180 | $ git checkout -b medley # 创建并切换分支以进去工作 181 | 182 | 接下来,做任何事情:修臭虫,加特性,加临时代码,诸如此类,经常按这种方式提交。 183 | 然后: 184 | 185 | $ git checkout sanitized 186 | $ git cherry-pick medley^^ 187 | 188 | 应用分支 ``medley'' 的祖父提交到分支 ``sanitized'' 。通过合适的挑选(像选樱桃 189 | 那样)你可以构建一个只包含成熟代码的分支,而且相关的提交也组织在一起。 190 | 191 | === 管理分支 === 192 | 193 | 列出所有分支: 194 | 195 | $ git branch 196 | 197 | 默认你从叫 ``master'' 的分支开始。一些人主张别碰“master”分支,而是创建你自 198 | 己版本的新分支。 199 | 200 | 选项 *-d* 和 *-m* 允许你来删除和移动(重命名)分支。参见 *git help branch* 。 201 | 202 | 分支``master'' 是一个有用的惯例。其他人可能假定你的仓库有一个叫这个名字的分 203 | 支,并且该分支包含你项目的官方版本。尽管你可以重命名或抹杀 ``master'' 分支, 204 | 你最好还是尊重这个约定。 205 | 206 | === 临时分支 === 207 | 208 | 很快你会发现你经常会因为一些相似的原因创建短期的分支:每个其它分支只是为了保 209 | 存当前状态,那样你就可以直接跳到较老状态以修复高优先级的臭虫之类。 210 | 211 | 可以和电视的换台做类比,临时切到别的频道,来看看其它台那正放什么。但并不是简 212 | 单地按几个按钮,你不得不创建,检出,合并,以及删除临时分支。幸运的是,Git已经 213 | 有了和电视机遥控器一样方便的快捷方式: 214 | 215 | $ git stash 216 | 217 | 这个命令保存当前状态到一个临时的地方(一个隐藏的地方)并且恢复之前状态。你的 218 | 工作目录看起来和你开始编辑之前一样,并且你可以修复臭虫,引入之前变更等。当你 219 | 想回到隐藏状态的时候,键入: 220 | 221 | $ git stash apply # 你可能需要解决一些冲突 222 | 223 | 你可以有多个隐藏,并用不同的方式来操作他们。参见 *git help slash* 。也许你已 224 | 经猜到,Git维护在这个场景之后的分支以执行魔法技巧. 225 | 226 | === 按你希望的方式工作 === 227 | 228 | 你可能犹疑于分支是否值得一试。毕竟,克隆也几乎一样快,并且你可以用 *cd* 来在 229 | 彼此之间切换,而不是用Git深奥的命令。 230 | 231 | 考虑一下浏览器。为什么同时支持多标签和多窗口?因为允许两者同时接纳了多种风 232 | 格的用户。一些用户喜欢只保持一个打开的窗口,然后用标签浏览多个网页。一些可能 233 | 坚持另一个极端:任何地方都没有标签的多窗口。一些喜好处在两者之间。 234 | 235 | 分支类似于你工作目录的标签,克隆则类似于打开的浏览器新窗口。这些是本地操作很 236 | 快,那为什么不试着找出最适合你的组合呢?Git让你按你确实所希望的那样工作。 237 | -------------------------------------------------------------------------------- /zh_cn/clone.txt: -------------------------------------------------------------------------------- 1 | == 克隆代码库 == 2 | 3 | 在较老一代的版本控制系统里,checkout是获取文件的标准操作。你将获得一组特定保 4 | 存状态的文件。 5 | 6 | 在Git和其他分布式版本控制系统里,克隆是标准的操作。通过创建整个仓库的克隆来 7 | 获得文件。或者说,你实际上把整个中心服务器做了个镜像。凡是主仓库上能做的事, 8 | 你都能做。 9 | 10 | === 计算机间同步 === 11 | 12 | 我可以忍受制作tar包或利用rsync来作备份和基本同步。但我有时在我笔记本上编辑, 13 | 其他时间在台式机上,而且这俩之间也许并不交互。 14 | 15 | 在一个机器上初始化一个Git仓库并提交你的文件。然后转到另一台机器上: 16 | 17 | $ git clone other.computer:/path/to/files 18 | 19 | 以创建这些文件和Git仓库的第二个拷贝。从现在开始, 20 | 21 | $ git commit -a 22 | $ git pull other.computer:/path/to/files HEAD 23 | 24 | 将把另一台机器上特定状态的文件“拉”到你正工作的机器上。如果你最近对同一个文 25 | 件做了有冲突的修改,Git将通知你,而你也应该在解决冲突之后再次提交。 26 | 27 | === 典型源码控制 === 28 | 29 | 为你的文件初始化Git仓库: 30 | 31 | $ git init 32 | $ git add . 33 | $ git commit -m "Initial commit" 34 | 35 | 在中心服务器,在某个目录初始化一个“裸仓库”: 36 | 37 | $ mkdir proj.git 38 | $ cd proj.git 39 | $ git init --bare 40 | $ touch proj.git/git-daemon-export-ok 41 | 42 | 如需要的话,启动Git守护进程: 43 | 44 | $ git daemon --detach # 它也许已经在运行了 45 | 46 | 对一些Git伺服服务,按照其提示来初始化空Git仓库。一般是在服务器网页上填写一个表单。 47 | 48 | 把你的项目“推送”到中心服务器: 49 | $ git push central.server/path/to/proj.git HEAD 50 | 51 | 若要克隆源码,可以键入: 52 | 53 | $ git clone central.server/path/to/proj.git 54 | 55 | 做了改动之后,开发保存变更到本地: 56 | 57 | $ git commit -a 58 | 59 | 更新到最新版本: 60 | 61 | $ git pull 62 | 63 | 所有冲突应被处理,然后提交: 64 | 65 | $ git commit -a 66 | 67 | 把本地改动捡入到中心仓库: 68 | 69 | $ git push 70 | 71 | 如果主服务器由于其他开发的活动,有了新的变更,这个推送将会失败,开发者应该把最 72 | 新版本更新至本地机器,解决合并冲突,然后重试。 73 | 74 | 为使用上面的pull和push命令,开发者必须有SSH访问权限。不过,通过键入以下命令,任 75 | 何人都可以看到源码: 76 | 77 | $ git clone git://central.server/path/to/proj.git 78 | 79 | 本地git协议和HTTP类似:并无安全验证,因此任何人都能拿到项目。因此,默认情况 80 | git协议禁止推操作。 81 | 82 | === 封闭源码 === 83 | 84 | 闭源项目须避免执行touch命令,并确保你从未创建`git-daemon-export-ok`文件。资源 85 | 库不再可以通过git协议获取;只有那些有SSH访问权限的人才能看到。如果你所有的资源 86 | 库都是封闭的,那也没必要运行运行git守护了,因为所有沟通都走SSH。 87 | 88 | === 裸仓库 === 89 | 90 | 之所以叫裸仓库是因为其没有工作目录;它只包含正常情况下隐藏在`.git`子目录下 91 | 的文件。换句话说,它维护项目历史,而且从不保存任何给定版本的快照。 92 | 93 | 裸仓库扮演的角色和中心版本控制系统中中心服务器的角色类似:你项目的中心。开 94 | 发从其中克隆项目,检入新近改动。典型地裸仓库存在一个服务器上,该服务器除了 95 | 分散数据外并不担负额外的任务。开发活动发生在克隆的代码库上,因此中心仓库没 96 | 有工作目录也行。 97 | 98 | 99 | 很多Git命令在裸仓库上失败,除非指定仓库路径到环境变量`GIT_DIR`,或者指定 100 | `--bare`选项。 101 | 102 | === 推还是拽 === 103 | 104 | 为什么我们介绍了push命令,而不是依赖熟悉的pull命令?首先,在裸仓库上pull会 105 | 失败:除非你必须“fetch”,一个之后我们要讨论的命令。但即使我们在中心服务器上 106 | 保持一个正常的仓库,拽些东西进去仍然很繁琐。我们不得不登陆服务器先,给pull 107 | 命令我们要拽自机器的网络地址。防火墙会阻碍,并且首先如果我们没有到服务器的 108 | shell访问怎么办呢? 109 | 110 | 然而,除了这个案例,我们反对推进仓库,因为当目标有工作目录时,困惑随之而来。 111 | 112 | 简短来说,学习Git的时候,只在目标是裸仓库的时候使用push,否则用pull的方式。 113 | 114 | === 项目分叉 === 115 | 116 | 项目走歪了吗?或者认为你可以做得更好?那么在服务器上: 117 | 118 | $ git clone git://main.server/path/to/files 119 | 120 | 之后告诉每个相关的人你服务器上项目的分支。 121 | 122 | 在之后的时间,你可以合并来自原先项目的改变,使用命令: 123 | 124 | $ git pull 125 | 126 | === 终极备份 === 127 | 128 | 需要制作很多散布在各处,并禁止篡改的冗余存档吗? 如果你的项目有很多开发者参 129 | 与,那你并不需要再做什么了。每份代码克隆都是一个有效备份。它不仅包含当前代码 130 | 库状态,也同时包含了项目的整个历史。多谢哈希加密算法,如果任何人的克隆库被损 131 | 坏,只要其与其他克隆库交互,损坏的代码就会被显示出来。 132 | 133 | 如果你的项目并不是那么流行,那就找尽可能多的伺服来存放克隆库吧。 134 | 135 | 真正的偏执狂应该总是把HEAD最近20字节的SHA1哈希值写到安全的地方。应该保证安全, 136 | 而不是把它藏起来。比如,把它发布到报纸上就不错,因为对攻击者而言,更改每份报 137 | 纸是很难的。 138 | 139 | === 轻快多任务 === 140 | 141 | 比如你想并行开发多个功能。那么提交你的项目并运行: 142 | 143 | $ git clone . /some/new/directory 144 | 145 | Git使用硬链接和文件共享来尽可能安全地创建克隆,因此它一眨眼就完成了,因此你现 146 | 在可以并行操作两个没有相互依赖的功能。例如,你可以编辑一个克隆,同时编译另一 147 | 个。感谢 http://en.wikipedia.org/wiki/Hard_link[hardlinking], 本地克隆比简单 148 | 备份省时省地。 149 | 150 | 现在你可以同时工作在两个彼此独立的特性上。比如,你可以在编译一个克隆的时候编 151 | 辑另一个克隆。任何时候,你都可以从其它克隆提交并拖拽变更。 152 | 153 | $ git pull /the/other/clone HEAD 154 | 155 | === 游击版本控制 === 156 | 157 | 你正做一个使用其他版本控制系统的项目, 而你非常思念Git? 那么在你的工作目录初 158 | 始化一个Git仓库: 159 | 160 | $ git init 161 | $ git add . 162 | $ git commit -m "Initial commit" 163 | 164 | 然后克隆它: 165 | 166 | $ git clone . /some/new/directory 167 | 168 | 并在这个目录工作,按你所想在使用Git。过一会,一旦你想和其他每个人同步,在这种 169 | 情况下,转到原来的目录,用其他的版本控制工具同步,并键入: 170 | 171 | $ git add . 172 | $ git commit -m "Sync with everyone else" 173 | 174 | 现在转到新目录运行: 175 | 176 | $ git commit -a -m "Description of my changes" 177 | $ git pull 178 | 179 | 把你的变更提交给他人的过程依赖于其他版本控制系统。这个新目录包含你的改动的文 180 | 件。需要运行其他版本控制系统的命令来上载这些变更到中心仓库。 181 | 182 | Subversion, 或许是最好的中心式版本控制系统,为无数项目所用。 *git svn* 命令为 183 | Subversion仓库自动化了上面的操作,并且也可以用作 184 | http://google-opensource.blogspot.com/2008/05/export-git-project-to-google-code.html[ 185 | 导出Git项目到Subversion仓库] 的替代。 186 | 187 | === Mercurial === 188 | 189 | Mercurial是一个类似的的版本控制系统,几乎可以和Git一起无缝工作。使用 190 | `hg-git`插件,一个Mercurial用户可以无损地往Git仓库推送,从Git仓库拖拽。 191 | 192 | 使用Git获得`hg-git`插件: 193 | 194 | $ git clone git://github.com/schacon/hg-git.git 195 | 196 | 或使用Mercurial: 197 | 198 | $ hg clone http://bitbucket.org/durin42/hg-git/ 199 | 200 | 不好意思,我没注意Git有类似的插件。因此, 我主张使用Git而不是Mercurial作为主资 201 | 源库,即使你偏爱Mercurial。使用Mercurial项目,通常一个自愿者维护一个平行的 202 | Git项目以适应Git用户,然而感谢`hg-git`插件,一个Git项目自动地适应Mercurial用 203 | 户。 204 | 205 | 尽管该插件可以把一个Mercurial仓库转成一个Git仓库,通过推送一个空仓库来实现, 206 | 这个差事交给`hg-fast-export.sh`脚本来做还是更容易些。这个脚本来自: 207 | 208 | $ git clone git://repo.or.cz/fast-export.git 209 | 210 | 如需转化,只需在一个空目录运行: 211 | 212 | $ git init 213 | $ hg-fast-export.sh -r /hg/repo 214 | 215 | 注意,需要先将该脚本加入你的`$PATH`路径中,再执行以上命令行。 216 | 217 | === Bazaar === 218 | 219 | 我们简略提一下Bazaar,它毕竟是紧跟Git和Mercurial之后最流行的自由分布式版本控 220 | 制系统。 221 | 222 | Bazaar有后来者的优势,它相对年轻些;它的设计者可以从前人的错误中学习,并且避免 223 | 先行者在历史上犯过的错误。另外,它的开发人员对可移植性以及和与其它版本控制系统 224 | 的互操作性也考虑周全。 225 | 226 | 一个`bzr-git`插件让Bazaar用户在一定程度下可以工作在Git仓库。`tailor`程序转 227 | 换Bazaar仓库到Git仓库,并且可以递增的方式做,要知道`bzr-fast-export`只是 228 | 在一次性转换性情况下工作良好。 229 | 230 | === 我偏爱Git的原因 === 231 | 232 | 我起先选择Git是因为我听说它能管理不可想象地不可管理的Linux内核源码。我从来没 233 | 觉得有离开的必要。Git已经工作的很好了,并且我也没有被其瑕疵所困扰。因为我主要 234 | 使用Linux,其他平台上的问题与我无关。 235 | 236 | 还有,我偏爱C程序和bash脚本,以及诸如Python的可执行可脚本:其代码依赖性较低,并 237 | 且我也沉迷于快速的执行时间。 238 | 239 | 我考虑过Git如何才能提高,甚至自己写过类似的工具,但只作为学术研究练练手。即使我 240 | 会完成这个项目,我也无论如何会继续使用Git,因为使用一个古里古怪的系统所获甚微。 241 | 242 | 自然地,你的需求和期望可能不同,并且你可能感觉使用另一个系统会好些。即便如此,使 243 | 用Git你都不至于错太远。 244 | -------------------------------------------------------------------------------- /zh_cn/drawbacks.txt: -------------------------------------------------------------------------------- 1 | == 附录 A: Git的缺点 == 2 | 3 | 有一些Git的问题,我已经藏在毯子下面了。有些可以通过脚本或回调方法轻易地解决, 4 | 有些需要重组或重定义项目,少数剩下的烦恼,还只能等待。或者更好地,你可以加入 5 | Git项目来帮忙。 6 | 7 | === SHA1 的弱点 === 8 | 9 | 随着时间的推移,密码学家发现越来越多的SHA1的弱点。人们发现,对资源雄厚的组织 10 | 而言,找到哈希冲突是可能的。在几年内,或许甚至一个一般的PC也将有足够计算能力 11 | 悄悄摧毁一个Git仓库。 12 | 13 | 希望在进一步研究出摧毁SHA1的方法之前,Git能迁移到一个更好的哈希算法。 14 | 15 | === 微软 Windows === 16 | 17 | Git在微软Windows上可能有些繁琐: 18 | 19 | - http://cygwin.com/[Cygwin] , 这是一个Windows下的类Linux的环境,其包含一 20 | 个 http://cygwin.com/packages/git/[一个Git在Windows下的移植]. 21 | 22 | - http://code.google.com/p/msysgit/[基于MSys的Git] 是另一个,要求最小运行 23 | 时支持,不过一些命令不能马上工作。 24 | 25 | === 不相关的文件 === 26 | 27 | 如果你的项目非常大,包含很多不相关的文件,而且目录树在不断变更,Git可能比其他系统 28 | 更不可靠,因为独立的文件是不被跟踪的。Git跟踪整个项目的变更,这通常才是有益的。 29 | 30 | 一个方案是将你的项目拆成小块,每个都由相关文件组成。如果你仍然希望在同一个资 31 | 源库里保存所有内容的话,可以使用 *git submodule* 。 32 | 33 | === 谁在编辑什么? === 34 | 35 | 一些版本控制系统在编辑前会强迫你显示和用某个方法标记一个文件。尽管这种要求很烦 36 | 人,尤其是需要和中心服务器通讯时。不过它还是有以下两个好处的: 37 | 38 | 1. 速度比较快,因为只有被标记的文件需要检查。 39 | 40 | 2. 通过查询在中心服务器谁把这个文件标记为编辑状态,可以知道谁正在这个文件上工作。 41 | 42 | 使用适当的脚本,你也可以使Git达到同样的效果。但这要求程序员协同工作,当他编辑一 43 | 个文件的时候还要运行特定的脚本。 44 | 45 | === 文件历史 === 46 | 47 | 因为Git记录的是项目范围内的变更,重造单一文件的变更历史比其他跟踪单一文件的版本 48 | 控制系统要稍微麻烦些。 49 | 50 | 好在麻烦还不大,也是值得的,因为Git其他的操作难以置信地高效。例如,`git 51 | checkout`比`cp -a`都快,而且项目范围的delta压缩也比基于文件的delta集合的做法 52 | 好多了。 53 | 54 | === 初始克隆 === 55 | 56 | 当一个项目历史很长后,与在其他版本系统里的检出代码相比,创建一个克隆的开销会 57 | 大的多。 58 | 59 | 长远来看,开始付出的代价还是值得付出的,因为大多将来的操作将由此变得很快,并 60 | 可以离线完成。然而,在一些情况下,使用`--depth`创建一个浅层克隆比较划算些。这种 61 | 克隆初始化的更快,但得到克隆的功能有所削减。 62 | 63 | === 不稳定的项目 === 64 | 65 | 由变更的大小来决定写入的速度快慢是Git的特性。一般人做了小的改动就会提交新版 66 | 本:这里修正一行错误,那里加一个新功能,或者修改注释等等。但如果你的文件在相邻 67 | 版本之间存在极大的差异,那每次提交时,你的历史记录会随整个项目的大小增长。 68 | 69 | 任何版本控制系统对此都束手无策,但普通的Git用户将面对更多资源的消耗,因为一般 70 | 来说,历史记录也会被克隆。 71 | 72 | 应该检查一下变更巨大的原因:或许文件格式需要改变一下。小修改应该仅仅导致几个 73 | 文件的细小改动。 74 | 75 | 或许,数据库或备份/打包方案才是正选,而不是版本控制系统。例如,版本控制就不适 76 | 宜用来管理网络摄像头周期性拍下的照片。 77 | 78 | 如果这些文件实在需要不断更改,他们实在需要版本控制,一个可能的办法是以中心的 79 | 方式使用Git。可以创建浅克隆,这样检出的较少,也没有项目的历史记录。当然,很多 80 | Git工具就不能用了,并且修复必须以补丁的形式提交。这也许还不错,因为似乎没人需 81 | 要大幅度变化的不稳定文件历史。 82 | 83 | 另一个例子是基于固件的项目,因为要用到巨大的二进制文件形式。用户对固件文件的变 84 | 化历史没有兴趣,更新的压缩比很低,因此固件修订将使仓库无谓的变大。 85 | 86 | 这种情况下,源码应该保存在一个Git仓库里,但二进制文件应该单独保存。为了简化问题, 87 | 应该发布一个脚本,使用Git克隆源码,并对固件只做同步或Git浅层克隆。 88 | 89 | === 全局计数器 === 90 | 91 | 一些中心版本控制系统都会维护一个正整数,当一个新提交被接受的时候这个整数就增 92 | 长。Git则是通过哈希值来记录所有变更,这在大多数情况下都工作的不错。 93 | 94 | 但一些人喜欢使用整数的方法。幸运的是,很容易就可以写个脚本,这样每次更新,中 95 | 心Git仓库就增大这个整数,或使用tag的方式,把最新提交的哈希值与这个整数关联起来。 96 | 97 | 每个克隆都可以维护这么个计数器,但这或许没什么用,因为只有中心仓库以及它的计数器 98 | 对每个人才有意义。 99 | 100 | === 空子目录 === 101 | 102 | 空子目录不可加入管理。但可以通过创建一个空文件以绕过这个问题。 103 | 104 | Git的当前实现,而不是它的设计,是造成这个缺陷的原因。如果运气好,一旦Git得到 105 | 更多关注,并其有更多用户要求这个功能,这个功能就会被实现。 106 | 107 | === 初始提交 === 108 | 109 | 传统的计算机系统从0计数,而不是1。不幸的是,关于提交,Git并不遵从这一约定。很 110 | 多命令在初始提交之前都不友好。另外,一些极少数的情况必须作特别地处理。例如重 111 | 订一个使用不同初始提交的分支。 112 | 113 | Git将从定义零提交中受益:一旦一个仓库被创建起来,HEAD将被设为包含20个零字节 114 | 的字符串。这个特别的提交代表一棵空的树,没有父节点,早于所有Git仓库。 115 | 116 | 然后运行git log,比如,通知用户至今还没有提交过变更,而不是报告致命错误并退出。 117 | 这与其他工具类似。 118 | 119 | 每个初始提交都隐式地成为这个零提交的后代。 120 | 121 | 不幸的是还有更糟糕的情况。如果把几个具有不同初始提交的分支合并到一起,之后的 122 | 重新修订不可避免的将需要人员的介入。 123 | 124 | === 接口怪癖 === 125 | 126 | 对提交A和提交B,表达式“A..B”和“A...B”的含义,取决于命令期望两个终点还是一 127 | 个范围。参见 *git help diff* 和 *git help rev-parse* 。 128 | -------------------------------------------------------------------------------- /zh_cn/grandmaster.txt: -------------------------------------------------------------------------------- 1 | == Git大师技 == 2 | 3 | 到现在,你应该有能力查阅 *git help* 页,并理解几乎所有东西。然而,查明解决特 4 | 定问题需要的确切命令可能是乏味的。或许我可以省你点功夫:以下是我过去曾经用到 5 | 的一些技巧。 6 | 7 | === 源码发布 === 8 | 9 | 就我的项目而言,Git完全跟踪了我想打包并发布给用户的文件。如需创建一个源码包,我 10 | 会运行: 11 | 12 | $ git archive --format=tar --prefix=proj-1.2.3/ HEAD 13 | 14 | === 提交变更 === 15 | 16 | 对特定项目而言,告诉Git你增加,删除和重命名了一些文件很麻烦。而键入如下命令会容易 17 | 的多: 18 | 19 | $ git add . 20 | $ git add -u 21 | 22 | Git将查找当前目录的文件并计算出所有更改过的内容。除了第二个add命令,如果你也打 23 | 算同时提交,则可以运行`git commit -a`。关于如何指定应被忽略的文件,参见 *git 24 | help ignore* 。 25 | 26 | 你也可以用一行命令完成以上任务: 27 | 28 | $ git ls-files -d -m -o -z | xargs -0 git update-index --add --remove 29 | 30 | 这里 *-z* 和 *-0* 选项可以消除包含特殊字符的文件名引起的不良副作用。注意这个 31 | 命令也会添加本应被忽略的文件,这时你可能需要加上 `-x` 或 `-X` 选项。 32 | 33 | === 我的提交太大了! === 34 | 35 | 是不是忽略提交太久了?一直痴迷于写代码,直到现在才想起有源码控制工具这回事?或者 36 | 提交一系列不相关的变更,因为你更喜欢这么做? 37 | 38 | 别担心,运行: 39 | 40 | $ git add -p 41 | 42 | 对你做过的每次修改,Git都将展示变动过的代码,并询问该变动是否应是下一次提交的一 43 | 部分。回答“y”或者“n”。当然也有其他选项,比如延迟决定;键入“?”来学习更多。 44 | 45 | 一旦你满意,键入 46 | 47 | $ git commit 48 | 49 | 来精确地提交你所选择的变更(阶段变更)。注意请勿加上 *-a* 选项,否则Git将提交 50 | 所有修改。 51 | 52 | 如果你修改了许多地方的许多文件怎么办?一个一个地查看这些变更会令人沮丧,心态麻木。 53 | 这种情况下,使用 *git add -i* , 它的界面不是很直观,但更灵活。敲几个键,你可 54 | 以一次决定阶段或非阶段性提交几个文件,或查看并只选择特定文件的变更。作为另一 55 | 种选择,你还可以运行 *git commit --interactive* ,这个命令会在你操作完后自动 56 | 进行提交。 57 | 58 | === 索引:Git的中转区域 === 59 | 60 | 当目前为止,我们一直在忽略Git著名的“索引”概念,但现在我们必须面对它,以解释上 61 | 面发生的事情。索引是一个临时中转区。Git很少在你的项目和它的历史之间直接倒腾数据。 62 | 通常,Git先写数据到索引,然后拷贝索引中的数据到最终目的地。 63 | 64 | 例如, *commit -a* 实际上是一个两步过程。第一步把每个追踪文件当前状态的快照放 65 | 到索引中。第二步永久记录索引中的快照。 没有 *-a* 的提交只执行第二步,并且只在 66 | 运行不知何故改变索引的命令才有意义,比如 *git add* 。 67 | 68 | 通常我们可以忽略索引并假装从历史中直接读并直接写。在这个情况下,我们希望更好 69 | 地控制,因此我们操作索引。我们放我们变更的一些的快照到索引中,而不是所有的, 70 | 然后永久地记录这个被小心操纵的快照。 71 | 72 | === 别丢了你的HEAD === 73 | 74 | HEAD好似一个游标,通常指向最新提交,随最新提交向前移动。一些Git命令可让你来移动 75 | 它。 例如: 76 | 77 | $ git reset HEAD~3 78 | 79 | 这将立即将HEAD向回移动三个提交。这样所有Git命令都表现得好似你没有做那最后三个提交, 80 | 然而你的文件保持在现在的状态。具体应用参见帮助页。 81 | 82 | 但如何回到将来呢?过去的提交对将来一无所知。 83 | 84 | 如果你有原先Head的SHA1值,那么: 85 | 86 | $ git reset 1b6d 87 | 88 | 但假设你从来没有记下呢?别担心,在这些命令里面,Git会将原先的Head保存为一个叫做 89 | ORIG_HEAD的标记,你可以安全体面的返回那里: 90 | 91 | $ git reset ORIG_HEAD 92 | 93 | === HEAD捕猎 === 94 | 95 | 或许ORIG_HEAD还不够;或许你刚认识到你犯了个历史性的错误,你需要回到一个早已忘记 96 | 分支上一个远古的提交。 97 | 98 | 默认的,Git将会将一个提交保存至少两星期,即使你命令Git摧毁该提交所在的分支。难点 99 | 是找到相应的哈希值。你可以查看在.git/objects里所有的哈希值并尝试找到你期望的提 100 | 交。但这里有一个更简单的办法。 101 | 102 | Git把算出的提交哈希值记录在“.git/logs”。这个子目录引用包括所有分支上所有活 103 | 动的历史,同时文件HEAD显示它曾经有过的所有哈希值。后者可用来发现分支上一些不 104 | 小心丢掉提交的哈希值。 105 | 106 | 命令reflog为访问这些日志文件提供了友好的接口,可以试试 107 | 108 | $ git reflog 109 | 110 | 而不是从reflog拷贝粘贴哈希值,试一下: 111 | 112 | $ git checkout "@{10 minutes ago}" 113 | 114 | 或者捡出后五次访问过的提交,通过: 115 | 116 | $ git checkout "@{5}" 117 | 118 | 更多内容参见 *git help rev-parse* 的``Specifying Revisions''部分。 119 | 120 | 你或许期望去为已删除的提交设置一个更长的保存周期。例如: 121 | 122 | $ git config gc.pruneexpire "30 days" 123 | 124 | 意思是一个被删除的提交会在删除30天并运行 *git gc* 以后,被永久丢弃。 125 | 126 | 你或许还想关掉 *git gc* 的自动运行: 127 | 128 | $ git config gc.auto 0 129 | 130 | 在这种情况下提交将只在你手工运行 *git gc* 的情况下才永久删除。 131 | 132 | === 基于Git构建 === 133 | 134 | 依照真正的UNIX风格设计,Git允许其易于用作其他程序的底层组件,比如图形界面, 135 | Web界面,可选择的命令行界面,补丁管理工具,导入和转换工具等等。实际上,一些 136 | Git命令它们自己就是站在巨人肩膀上的脚本。通过一点修补,你可以定制Git适应你的 137 | 偏好。 138 | 139 | 一个简单的技巧是,用Git内建alias命令来缩短你最常使用命令: 140 | 141 | $ git config --global alias.co checkout 142 | $ git config --global --get-regexp alias # 显示当前别名 143 | alias.co checkout 144 | $ git co foo # 和“git checkout foo”一样 145 | 146 | 另一个技巧,在提示符或窗口标题上打印当前分支。调用: 147 | 148 | $ git symbolic-ref HEAD 149 | 150 | 显示当前分支名。在实际应用中,你可能最想去掉“refs/heads/”并忽略错误: 151 | 152 | $ git symbolic-ref HEAD 2> /dev/null | cut -b 12- 153 | 154 | 子目录 +contrib+ 是一个基于Git工具的宝库。它们中的一些命令不时的会被提升为官方 155 | 命令。在Debian和Ubuntu,这个目录位于 +/usr/share/doc/git-core/contrib+ 。 156 | 157 | 一个受欢迎的居民是 +workdir/git-new-workdir+ 。通过聪明的符号链接,这个脚本创 158 | 建一个新的工作目录,其历史与原来的仓库共享: 159 | 160 | $ git-new-workdir an/existing/repo new/directory 161 | 162 | 这个新的目录和其中的文件可被视为一个克隆,除了历史是共享的,两者的树会自动保持 163 | 同步,而不必合并,推入或拉出。 164 | 165 | === 大胆的特技 === 166 | 167 | 最近以来,Git努力使用户因意外而销毁数据变得更困难。但如若你知道你在做什么,你可 168 | 以突破为通用命令所设的保障措施。 169 | 170 | *Checkout*:未提交的变更会导致捡出失败。销毁你的变更,并无论如何都checkout一 171 | 个指定的提交,使用强制标记: 172 | 173 | $ git checkout -f HEAD^ 174 | 175 | 另外,如果你为捡出指定特别路径,那就没有安全检查了。提供的路径将被不加提示地 176 | 覆盖。如你使用这种方式的检出,要小心。 177 | 178 | *Reset*: 如有未提交变更重置也会失败。强制其通过,运行: 179 | 180 | $ git reset --hard 1b6d 181 | 182 | *Branch*: 引起变更丢失的分支删除会失败。强制删除,键入: 183 | 184 | $ git branch -D dead_branch # instead of -d 185 | 186 | 类似,通过移动试图覆盖分支,如果随之而来有数据丢失,那么覆盖也会失败。强制移动 187 | 分支,键入: 188 | 189 | $ git branch -M source target # 而不是 -m 190 | 191 | 不像checkout和重置,这两个命令将延迟数据销毁。这个变更仍然存储在.git的子目录里, 192 | 并且可以通过恢复.git/logs里的相应哈希值获取(参见上面 上面“HEAD猎捕”)。默 193 | 认情况下,这些数据会保存至少两星期。 194 | 195 | *Clean*: 一些Git命令拒绝执行,因为它们担心会重装未纳入管理的文件。如果你确信 196 | 所有未纳入管理的文件都是消耗品,那就无情地删除它们,使用: 197 | 198 | $ git clean -f -d 199 | 200 | 下次,那个讨厌的命令就会工作! 201 | 202 | === 阻止坏提交 === 203 | 204 | 愚蠢的错误会污染我的代码库。最可怕的是由于忘记 *git add* 而引起的文件丢失。较小 205 | 的错误则是行末追加空格而引发合并冲突:尽管危害少,我希望这些永远不要出现在公开 206 | 记录里。 207 | 208 | 不过我购买了傻瓜保险,通过使用一个_钩子_来提醒我这些问题: 209 | 210 | $ cd .git/hooks 211 | $ cp pre-commit.sample pre-commit # 对旧版本Git,先运行chmod +x 212 | 213 | 现在如果Git检测到无用的空格或未解决的合并冲突,它将放弃合并。 214 | 215 | 对本文档,我最终添加以下到 *pre-commit* 钩子的前面,来防止缺魂儿的事: 216 | 217 | if git ls-files -o | grep '\.txt$'; then 218 | echo FAIL! Untracked .txt files. 219 | exit 1 220 | fi 221 | 222 | 一部分其他的Git操作也支持钩子;参见 *git help hooks* 。我们早先激活了作为例子的 223 | *post-update* 钩子,当讨论基于HTTP的Git的时候。无论head何时移动,这个钩子都会 224 | 运行。例子中的脚本post-update会在Git面对并不知晓的传输协议,诸如HTTP时,更新自己的 225 | 资料库,以确保它有能力交换所需的文件。 226 | -------------------------------------------------------------------------------- /zh_cn/history.txt: -------------------------------------------------------------------------------- 1 | == 关于历史 == 2 | 3 | Git分布式本性使得历史可以轻易编辑。但你若篡改过去,需要小心:只重写你独自拥有 4 | 的那部分。正如民族间会无休止的争论谁犯下了什么暴行一样,如果在另一个人的克隆 5 | 里,历史版本与你的不同,当你们的树互操作时,你们会遇到一致性方面的问题。 6 | 7 | 一些开发人员强烈地感到历史应该永远不变,不好的部分也不变,所有都不变。另一些觉 8 | 得代码树在向外发布之前,应该整得漂漂亮亮的。Git同时支持两者的观点。像克隆,分 9 | 支和合并一样,重写历史只是Git给你的另一强大功能,至于如何明智地使用它,那是你 10 | 的事了。 11 | 12 | === 我认错 === 13 | 14 | 刚提交,但你期望你输入的是一条不同的信息?那么键入: 15 | 16 | $ git commit --amend 17 | 18 | 来改变上一条信息。意识到你还忘记了加一个文件?运行git add来加,然后运行上面的 19 | 命令。 20 | 21 | 希望在上次提交里包括多一点的改动?那么就做这些改动并运行: 22 | 23 | $ git commit --amend -a 24 | 25 | === 更复杂情况 === 26 | 27 | 假设上面的问题再糟糕十倍,比如在漫长的时间里我们提交了一堆,但你不太喜欢他们的 28 | 组织方式,而且一些提交信息需要重写。那么键入: 29 | 30 | $ git rebase -i HEAD~10 31 | 32 | 则最后的10个提交会出现在你喜爱的$EDITOR(即通过设置EDITOR环境变量决定使用哪个 33 | 文本编辑器)。一个例子: 34 | 35 | pick 5c6eb73 Added repo.or.cz link 36 | pick a311a64 Reordered analogies in "Work How You Want" 37 | pick 100834f Added push target to Makefile 38 | 39 | 不像git log,列表中的提交是旧的在前,新的在后。在上面的列表中,5c6eb73是最老的 40 | 提交,100834是最新的提交。接下来可以在$EDITOR中: 41 | 42 | - 通过删除行来移去提交。 43 | - 通过对几行记录重新排序,来重组提交顺序。 44 | - 替换 `pick` 命令: 45 | * `edit` 标记一个提交需要修订。 46 | * `reword` 改变日志信息。 47 | * `squash` 将一个提交与其前一个合并。 48 | * `fixup` 将一个提交与其前一个合并,并丢弃日志信息。 49 | 50 | 比如,将第二个提交的`pick`修改为`squash`: 51 | pick 5c6eb73 Added repo.or.cz link 52 | squash a311a64 Reordered analogies in "Work How You Want" 53 | pick 100834f Added push target to Makefile 54 | 55 | 保存退出,则Git会把a311a64合并进5c6eb73。想象一下“挤压”动作,squash的作用就是 56 | 把一个提交“挤压”进前一个提交。 57 | 58 | “挤压”的同时,Git合并了两个提交的日志信息供编辑。比较一下*fixup*命令,其直接 59 | 扔掉“挤压“后合并的日志信息。 60 | 61 | 如果你把一个提交标记为*edit*,Git会带你回到这个提交点,你可以修改当时的提交信息 62 | ,甚至可以增加新的提交。修改完毕后执行: 63 | 64 | $ git rebase --continue 65 | 66 | 直到遇到下一个*edit*标记点,Git会回放所有遇到的提交。 67 | 68 | 也可以放弃修改: 69 | 70 | $ git rebase --abort 71 | 72 | 这样尽早提交,经常提交:你之后还可以用rebase来规整。 73 | 74 | === 本地变更之后 === 75 | 76 | 你正在一个活跃的项目上工作。随着时间推移,你做了几个本地提交,然后你使用合并 77 | 与官方版本同步。在你准备好提交到中心分支之前,这个循环会重复几次。 78 | 79 | 但现在你本地Git克隆掺杂了你的改动和官方改动。你更期望在变更列表里,你所有的变 80 | 更能够连续列出。 81 | 82 | 这就是上面提到的 *git rebase* 所做的工作。在很多情况下你可以使用 *--onto* 标 83 | 记以避免交互。 84 | 85 | 另外参见 *git help rebase* 以获取这个让人惊奇的命令更详细的例子。你可以拆分提 86 | 交。你甚至可以重新组织一棵树的分支。 87 | 88 | 要小心的是,rebase指令非常强悍,对于复杂的rebase,最好首先使用*git clone*备份 89 | 一下。 90 | 91 | === 重写历史 === 92 | 93 | 偶尔,你需要做一些代码控制——好比从正式的照片中去除一些人一样——你需要从历史记录 94 | 里面彻底的抹掉他们。例如,假设我们要发布一个项目,但由于一些原因,项目中的某 95 | 个文件不能公开。或许我把我的信用卡号记录在了一个文本文件里,而我又意外的把它 96 | 加入到了这个项目中。仅仅删除这个文件是不够的,因为从别的提交记录中还是可以访 97 | 问到这个文件。因此我们必须从所有的提交记录中彻底删除这个文件。 98 | 99 | $ git filter-branch --tree-filter 'rm top/secret/file' HEAD 100 | 101 | 参见 *git help filter-branch* ,那里讨论了这个例子并给出一个更快的方法。一般 102 | 地, *filter-branch* 允许你使用一个单一命令来大范围地更改历史。 103 | 104 | 此后,+.git/refs/original+目录描述操作之前的状态。检查命令 *filter-branch* 的 105 | 确做了你想要做的,然后删除此目录,如果你想运行多次filter-branch命令。 106 | 107 | 最后,如果你想之后和修订过的版本交互的话,记得用你修订过的版本替换你的项目克隆。 108 | 109 | === 制造历史 === 110 | 111 | [[makinghistory]] 112 | 想把一个项目迁移到Git吗?如果这个项目是在用比较有名气的系统,那可以使用一些其 113 | 他人已经写好的脚本,把整个项目历史记录导出来放到Git里。 114 | 115 | 否则,查一下 *git fast-import* ,这个命令会从一个特定格式的文本读入,从头来创 116 | 建Git历史记录。通常可以用这个命令很快写一个脚本运行一次,一次迁移整个项目。 117 | 118 | 作为一个例子,粘贴以下所列到临时文件,比如/tmp/history: 119 | 120 | ---------------------------------- 121 | commit refs/heads/master 122 | committer Alice <alice@example.com> Thu, 01 Jan 1970 00:00:00 +0000 123 | data <<EOT 124 | Initial commit. 125 | EOT 126 | 127 | M 100644 inline hello.c 128 | data <<EOT 129 | #include <stdio.h> 130 | 131 | int main() { 132 | printf("Hello, world!\n"); 133 | return 0; 134 | } 135 | EOT 136 | 137 | 138 | commit refs/heads/master 139 | committer Bob <bob@example.com> Tue, 14 Mar 2000 01:59:26 -0800 140 | data <<EOT 141 | Replace printf() with write(). 142 | EOT 143 | 144 | M 100644 inline hello.c 145 | data <<EOT 146 | #include <unistd.h> 147 | 148 | int main() { 149 | write(1, "Hello, world!\n", 14); 150 | return 0; 151 | } 152 | EOT 153 | 154 | ---------------------------------- 155 | 156 | 之后从这个临时文件创建一个Git仓库,键入: 157 | 158 | $ mkdir project; cd project; git init 159 | $ git fast-import --date-format=rfc2822 < /tmp/history 160 | 161 | 你可以从这个项目checkout出最新的版本,使用: 162 | 163 | $ git checkout master . 164 | 165 | 命令*git fast-export* 可将任意仓库转换成 *git fast-import* 格式,你可以研究其输 166 | 出来写新的导出程序, 或以人类可以理解的格式转移仓库。的确,这些命令可以通过只接受文 167 | 本的渠道来发送仓库文件。 168 | 169 | 170 | === 哪儿错了? === 171 | 172 | 你刚刚发现程序里有一个功能出错了,而你十分确定几个月以前它运行的很正常。天啊! 173 | 这个臭虫是从哪里冒出来的?要是那时候能按照开发的内容进行过测试该多好啊。 174 | 175 | 现在说这个已经太晚了。然而,即使你过去经常提交变更,Git还是可以精确的找出问题所在: 176 | 177 | $ git bisect start 178 | $ git bisect bad HEAD 179 | $ git bisect good 1b6d 180 | 181 | Git从历史记录中检出一个中间的状态。在这个状态上测试功能,如果还是有问题: 182 | 183 | $ git bisect bad 184 | 185 | 如果可以工作了,则把"bad"替换成"good"。Git会再次帮你找到一个以确定的好版本和 186 | 坏版本之间的状态,通过这种方式缩小范围。经过一系列的迭代,这种二分搜索会帮你 187 | 找到导致这个错误的那次提交。一旦完成了问题定位的调查,你可以返回到原始状态, 188 | 键入: 189 | 190 | $ git bisect reset 191 | 192 | 不需要手工测试每一次改动,执行如下命令可以自动的完成上面的搜索: 193 | 194 | $ git bisect run my_script 195 | 196 | Git使用指定命令(通常是一个一次性的脚本)的返回值来决定一次改动是否是正确的: 197 | 命令退出时的代码0代表改动是正确的,125代表要跳过对这次改动的检查,1到127之间 198 | 的其他数值代表改动是错误的。返回负数将会中断整个bisect的检查。 199 | 200 | 你还能做更多的事情: 帮助文档解释了如何展示bisects, 检查或重放bisect的日志,并 201 | 可以通过排除对已知正确改动的检查,得到更好的搜索速度。 202 | 203 | === 谁让事情变糟了? === 204 | 205 | 和其他许多版本控制系统一样,Git也有一个"blame"命令: 206 | 207 | $ git blame bug.c 208 | 209 | 这个命令可以标注出一个指定的文件里每一行内容的最后修改者,和最后修改时间。但 210 | 不像其他版本控制系统,Git的这个操作是在线下完成的,它只需要从本地磁盘读取信息。 211 | 212 | === 个人经验 === 213 | 214 | 在一个中心版本控制系统里,历史的更改是一个困难的操作,并且只有管理员才有权这 215 | 么做。没有网络,克隆,分支和合并都没法做。像一些基本的操作如浏览历史,或提交 216 | 变更也是如此。在一些系统里,用户使用网络连接仅仅是为了查看他们自己的变更,或 217 | 打开文件进行编辑。 218 | 219 | 中心系统排斥离线工作,也需要更昂贵的网络设施,特别是当开发人员增多的时候。最 220 | 重要的是,所有操作都一定程度变慢,一般在用户避免使用那些能不用则不用的高级命 221 | 令时。在极端的情况下,即使是最基本的命令也会变慢。当用户必须运行缓慢的命令的 222 | 时候,由于工作流被打断,生产力就会降低。 223 | 224 | 我有这方面的一手经验。Git是我使用的第一个版本控制系统。我很快学会适应了它,并 225 | 使用了它提供的许多功能。我简单地假设其他系统也是相似的:选择一个版本控制系统应 226 | 该和选择一个编辑器或浏览器没啥两样。 227 | 228 | 在我之后被迫使用中心系统的时候,我被震惊到了。我那有些脆弱的网络没给Git带来 229 | 大麻烦,但是当它需要像本地硬盘一样稳定工作的时候,它使开发变得困难重重。另 230 | 外,我发现我自己有选择地避免使用特定的命令,以避免踏雷,这极大地影响了我,使 231 | 我不能按照我喜欢的方式工作。 232 | 233 | 当我不得不运行一个速度缓慢的命令时,这种等待极大地破坏了我思绪的连续性。在等 234 | 待服务器通讯完成的时候,我选择做其他的事情以度过这段时光,比如查看邮件或写其 235 | 他的文档。当我返回我原先的工作场景的时候,这个命令早已结束,并且我还需要浪费 236 | 时间试图记起我之前正在做什么。人类并不擅长场景间的切换。 237 | 238 | 还有一个有意思的大众悲剧效应:预料到网络拥挤,为了减少将来的等待时间,每个人 239 | 将比以往消费更多的带宽在各种操作上。大家共同的努力结果加剧了拥挤,这等于是鼓 240 | 励个人下次消费更多带宽以避免更长的等待时间。 241 | -------------------------------------------------------------------------------- /zh_cn/intro.txt: -------------------------------------------------------------------------------- 1 | == 入门 == 2 | 3 | 我将用类比的方式来介绍版本控制的概念。更严谨的解释参见 4 | http://en.wikipedia.org/wiki/Revision_control[维基百科版本修订控制条目]。 5 | 6 | === 工作是玩 === 7 | 8 | 我从小就玩电脑游戏,直到今天;不过我只是在长大后才开始使用版本控制系统。我 9 | 想我并不是个例,所以拿两者工作方式进行类比,可使一些概念更易解释,也易于理解。 10 | 11 | 编写代码,或编辑文档,和玩游戏差不多。在你做出了很多进展之后,你最好保存一下。 12 | 要做到这点,点击你所信任的编辑器保存按钮就好了。 13 | 14 | 但这将覆盖老版本。就像那些学校里玩的老游戏,只有一个存档:你确实可以保存,但 15 | 你不能回到更老的状态了。这真让人扫兴,因为那个状态可能恰好保存了这个游戏特别 16 | 有意思一关,说不定哪天你想再玩一下呢。或者更糟糕的,你当前的保存是个必败局, 17 | 这样你就不得不从头开始玩了。 18 | 19 | === 版本控制 === 20 | 21 | 在编辑的时候,如果想保留旧版本,你可以将文件“另存为”一个不同的文件,或在保 22 | 存之前将文件拷贝到别处。你可能会压缩这些文件以节省空间。这是一个初级的依赖 23 | 手工进行的版本控制方式。游戏软件在这块早就做了很多提高,很多游戏都提供基于 24 | 时间戳的多个存档槽。 25 | 26 | 让我们看看稍稍复杂的情况。比如你有很多放在一起的文件,比如项目源码,或网站文 27 | 件。现在如你想保留旧版本,你不得不把整个目录存档。手工保存多个版本很不方便, 28 | 而且很快会耗费巨大。 29 | 30 | 在一些电脑游戏里,一个存档真的包含在一个充满文件的目录里。这些游戏为玩家屏蔽 31 | 了这些细节,并提供一个方便易用的界面来管理该目录的不同版本。 32 | 33 | 版本控制系统也没有不同。两者提供友好的用户界面,来管理目录里的东西。你可以频 34 | 繁保存,也可以之后加载任一存档。不像大多数计算机游戏,版本控制系统通常精于节 35 | 省存储空间。一般情况下,如果两个版本间只有少数文件的变更,每个文件的变更也不 36 | 大,那就只存储差异的部分,而不是把全部拷贝的都保存下来,以节省存储空间。 37 | 38 | === 分布控制 === 39 | 40 | 现在设想一个很难的游戏。太难打了,以至于世界各地很多骨灰级玩家决定组队,分享 41 | 他们游戏存档以攻克它。Speedrun就是现实中的例子:在同一个游戏里,玩家们分别 42 | 攻克不同的等级,协同工作以创造惊人战绩。 43 | 44 | 你如何搭建一个系统,使得他们易于得到彼此的存档?并易于上载新的存档? 45 | 46 | 在过去,每个项目都使用中心式版本控制。某个服务器上放所有保存的游戏记录。其他 47 | 人就不用再做备份了。每个玩家在他们机器上最多保留几个游戏记录。当一个玩家想更 48 | 新至最新进度时候,他们需要把这个进度从主服务器下载下来,玩一会儿,保存并上载 49 | 到主服务器以供其他人使用。 50 | 51 | 假如一个玩家由于某种原因,想得到一个较旧版本的游戏进度该怎么办?或许当前保存的 52 | 游戏是一个注定的败局,因为某人在第三级忘记捡某个物品;他们希望能找到最近一个 53 | 可以完成的游戏记录。或者他们想比较两个旧版本间的差异,来估算某个特定玩家干了 54 | 多少活。 55 | 56 | 查看旧版本的理由有很多,但检查的办法都是一样的。他们必须去中心服务器索要那个 57 | 旧版本的记录。需要的旧版本越多,和服务器的交互就越多。 58 | 59 | Git是新一代的版本控制系统中的一员,它的特点是分布式的,广义上也可以被看作是一 60 | 种中心式系统。从主服务器下载时,玩家会得到所有保存的记录,而不仅是最新版。这 61 | 看来,玩家们好像把中心服务器做了个镜像。 62 | 63 | 最初的克隆操作可能比较费时,特别当存档有很长历史的时候,但从长远看这是值得的。一 64 | 个显而易见的好处是,当查看一个旧版本时,就不再需要和中心服务器通讯了。 65 | 66 | === 一个误区 === 67 | 68 | 一个很常见的错误观念是,分布式系统不适合需要官方中心仓库的项目。这与事实并不 69 | 相符。给谁照相也不会偷走他们的灵魂。类似地,克隆主仓库并不降低它的重要性。 70 | 71 | 一般来说,一个中心版本控制系统能做的任何事,一个良好设计的分布式系统都能做得 72 | 更好。网络资源总要比本地资源耗费更昂贵。不过我们应该在稍后分析分布式方案的缺点, 73 | 这样人们才不会按照习惯做出错误的比较。 74 | 75 | 一个小项目或许只需要分布式系统提供的一小部分功能,但是,在项目很小的时候,就理应 76 | 使用规划并不好的系统?就好比说,在计算较小数目的时候应该使用罗马数字? 77 | 78 | 而且,你的项目的增长可能会超出你最初的预期。从一开始就使用Git好似带着一把瑞士 79 | 军刀,尽管你很多时候只是用它来开开瓶盖。某天你迫切需要一把改锥,你就会庆幸你 80 | 所有的不单单是一个启瓶器。 81 | 82 | === 合并冲突 === 83 | 84 | 对于这个话题,电脑游戏的类比显得不够用。那让我们再来看看文档编辑的情况吧。 85 | 86 | 假设Alice在文档开头插入一行,并且Bob在文档末尾添加一行。他们都上传了他们的改 87 | 动。大多数系统将自动给出一个合理的处理方式:接受且合并他们的改动,这样Alice和 88 | Bob两人的改动都会生效。 89 | 90 | 现在假设Alice和Bob对文件的同一行做了不同的改动。如果没有人工参与的话,这个冲 91 | 突是无法解决的。第二个人在上载文件时,会收到 _合并冲突_ 的通知,要么用一个人 92 | 的改动覆盖另一个的,要么完全修订这一行。 93 | 94 | 更复杂的情况也可能出现。版本控制系统自己处理相对简单的情况,把困难的情况留给 95 | 人来处理。它们的行为通常是可配置的。 96 | -------------------------------------------------------------------------------- /zh_cn/multiplayer.txt: -------------------------------------------------------------------------------- 1 | == 多人Git == 2 | 3 | 我最初在一个私人项目上使用Git,我是那个项目的唯一的开发者。在与Git分布式特性 4 | 有关的命令中,我只用到了 *pull* 和 *clone*,以此即可在不同地方保持项目同步。 5 | 6 | 后来我想用Git发布我的代码,并且包括其他贡献者的变更。我不得不学习如何管理有来 7 | 自世界各地的多个开发的项目,幸运的是,这是Git的长处,也可以说是其存在的理由。 8 | 9 | === 我是谁? === 10 | 11 | 每个提交都有一个作者姓名和电子信箱,这显示在 *git log* 里。Git使用系统默认 12 | 设定来填充这些信息。要设定这些信息,键入: 13 | 14 | $ git config --global user.name "John Doe" 15 | $ git config --global user.email johndoe@example.com 16 | 17 | 去掉global选项设定则只对当前仓库生效。 18 | 19 | === Git在SSH, HTTP上的使用 === 20 | 21 | 假设你有ssh访问权限,可以访问一个网页服务器,但上面并没有安装Git。尽管比它的 22 | 原生协议效率低,Git也是可以通过HTTP来进行通信的。 23 | 24 | 在你的帐户下,下载,编译并安装Git,并在你的网页目录里创建一个Git仓库: 25 | 26 | $ GIT_DIR=proj.git git init 27 | $ cd proj.git 28 | $ git --bare update-server-info 29 | $ cp hooks/post-update.sample hooks/post-update 30 | 31 | 对较老版本的Git,只拷贝还不够,你还要运行: 32 | 33 | $ chmod a+x hooks/post-update 34 | 35 | 现在你可以通过SSH从随便哪个克隆发布你的最新版本: 36 | 37 | $ git push web.server:/path/to/proj.git master 38 | 39 | 而随便任何人都可以通过如下命令来取得你的项目: 40 | 41 | $ git clone http://web.server/proj.git 42 | 43 | === Git在随便什么上的使用 === 44 | 45 | 若想不依赖服务器,甚至无需网络连接来同步仓库?需要在紧急时期凑合一下?我们 46 | 已经看过<<makinghistory, *git fast-export* 和 *git fast-import* 可以转换 47 | 资源库到一个单一文件以及转回来>>。 我们可以通过任何媒介,来来回回传送这些文件 48 | 以同步git仓库。但一个更有效率的工具是 *git bundle* 。 49 | 50 | 发送者创建一个“文件包”: 51 | 52 | $ git bundle create somefile HEAD 53 | 54 | 然后传输这个文件包, +somefile+ ,给某个其他参与者:电子邮件,优盘,一个 55 | *xxd* 打印品和一个OCR扫描仪,通过电话读字节,狼烟,等等。接收者通过键入如下命 56 | 令从文件包获取提交: 57 | 58 | $ git pull somefile 59 | 60 | 接收者甚至可以在一个空仓库做这个。不考虑大小, +somefile+ 可以包含整个原先 61 | git仓库。 62 | 63 | 在较大的项目里,可以通过只打包其他仓库缺少的变更来消除存储浪费。例如,假设提交 64 | ``1b6d...''是两个参与者共享的最近提交: 65 | 66 | $ git bundle create somefile HEAD ^1b6d 67 | 68 | 如果提交频繁,人们可能很容易忘记刚发送了哪个提交。帮助页面建议使用标签解决这个问 69 | 题。即,在你发了一个文件包后,键入: 70 | 71 | $ git tag -f lastbundle HEAD 72 | 73 | 并创建较新文件包,使用: 74 | 75 | $ git bundle create newbundle HEAD ^lastbundle 76 | 77 | === 补丁:全球货币 === 78 | 79 | 补丁是变更的文本形式,易于计算机理解,人也类似。补丁可以通吃。你可以给开发者电 80 | 邮一个补丁,不用管他们用的什么版本控制系统,只要对方可以读电子邮件,他们就能看 81 | 到你的修改。类似的,在你这边,你只需要一个电子邮件帐号,而不必搭建一个在线的Git 82 | 仓库。 83 | 84 | 回想一下第一章: 85 | 86 | $ git diff 1b6d > my.patch 87 | 88 | 输出是一个补丁,可以粘贴到电子邮件里用以讨论。在一个Git仓库,键入: 89 | 90 | $ git apply < my.patch 91 | 92 | 来打这个补丁。 93 | 94 | 在更正式些的设置里,当作者名字以及或许签名应该被记录下的时候,为过去某一刻生成 95 | 补丁,键入: 96 | 97 | $ git format-patch 1b6d 98 | 99 | 结果文件可以给 *git-send-email* 发送,或者手工发送。你也可以指定一个提交范围: 100 | 101 | $ git format-patch 1b6d..HEAD^^ 102 | 103 | 在接收一端,保存邮件到一个文件,然后键入: 104 | 105 | $ git am < email.txt 106 | 107 | 这就打了补丁并创建了一个提交,其自动包含了诸如作者之类的信息。 108 | 109 | 使用浏览器的邮件客户端,在保存补丁为文件之前,你可能需要建一个按钮,看看邮件内 110 | 容原来的原始形式。 111 | 112 | 对基于mbox的邮件客户端有些微不同,但如果你在使用的话,你可能是那种能轻易找出 113 | 答案的那种人,不用读教程。 114 | 115 | === 对不起,移走了 === 116 | 117 | 克隆一个仓库后,运行 *git push* 或 *git pull* 将自动推到或从原先的仓库URL拉出 118 | 新内容。Git如何做这个呢?秘密在于同克隆一起创建的配置选项里面。让我们看一下: 119 | 120 | $ git config --list 121 | 122 | 选项 +remote.origin.url+ 控制仓库的URL源;``origin'' 是给源仓库的昵称。和 123 | ``master'' 分支的惯例一样,我们可以改变或删除这个昵称,但通常没有理由这么做。 124 | 125 | 如果原先仓库移走,我们可以更新URL,通过: 126 | 127 | $ git config remote.origin.url git://new.url/proj.git 128 | 129 | 选项 +branch.master.merge+ 指定 *git pull* 里的默认远端分支。在初始克隆的时候, 130 | 它被设为原仓库的当前分支,因此即使原仓库之后挪到一个不同的分支,后来的 131 | pull也将忠实地跟着原来的分支。 132 | 133 | 这个选项只使用我们初次克隆的仓库,它的值记录在选项 +branch.master.remote+ 134 | 。如果我们从其他仓库拉入,我们必须显示指定我们想要哪个分支: 135 | 136 | $ git pull git://example.com/other.git master 137 | 138 | 以上也解释了为什么我们较早一些push和pull的例子没有参数。 139 | 140 | === 远端分支 === 141 | 142 | 当你克隆了一个仓库,你也克隆了它的所有分支。你或许没有注意到这点,因为Git将它们 143 | 隐藏起来了:你必须明确地要求。这使得远端仓库里的分支不至于干扰你的分支,也使 144 | Git对初学者稍稍容易些。 145 | 146 | 列出远端分支,使用: 147 | 148 | $ git branch -r 149 | 150 | 你应该看到类似: 151 | 152 | origin/HEAD 153 | origin/master 154 | origin/experimental 155 | 156 | 这显示了远端仓库的分支和HEAD,可以用在常用的Git命令里。例如,假设你已经做了 157 | 很多提交,并希望和最后取到的版本比较一下。你可以搜索适当的SHA1哈希值,但使用 158 | 下面命令更容易些: 159 | 160 | $ git diff origin/HEAD 161 | 162 | 或你可以看看``experimental''分支都有啥: 163 | 164 | $ git log origin/experimental 165 | 166 | === 多远端 === 167 | 168 | 假设另两个开发在同一个项目上工作,我们希望保持两个标签。我们可以同时跟踪多个 169 | 仓库: 170 | 171 | $ git remote add other git://example.com/some_repo.git 172 | $ git pull other some_branch 173 | 174 | 现在我们已经合并到第二个仓库的一个分支,并且我们已容易访问所有仓库的所有 175 | 分支。 176 | 177 | $ git diff origin/experimental^ other/some_branch~5 178 | 179 | 但如果为了不影响自己的工作,我们只想比较他们的变更怎么办呢?换句话说,我们想 180 | 检查一下他们的分支,又不使他们的变更入侵我们的工作目录。这里我们并不要运行pull 181 | 命令,而是运行: 182 | 183 | $ git fetch # Fetch from origin, the default. 184 | $ git fetch other # Fetch from the second programmer. 185 | 186 | 这只是获取历史。尽管工作目录维持不变,我们可以参考任何仓库的任何分支,使用 187 | 一个Git命令,因为我们现在有一个本地拷贝。 188 | 189 | 回想一下,在幕后,一个pull是简单地一个 *fetch* 然后 *merge* 。通常,我们 190 | *pull* 因为我们想在获取后合并最近提交;这个情况是一个值得注意的例外。 191 | 192 | 关于如何去除远端仓库,如何忽略特定分支等更多,参见 *git help remote* 。 193 | 194 | === 我的喜好 === 195 | 196 | 对我手头的项目,我喜欢贡献者去准备仓库,这样我可以从其中拉。一些Git伺服让你 197 | 点一个按钮,拥有自己的分叉项目。 198 | 199 | 在我获取一个树之后,我运行Git命令去浏览并检查这些变更,理想情况下这些变更组织 200 | 良好,描述良好。我合并这些变更,也或许做些编辑。直到满意,我才把变更推入主资 201 | 源库。 202 | 203 | 尽管我不经常收到贡献,我相信这个方法扩展性良好。参见 204 | http://torvalds-family.blogspot.com/2009/06/happiness-is-warm-scm.html[ 这篇 205 | 来自Linus Torvalds的博客 ] 206 | 207 | 呆在Git的世界里比补丁文件稍更方便,因为不用我将补丁转换到Git提交。更进一步, 208 | Git处理诸如作者姓名和信箱地址的细节,还有时间和日期,以及要求作者描述他们的提 209 | 交。 210 | -------------------------------------------------------------------------------- /zh_cn/preface.txt: -------------------------------------------------------------------------------- 1 | = Git 魔法 = 2 | Ben Lynn 3 | 2007年8月 4 | 5 | == 前言 == 6 | 7 | http://git.or.cz/[Git] 堪称版本控制瑞士军刀。这个可靠、多才多艺、用途多样的校 8 | 订工具异常灵活,以致不易掌握,更别说精通了。 9 | 10 | 正如Arthur C. Clarke所说,足够先进的技术与魔法无二。这是学习Git的好办法:新手 11 | 不妨忽略Git的内部机理,只当小把戏玩,借助Git其奇妙的能力,逗逗朋友,气气敌人。 12 | 13 | 为了不陷入细节,我们对特定功能提供大面上的讲解。在反复应用之后,慢慢地你会理 14 | 解每个小技巧如何工作,以及如何组合这些技巧以满足你的需求。 15 | 16 | .翻译 17 | 18 | - link:/\~blynn/gitmagic/intl/zh_cn/[简体中文]: 俊杰,萌和江薇。 19 | link:/~blynn/gitmagic/intl/zh_tw/[正体中文] 由 + cconv -f UTF8-CN -t 20 | UTF8-TW + 转换。 21 | - link:/~blynn/gitmagic/intl/fr/[法文]: Alexandre Garel。也在 22 | http://tutoriels.itaapy.com/[itaapy]。 23 | - link:/~blynn/gitmagic/intl/de/[德文]: Benjamin Bellee和Armin Stebich;也在 24 | http://gitmagic.lordofbikes.de/[Armin的网站]。 25 | - http://www.slideshare.net/slide_user/magia-git[葡萄牙文]: Leonardo 26 | Siqueira Rodrigues 27 | [http://www.slideshare.net/slide_user/magia-git-verso-odt[ODT版]]。 28 | - link:/~blynn/gitmagic/intl/ru/[俄文]: Tikhon Tarnavsky, Mikhail Dymskov, 29 | 和其他人。 30 | - link:/~blynn/gitmagic/intl/es/[西班牙]: Rodrigo Toledo和Ariset Llerena 31 | Tapia。 32 | - link:/~blynn/gitmagic/intl/vi/[越南文]: Trần Ngọc Quân; 也在 33 | http://vnwildman.users.sourceforge.net/gitmagic.html[他的网站]. 34 | 35 | .其它版本 36 | 37 | - link:book.html[单一文件]: 纯HTML,无CSS。 38 | - link:book.pdf[PDF文件]: 打印效果好. 39 | - http://packages.debian.org/gitmagic[Debian包], 40 | http:://packages.ubuntu.com/gitmagic[Ubuntu包]: 本站快速本地拷贝。如果 41 | http://csdcf.stanford.edu/status/[下线了]会方便些。 42 | - http://www.amazon.com/Git-Magic-Ben-Lynn/dp/1451523343/[纸质书 43 | [Amazon.com]]: 64 页, 15.24cm x 22.86cm, 黑白。 没有电子设备的时候会方便些。 44 | 45 | === 致谢! === 46 | 47 | 那么多人对本文档的翻译让我受宠若惊。他们的付出拓宽了读者群,我非常感激。 48 | 49 | Dustin Sallings、Alberto Bertogli、James Cameron、Douglas Livingstone、 50 | Michael Budde、Richard Albury、Tarmigan、 Derek Mahar、Frode Aannevik、 51 | Keith Rarick、 Andy Somerville、 Ralf Recker、 Øyvind A. Holm、 Miklos Vajna、 52 | Sébastien Hinderer、 Thomas Miedema、 Joe Malin、 和Tyler Breisacher对本文档 53 | 正确性和优化做出了贡献。 54 | 55 | François Marier维护Debian包,该Debian包起初由Daniel Baumann创建。 56 | 57 | 感谢其他很多提供帮助和鼓励的人。名单太长了我无法一一写下。 58 | 59 | 如果我不小心把你的名字落下,请告诉我或者发一个补丁。 60 | 61 | .免费Git伺服 62 | 63 | - http://repo.or.cz/[http://repo.or.cz/] 为自由项目提供服务。第一个Git服务器。 64 | 由最早的Git开发人员创建和维护。 65 | - http://gitorious.org/[http://gitorious.org/] 是另一个Git服务站点,为开源项 66 | 目提供服务。 67 | - http://github.com/[http://github.com/] 开源项目免费,私有项目收钱。 68 | 69 | 感谢以上站点为本文档提供伺服服务。 70 | 71 | === 许可 === 72 | 73 | 本指南在http://www.gnu.org/licenses/gpl-3.0.html[ GNU通用公共许可协议版本3 ] 74 | 之下发布。很自然,源码保存在一个Git仓库里,可以通过以下命令获得源码: 75 | 76 | $ git clone git://repo.or.cz/gitmagic.git # 创建“gitmagic”目录. 77 | 78 | 或从以下镜像得到: 79 | 80 | $ git clone git://github.com/blynn/gitmagic.git 81 | $ git clone git://gitorious.org/gitmagic/mainline.git 82 | 83 | -------------------------------------------------------------------------------- /zh_cn/secrets.txt: -------------------------------------------------------------------------------- 1 | == 揭开面纱 == 2 | 3 | 我们揭开Git神秘面纱,往里瞧瞧它是如何创造奇迹的。我会跳过细节,若要更深入的了解Git 4 | 工作原理,可参见 http://www.kernel.org/pub/software/scm/git/docs/user-manual.html[ 用 5 | 户手册]。 6 | 7 | === 大象无形 === 8 | 9 | Git怎么这么谦逊寡言呢?除了偶尔提交和合并外,你可以如常工作,就像不知道版本控 10 | 制系统存在一样。那就是,直到你需要它,并且感到时间合适的时候以外,Git都只是默 11 | 默在后台看顾着你。 12 | 13 | 其他版本控制系统强迫你与繁文缛节和官僚主义不断斗争。文件的权限可能是只读的, 14 | 除非你明确地告诉中心服务器哪些文件你打算编辑。即使最基本的命令,随着用户数目 15 | 的增多,也会慢的像爬一样。中心服务器可能正跟踪什么人,什么时候check out了什么 16 | 代码。当网络连接断了的时候,你就遭殃了。开发人员不断地与这些版本控制系统的种 17 | 种限制作斗争。一旦网络或中心服务器瘫痪,工作就嘎然而止。 18 | 19 | 与之相反,Git简单地在你工作目录下的`.git`目录保存你项目的历史。这是你自己的历 20 | 史拷贝,因此你可以保持离线,直到你想和他人沟通为止。你拥有你的文件命运完全的 21 | 控制权,因为Git可以轻易在任何时候从`.git`重建一个曾经保存过的状态。 22 | 23 | === 数据完整性 === 24 | 25 | 很多人把加密和保持信息机密关联起来,但一个同等重要的目标是保证信息安全。合理 26 | 使用哈希加密功能可以防止无意或有意的数据损坏行为。 27 | 28 | 一个SHA1哈希值可被认为是一个唯一的160位ID数,用它可以唯一标识你一生中遇到的每 29 | 个字节串。 实际上不止如此:每个字节串可供任何人用好多辈子。 30 | 31 | 对一个文件而言,其整体内容的哈希值可以被看作这个文件的唯一标识ID数。 32 | 33 | 因为一个SHA1哈希值本身也是一个字节串,我们可以哈希包括其他哈希值的字节串。这 34 | 个简单的观察出奇地有用:查看“哈希链”。我们之后会看Git如何利用这一点来高效地 35 | 保证数据完整性。 36 | 37 | 简言之,Git把数据保存在`.git/objects`子目录,那里看不到正常文件名,相反你只 38 | 看到ID。通过用ID作为文件名,加上一些文件锁和时间戳技巧,Git把任意一个原始的文 39 | 件系统转化为一个高效而稳定的数据库。 40 | 41 | === 智能 === 42 | 43 | Git是如何知道你重命名了一个文件,即使你从来没有明确提及这个事实?当然,你或许 44 | 是运行了 *git mv* ,但这个命令和 *git add* 紧随 *git rm* 是完全一样的。 45 | 46 | Git启发式地找出相连版本之间的重命名和拷贝。实际上,它能检测文件之间代码块的移 47 | 动或拷贝!尽管它不能覆盖所有的情况,但它已经做的很好了,并且这个功能也总在改 48 | 进中。如果它在你那儿不工作的话,可以尝试打开开销更高的拷贝检测选项,并考虑升 49 | 级。 50 | 51 | === 索引 === 52 | 53 | 对每个加入库中管理的文件,Git都会在一个名为“index”的文件里记录统计信息,诸如 54 | 大小,创建时间和最后修改时间。为了确定文件是否被更改,Git会将当前统计信息同那 55 | 些在索引里的统计信息对比。如果一致,那Git就跳过该文件。 56 | 57 | 因为统计信息的调用比读文件内容快的很多,如果你仅仅编辑了少数几个文件,Git几乎 58 | 不需要什么时间就能更新他们的统计信息。 59 | 60 | 我们前面讲过索引是一个中转区。为什么一堆文件的统计数据是一个中转区?因为添加 61 | 命令将文件放到Git的数据库并更新它们的统计信息,而无参数的提交命令将只基于统计 62 | 信息和已经在数据库里的文件来创建一个全新的提交。 63 | 64 | === Git的源起 === 65 | 66 | 这个 http://lkml.org/lkml/2005/4/6/121[ Linux内核邮件列表帖子] 描述了导致 67 | Git诞生的一系列事件。对Git史学家而言,整个讨论线是一个令人着迷的历史探究过程。 68 | 69 | === 对象数据库 === 70 | 71 | 你数据的每个版本都保存在“对象数据库”里,其位于子目录`.git/objects`内;其他位 72 | 于`.git/`的较少数据:索引,分支名,标签,配置选项,日志,头提交的当前位置等。 73 | 对象数据库朴素而优雅,是Git的力量之源。 74 | 75 | `.git/objects`里的每个文件是一个对象。有3种对象跟我们有关:“blob”对象, 76 | “tree”对象,和“commit”对象。 77 | 78 | === Blob对象 === 79 | 80 | 首先来一个小把戏。选择一个文件名,任意文件名。在一个空目录: 81 | 82 | $ echo sweet > YOUR_FILENAME 83 | $ git init 84 | $ git add . 85 | $ find .git/objects -type f 86 | 87 | 你将看到 +.git/objects/aa/823728ea7d592acc69b36875a482cdf3fd5c8d+ 。 88 | 89 | 我如何在不知道文件名的情况下知道这个?这是因为以下内容的SHA1哈希值: 90 | 91 | "blob" SP "6" NUL "sweet" LF 92 | 93 | 是 aa823728ea7d592acc69b36875a482cdf3fd5c8d,这里SP是一个空格,NUL是一 94 | 个0字节,LF是一个换行符。你可以验证这一点,键入: 95 | 96 | $ printf "blob 6\000sweet\n" | sha1sum 97 | 98 | Git基于“内容寻址”:文件并不按它们的文件名存储,而是按它们包含内容的哈希值, 99 | 在一个叫“blob对象”的文件里。我们可以把文件内容的哈希值看作一个唯一ID,这样 100 | 在某种意义上我们通过他们内容放置文件。开始的“blob 6”只是一个包含对象类型与 101 | 其长度的头;它简化了内部存储。 102 | 103 | 这样我可以轻易预言你所看到的输出:文件名是无关的:只有里面的内容被用作构 104 | 建blob对象。 105 | 106 | 你可能想知道对相同的文件会发生什么。试图填加一个你文件的拷贝,什么文件名都行。 107 | 在 +.git/objects+ 的内容保持不变,不管你加了多少。Git都只存储一次数据。 108 | 109 | 顺便说一句,在 +.git/objects+ 里的文件用zlib压缩,因此你不应该直接查看他们。 110 | 可以通过http://www.zlib.net/zpipe.c[zpipe -d] 管道, 或者键入: 111 | 112 | $ git cat-file -p aa823728ea7d592acc69b36875a482cdf3fd5c8d 113 | 114 | 这样可以漂亮地打印出给定的对象。注意,上面的cat-file命令中,aa是目录名。 115 | 116 | === Tree对象 === 117 | 118 | 但文件名在哪?它们必定在某个阶段保存在某个地方。Git在提交时得到文件名: 119 | 120 | $ git commit # 输入一些信息。 121 | $ find .git/objects -type f 122 | 123 | 你应看到3个对象。这次我不能告诉你这两个新文件是什么,因为它部分依赖你选择的文 124 | 件名。我继续进行,假设你选了``rose''。如果你没有,你可以重写历史以让它看起来 125 | 像似你做了: 126 | 127 | $ git filter-branch --tree-filter 'mv YOUR_FILENAME rose' 128 | $ find .git/objects -type f 129 | 130 | 现在你应看到文件 +.git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9+ ,因 131 | 为这是以下内容的SHA1哈希值: 132 | 133 | "tree" SP "32" NUL "100644 rose" NUL 0xaa823728ea7d592acc69b36875a482cdf3fd5c8d 134 | 135 | 通过键入以下命令来检查这个文件真的包含上面内容: 136 | 137 | $ echo 05b217bb859794d08bb9e4f7f04cbda4b207fbe9 | git cat-file --batch 138 | 139 | 使用zpipe,验证哈希值是容易的: 140 | 141 | $ zpipe -d < .git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9 | sha1sum 142 | 143 | 与查看文件相比,哈希值验证更轻巧一些,因为其输出不包含原始未压缩文件。 144 | 145 | 这里的输出是一个“tree”对象:一组包含文件类型,文件名和哈希值的数据。在我们的例 146 | 子里,文件类型是100644,这意味着“rose”是一个一般文件,并且哈希值指blob对象, 147 | 包含“rose”的内容。其他可能文件类型有可执行,链接或者目录。在最后一个例子里, 148 | 哈希值指向一个tree对象。 149 | 150 | 在一些过渡性的分支,你会有一些你不再需要的老的对象,尽管在宽限过期之后,它们 151 | 会被自动清除,现在我们还是将其删除,以使我们比较容易跟上这个示范的例子。 152 | 153 | $ rm -r .git/refs/original 154 | $ git reflog expire --expire=now --all 155 | $ git prune 156 | 157 | 在真实项目里你通常应该避免像这样的命令,因为你在破坏备份。如果你期望一个干净 158 | 的仓库,通常最好做一个新的克隆。还有,直接操作 +.git+ 时一定要小心:如果 159 | Git命令同时也在运行会怎样,或者突然停电?一般,引用应由 *git update-ref -d* 160 | 删除,尽管通常手工删除 +refs/original+ 也是安全的。 161 | 162 | === Commit对象 === 163 | 164 | 我们已经解释了三个对象中的两个。第三个是“commit”对象。其内容依赖于提交信息 165 | 以及其创建的日期和时间。为满足这里我们所需的,我们不得不调整一下: 166 | 167 | $ git commit --amend -m Shakespeare # 改提交信息 168 | $ git filter-branch --env-filter 'export 169 | GIT_AUTHOR_DATE="Fri 13 Feb 2009 15:31:30 -0800" 170 | GIT_AUTHOR_NAME="Alice" 171 | GIT_AUTHOR_EMAIL="alice@example.com" 172 | GIT_COMMITTER_DATE="Fri, 13 Feb 2009 15:31:30 -0800" 173 | GIT_COMMITTER_NAME="Bob" 174 | GIT_COMMITTER_EMAIL="bob@example.com"' # Rig timestamps and authors. 175 | $ find .git/objects -type f 176 | 177 | 你现在应看到 +.git/objects/49/993fe130c4b3bf24857a15d7969c396b7bc187+ 是下列 178 | 内容的SHA1哈希值: 179 | 180 | "commit 158" NUL 181 | "tree 05b217bb859794d08bb9e4f7f04cbda4b207fbe9" LF 182 | "author Alice <alice@example.com> 1234567890 -0800" LF 183 | "committer Bob <bob@example.com> 1234567890 -0800" LF 184 | LF 185 | "Shakespeare" LF 186 | 187 | 和前面一样,你可以运行zpipe或者cat-file来自己看。 188 | 189 | 这是第一个提交,因此没有父提交,但之后的提交将总有至少一行,指定一个父提交。 190 | 191 | === 没那么神 === 192 | 193 | Git的秘密似乎太简单。看起来似乎你可以整合几个shell脚本,加几行C代码来弄起来, 194 | 也就几个小时的事:一个基本文件操作和SHA1哈希化的混杂,用锁文件装饰一下,文件 195 | 同步保证健壮性。实际上,这准确描述了Git的最早期版本。尽管如此,除了巧妙地打包 196 | 以节省空间,巧妙地索引以省时间,我们现在知道Git如何灵巧地改造文件系统,使其成 197 | 为一个完美的版本控制数据库。 198 | 199 | 例如,如果对象数据库里的任何一个文件由于硬盘错误损毁,那么其哈希值将不再匹配, 200 | 这个错误会报告给我们。通过哈希化其他对象的哈希值,我们在所有层面维护数据完整 201 | 性。Commit对象是原子性的,也就是说,一个提交永远不会部分地记录变更:在我们已经 202 | 存储所有关于tree对象,blob对象和父commit对象之后,我们才可以计算提交的的哈希 203 | 值并将其存储在数据库,对象数据库不受诸如停电之类的意外中断影响。 204 | 205 | 我们打败了即使是最狡猾的对手。假设有人试图悄悄修改一个项目里一个远古版本文件的 206 | 内容,为使对象据库看起来健康,他们也必须修改相应blob对象的哈希值,既然它现在 207 | 是一个不同的字节串。这意味着他们将不得不引用这个文件的tree对象的哈希值,并反 208 | 过来改变所有与这个tree相关的commit对象的哈希值,还要加上这些提交所有后裔的哈 209 | 希值。这暗示官方head的哈希值与这个坏仓库不同。通过跟踪不匹配哈希值线索,我 210 | 们可以查明残缺文件,以及第一个被破坏的提交。 211 | 212 | 总之,只要20个字节代表最后一次的提交是安全的,我们就将不可能篡改一个Git仓库。 213 | 214 | 那么Git的著名功能怎样实现的呢?分支?合并?标签?这些都是单纯的细节。当前head保 215 | 存在文件+.git /HEAD+ ,其中包含了一个commit对象的哈希值。该哈希值在运行提交 216 | 以及其他命令时更新。分支几乎一样:它们是保存在 +.git/refs/heads+ 的文件。标签 217 | 也是:它们住在 +.git/refs/tags+ ,但它们由一套不同的命令更新。 218 | -------------------------------------------------------------------------------- /zh_cn/translate.txt: -------------------------------------------------------------------------------- 1 | == 附录 B: 本指南的翻译 == 2 | 3 | 我推荐如下步骤翻译本指南,这样我的脚本就可以快速生成HTML和PDF版本,并且所有翻 4 | 译也可以共存于同一个仓库。 5 | 6 | 克隆源码,然后针对不同目标 7 | http://www.iana.org/assignments/language-subtag-registry[语言的IETF tag]创建 8 | 一个目录。参见 9 | http://www.w3.org/International/articles/language-tags/Overview.en.php[ W3C在 10 | 国际化方面的文章 ]。例如,英语是“en”,日语是“ja”,正体中文是“zh-Hant”。 11 | 然后在新建目录,翻译这些来自“en”目录的 +txt+ 文件。 12 | 13 | 例如,要将本指南译为 http://en.wikipedia.org/wiki/Klingon_language[ 克林贡语 ], 14 | 你可以键入: 15 | 16 | $ git clone git://repo.or.cz/gitmagic.git 17 | $ cd gitmagic 18 | $ mkdir tlh # "tlh" 是克林贡语的IETF语言码。 19 | $ cd tlh 20 | $ cp ../en/intro.txt . 21 | $ edit intro.txt # 翻译这个文件 22 | 23 | 对每个文件都一样。 24 | 25 | 打开Makefile文件,把语言码加入`TRANSLATIONS`变量,现在你可以时不时查看你的工 26 | 作: 27 | 28 | $ make tlh 29 | $ firefox book-tlh/index.html 30 | 31 | 经常提交你的更新,这样我就知道他们什么时候可以完成。GitHub.com提供一个便于fork 32 | “gitmatic”项目的界面,提交你的变更,然后告诉我去合并。 33 | 34 | 但请按照最适合你的方式做:例如,中文译者就使用 35 | Google Docs。只要你的工作能使更多人看到我的工作,我就高兴。 36 | -------------------------------------------------------------------------------- /zh_tw/basic.txt: -------------------------------------------------------------------------------- 1 | == 基本技巧 == 2 | 3 | 與其一頭紮進Git命令的海洋中,不如來點基本的例子試試手。它們簡單而且實用。實際 4 | 上,在開始使用Git的頭幾個月,我所用的從來沒超出本章介紹的內容。 5 | 6 | === 保存狀態 === 7 | 8 | 要不來點猛的?在做之前,先為當前目錄所有檔案做個快照,使用: 9 | 10 | $ git init 11 | $ git add . 12 | $ git commit -m "My first backup" 13 | 14 | 現在如果你的編輯亂了套,恢復之前的版本: 15 | 16 | $ git reset --hard 17 | 18 | 再次保存狀態: 19 | 20 | $ git commit -a -m "Another backup" 21 | 22 | === 添加、刪除、重命名 === 23 | 24 | 以上命令將只跟蹤你第一次運行 *git add* 命令時就已經存在的檔案。如果要添加新文 25 | 件或子目錄,你需要告訴Git: 26 | 27 | $ git add readme.txt Documentation 28 | 29 | 類似,如果你想讓Git忘記某些檔案: 30 | 31 | $ git rm kludge.h obsolete.c 32 | $ git rm -r incriminating/evidence/ 33 | 34 | 這些檔案如果還沒刪除,Git刪除它們。 35 | 36 | 重命名檔案和先刪除舊檔案,再添加新檔案的一樣。也有一個快捷方式 *git mv* ,和 37 | *mv* 命令的用法一樣。例如: 38 | 39 | $ git mv bug.c feature.c 40 | 41 | === 進階撤銷/重做 === 42 | 43 | 有時候你只想把某個時間點之後的所有改動都回滾掉,因為這些的改動是不正確的。那 44 | 麼: 45 | 46 | $ git log 47 | 48 | 來顯示最近提交列表,以及他們的SHA1哈希值: 49 | 50 | ---------------------------------- 51 | commit 766f9881690d240ba334153047649b8b8f11c664 52 | Author: Bob <bob@example.com> 53 | Date: Tue Mar 14 01:59:26 2000 -0800 54 | 55 | Replace printf() with write(). 56 | 57 | commit 82f5ea346a2e651544956a8653c0f58dc151275c 58 | Author: Alice <alice@example.com> 59 | Date: Thu Jan 1 00:00:00 1970 +0000 60 | 61 | Initial commit. 62 | ---------------------------------- 63 | 64 | 哈希值的前幾個字元足夠確定一個提交;也可以拷貝粘貼完整的哈希值,鍵入: 65 | 66 | $ git reset --hard 766f 67 | 68 | 來恢復到一個指定的提交狀態,並從記錄裡永久抹掉所有比該記錄新一些的提交。 69 | 70 | 另一些時候你想簡單地跳到一個舊狀態。這種情況,鍵入: 71 | 72 | $ git checkout 82f5 73 | 74 | 這個操作將把你帶回過去,同時也保留較新提交。然而,像科幻電影裡時光旅行一樣, 75 | 如果你這時編輯並提交的話,你將身處另一個現實裡,因為你的動作與開始時相比是不 76 | 同的。 77 | 78 | 這另一個現實叫作“分支”(branch),之後 <<branch,我們會對這點多討論一些>>。 79 | 至于現在,只要記住: 80 | 81 | $ git checkout master 82 | 83 | 會把你帶到當下來就可以了。另外,為避免Git的抱怨,應該在每次運行checkout之前提 84 | 交(commit)或重置(reset)你的改動。 85 | 86 | 還以電腦遊戲作為類比: 87 | 88 | - *`git reset --hard`*: 加載一個舊記錄並刪除所有比之新的記錄。 89 | 90 | - *`git checkout`*: 加載一個舊記錄,但如果你在這個記錄上玩,遊戲狀態將偏離第 91 | 一輪的較新狀態。你現在打的所有遊戲記錄會在你剛進入的、代表另一個真實的分支 92 | 裡。<<branch,我們稍後論述>>。 93 | 94 | 你可以選擇只恢復特定檔案和目錄,通過將其加在命令之後: 95 | 96 | $ git checkout 82f5 some.file another.file 97 | 98 | 小心,這種形式的 *checkout* 會不聲不響地覆蓋檔案。為阻止意外發生,在運行任何 99 | checkout命令之前做提交,尤其在初學Git的時候。通常,任何時候你覺得對運行某個命 100 | 令不放心,無論Git命令還是不是Git命令,就先運行一下 *git commit -a* 。 101 | 102 | 不喜歡拷貝站題哈希值?那就用: 103 | 104 | $ git checkout :/"My first b" 105 | 106 | 來跳到以特定字元串開頭的提交。你也可以回到倒數第五個保存狀態: 107 | 108 | $ git checkout master~5 109 | 110 | === 撤銷 === 111 | 112 | 在法庭上,事件可以從法庭記錄裡敲出來。同樣,你可以檢出特定提交以撤銷。 113 | 114 | $ git commit -a 115 | $ git revert 1b6d 116 | 117 | 講撤銷給定哈希值的提交。本撤銷被記錄為一個新的提交,你可以通過運行 *git log* 118 | 來確認這一點。 119 | 120 | === 變更日誌生成 === 121 | 122 | 一些項目要求生成變更日誌http://en.wikipedia.org/wiki/Changelog[changelog]. 生 123 | 成一個,通過鍵入: 124 | 125 | $ git log > ChangeLog 126 | 127 | === 下載檔案 === 128 | 129 | 得到一個由Git管理的項目的拷貝,通過鍵入: 130 | 131 | $ git clone git://server/path/to/files 132 | 133 | 例如,得到我用來創建該站的所有檔案: 134 | 135 | $ git clone git://git.or.cz/gitmagic.git 136 | 137 | 我們很快會對 *clone* 命令談的很多。 138 | 139 | === 到最新 === 140 | 141 | 如果你已經使用 *git clone* 命令得到了一個項目的一份拷貝,你可以更新到最新版, 142 | 通過: 143 | 144 | $ git pull 145 | 146 | 147 | === 快速發佈 === 148 | 149 | 假設你寫了一個腳本,想和他人分享。你可以只告訴他們從你的計算機下載,但如果此 150 | 時你正在改進你的腳本,或加入試驗性質的改動,他們下載了你的腳本,他們可能由此 151 | 陷入困境。當然,這就是發佈周期存在的原因。開發人員可能頻繁進行項目修改,但他 152 | 們只在他們覺得代碼可以見人的時候才擇時發佈。 153 | 154 | 用Git來完成這項,需要進入你的腳本所在目錄: 155 | 156 | $ git init 157 | $ git add . 158 | $ git commit -m "First release" 159 | 160 | 然後告訴你的用戶去運行: 161 | 162 | $ git clone your.computer:/path/to/script 163 | 164 | 來下載你的腳本。這要假定他們有ssh訪問權限。如果沒有,需要運行 *git daemon* 並 165 | 告訴你的用戶去運行: 166 | 167 | $ git clone git://your.computer/path/to/script 168 | 169 | 從現在開始,每次你的腳本準備好發佈時,就運行: 170 | 171 | $ git commit -a -m "Next release" 172 | 173 | 並且你的用戶可以通過進入包含你腳本的目錄,並鍵入下列命令,來更新他們的版本: 174 | 175 | $ git pull 176 | 177 | 你的用戶永遠也不會取到你不想讓他們看到的腳本版本。顯然這個技巧對所有的東西都 178 | 是可以,不僅是對腳本。 179 | 180 | 181 | === 我們已經做了什麼? === 182 | 183 | 找出自從上次提交之後你已經做了什麼改變: 184 | 185 | $ git diff 186 | 187 | 或者自昨天的改變: 188 | 189 | $ git diff "@{yesterday}" 190 | 191 | 或者一個特定版本與倒數第二個變更之間: 192 | 193 | $ git diff 1b6d "master~2" 194 | 195 | 輸出結果都是補丁格式,可以用 *git apply* 來把補丁打上。也可以試一下: 196 | 197 | $ git whatchanged --since="2 weeks ago" 198 | 199 | 我也經常用http://sourceforge.net/projects/qgit[qgit] 瀏覽歷史, 因為他的圖形界 200 | 面很養眼,或者 http://jonas.nitro.dk/tig/[tig] ,一個文本界面的東西,很慢的網 201 | 絡狀況下也工作的很好。也可以安裝web 伺服器,運行 *git instaweb* ,就可以用任 202 | 何瀏覽器瀏覽了。 203 | 204 | === 練習 === 205 | 206 | 比方A,B,C,D是四個連續的提交,其中B與A一樣,除了一些檔案刪除了。我們想把這 207 | 些刪除的檔案加回D。我們如何做到這個呢? 208 | 209 | 至少有三個解決方案。假設我們在D: 210 | 211 | 1. A與B的差別是那些刪除的檔案。我們可以創建一個補丁代表這些差別,然後吧補丁 212 | 打上: 213 | 214 | $ git diff B A | git apply 215 | 216 | 2. 既然這些檔案存在A,我們可以把它們拿出來: 217 | 218 | $ git checkout A foo.c bar.h 219 | 220 | 3. 我們可以把從A到B的變化視為可撤銷的變更: 221 | 222 | $ git revert B 223 | 224 | 哪個選擇最好?這取決於你的喜好。利用Git滿足自己需求是容易,經常還有多個方法。 225 | -------------------------------------------------------------------------------- /zh_tw/branch.txt: -------------------------------------------------------------------------------- 1 | == 分支巫術 == 2 | 3 | 即時分支合併是Git最給力的殺手鐧。 4 | 5 | *問題* :外部因素要求必須切換場景。在發佈版本中突然蹦出個嚴重缺陷。某個特性完 6 | 成的截至日期就要來臨。在項目關鍵部分可以提供幫助的一個開發正打算離職。所有情 7 | 況逼迫你停下所有手頭工作,全力撲到到這個完全不同的任務上。 8 | 9 | 打斷思維的連續性會使你的生產力大大降低,並且切換上下文也更麻煩,更大的損失。 10 | 使用中心版本控制我們必須從中心伺服器下載一個新的工作拷貝。分散式系統的情況就 11 | 好多了,因為我們能夠在本地克隆所需要的版本。 12 | 13 | 但是克隆仍然需要拷貝整個工作目錄,還有直到給定點的整個歷史記錄。儘管Git使用文 14 | 件共享和硬連結減少了花費,項目檔案自身還是必須在新的工作目錄裡重建。 15 | 16 | *方案* :Git有一個更好的工具對付這種情況,比克隆快多了而且節省空間: *git 17 | branch* 。 18 | 19 | 使用這個魔咒,目錄裡的檔案突然從一個版本變到另一個。除了只是在歷史記錄裡上跳 20 | 下竄外,這個轉換還可以做更多。你的檔案可以從上一個發佈版變到實驗版本到當前開 21 | 發版本到你朋友的版本等等。 22 | 23 | === 老闆鍵 === 24 | 25 | 曾經玩過那樣的遊戲嗎?按一個鍵(“老闆鍵”),屏幕立即顯示一個電子表格或別的? 26 | 那麼如果老闆走進辦公室,而你正在玩遊戲,就可以快速將遊戲藏起來。 27 | 28 | 在某個目錄: 29 | 30 | $ echo "I'm smarter than my boss" > myfile.txt 31 | $ git init 32 | $ git add . 33 | $ git commit -m "Initial commit" 34 | 35 | 我們已經創建了一個Git倉庫,該倉庫記錄一個包含特定信息的檔案。現在我們鍵入: 36 | 37 | $ git checkout -b boss # 之後似乎沒啥變化 38 | $ echo "My boss is smarter than me" > myfile.txt 39 | $ git commit -a -m "Another commit" 40 | 41 | 看起來我們剛剛只是覆蓋了原來的檔案並提交了它。但這是個錯覺。鍵入: 42 | 43 | $ git checkout master # 切到檔案的原先版本 44 | 45 | 嘿真快!這個檔案就恢復了。並且如果老闆決定窺視這個目錄,鍵入: 46 | 47 | $ git checkout boss # 切到適合老闆看的版本 48 | 49 | 你可以在兩個版本之間相切多少次就切多少次,而且每個版本都可以獨立提交。 50 | 51 | === 骯髒的工作 === 52 | 53 | [[branch]] 54 | 55 | 比如你正在開發某個特性,並且由於某種原因,你需要回退三個版本,臨時加進幾行打 56 | 印語句來,來看看一些東西是如何工作的。那麼: 57 | 58 | $ git commit -a 59 | $ git checkout HEAD~3 60 | 61 | 現在你可以到處加醜陋的臨時代碼。你甚至可以提交這些改動。當你做完的時候, 62 | 63 | $ git checkout master 64 | 65 | 來返回到你原來的工作。看,所有未提交變更都結轉了。 66 | 67 | 如果你後來想保存臨時變更怎麼辦?簡單: 68 | 69 | $ git checkout -b dirty 70 | 71 | 只要在切換到主分支之前提交就可以了。無論你什麼時候想回到髒的變更,只需鍵入: 72 | 73 | $ git checkout dirty 74 | 75 | 我們在前面章節討論加載舊狀態的時候,曾經接觸過這個命令。最終我們把故事說全: 76 | 檔案改變成請求的狀態,但我們必須離開主分支。從現在開始的任何提交都會將你的文 77 | 件提交到另一條不同的路,這個路可以之後命名。 78 | 79 | 換一個說法,在checkout一個舊狀態之後,Git自動把你放到一個新的,未命名的分支, 80 | 這個分支可以使用 *git checkout -b* 來命名和保存。 81 | 82 | === 快速修訂 === 83 | 84 | 你正在做某件事的當間,被告知先停所有的事情,去修理一個新近發現的臭蟲,這個臭 85 | 蟲在提交 `1b6d...`: 86 | 87 | $ git commit -a 88 | $ git checkout -b fixes 1b6d 89 | 90 | 那麼一旦你修正了這個臭蟲: 91 | 92 | $ git commit -a -m "Bug fixed" 93 | $ git checkout master 94 | 95 | 並可以繼續你原來的任務。你甚至可以“合併”到最新修訂: 96 | 97 | $ git merge fixes 98 | 99 | === 合併 === 100 | 101 | 一些版本控制系統,創建分支很容易,但把分支合併回來很難。使用Git,合併簡直是家 102 | 常便飯,以至于甚至你可能對其發生沒有察覺。 103 | 104 | 我們很久之前就遇到合併了。 *pull* 命令取出提交併合並它們到你的當前分支。如果 105 | 你沒有本地變更,那這個合併就是一個“快進”,相當於中心式版本控制系統裡的一個 106 | 弱化的獲取最新版本操作。但如有本地變更,Git將自動合併,並報告任何衝突。 107 | 108 | 通常,一個提交只有一個“父提交”,也叫前一個提交。合併分支到一起產生一個至少 109 | 有兩個父的提交。這就引出了問題: `HEAD~10` 真正指哪個提交?一個提交可能有多個 110 | 父,那我們跟哪個呢? 111 | 112 | 原來這個表示每次選擇第一個父。這是可取的,因為在合併時候當前分支成了第一個父; 113 | 多數情況下我們只關注我們在當前分支都改了什麼,而不是從其他分支合併來的變更。 114 | 115 | 你可以用插入符號來特別指定父。比如,顯示來自第二個父的日誌: 116 | 117 | $ git log HEAD^2 118 | 119 | 你可以忽略數字以指代第一個父。比如,顯示與第一個父的差別: 120 | 121 | $ git diff HEAD^ 122 | 123 | 你可以結合其他類型使用這個記號。比如: 124 | 125 | $ git checkout 1b6d^^2~10 -b ancient 126 | 127 | 開始一個新分支 ``ancient'' ,表示第一個父的第二個父的倒數第十次提交的狀態。 128 | 129 | === 不間斷工作流 === 130 | 131 | 經常在硬件項目裡,計劃的第二步必須等第一步完成才能開始。待修的汽車傻等在車庫 132 | 裡,直到特定的零件從工廠運來。一個原型在其可以構建之前,可能苦等晶片成型。 133 | 134 | 軟件項目可能也類似。新功能的第二部分不得不等待,直到第一部分發佈並通過測試。 135 | 一些項目要求你的代碼需要審批才能接受,因此你可能需要等待第一部分得到批准,才 136 | 能開始第二部分。 137 | 138 | 多虧了無痛分支合併,我們可以不必遵循這些規則,在第一部分正式準備好前開始第二 139 | 部分的工作。假設你已經將第一部分提交並發去審批,比如說你現在在主分支。那麼分 140 | 岔: 141 | 142 | $ git checkout -b part2 143 | 144 | 接下來,做第二部分,隨時可以提交變更。只要是人就可能犯錯誤,經常你將回到第一 145 | 部分在修修補補。如果你非常幸運,或者超級棒,你可能不必做這幾行: 146 | 147 | $ git checkout master # 回到第一部分 148 | $ 修復問題 149 | $ git commit -a # 提交變更 150 | $ git checkout part2 # 回到第二部分 151 | $ git merge master # 合併這些改動 152 | 153 | 最終,第一部分獲得批准: 154 | 155 | $ git checkout master # 回到第一部分 156 | $ submit files # 對世界發佈 157 | $ git merge part2 # 合併第二部分 158 | $ git branch -d part2 # 刪除分支“part2” 159 | 160 | 現在你再次處在主分支,第二部分的代碼也在工作目錄。 161 | 162 | 很容易擴展這個技巧,應用到任意數目的部分。它也很容易追溯分支:假如你很晚才意 163 | 識到你本應在7次提交前就創建分支。那麼鍵入: 164 | 165 | $ git branch -m master part2 # 重命名“master”分支為“part2”。 166 | $ git branch master HEAD~7 # 以七次前提交建一個新的“master”。 167 | 168 | 分支 `master` 只有第一部分內容,其他內容在分支 `part2` 。 我們現在後一個分支; 169 | 我們創建了 `master` 分支還沒有切換過去,因為我們想繼續工作在 `part2` 。這是不 170 | 尋常的。直到現在,我們已經在創建之後切換到分支,如: 171 | 172 | $ git checkout HEAD~7 -b master # 創建分支,並切換過去。 173 | 174 | === 重組雜亂 === 175 | 176 | 或許你喜歡在同一個分支下完成工作的方方面面。你想為自己保留工作進度並希望其他 177 | 人只能看到你仔細整理過後的提交。開啟一對分支: 178 | 179 | $ git branch sanitized # 為乾淨提交創建分支 180 | $ git checkout -b medley # 創建並切換分支以進去工作 181 | 182 | 接下來,做任何事情:修臭蟲,加特性,加臨時代碼,諸如此類,經常按這種方式提交。 183 | 然後: 184 | 185 | $ git checkout sanitized 186 | $ git cherry-pick medley^^ 187 | 188 | 應用分支 ``medley'' 的祖父提交到分支 ``sanitized'' 。通過合適的挑選(像選櫻桃 189 | 那樣)你可以構建一個只包含成熟代碼的分支,而且相關的提交也組織在一起。 190 | 191 | === 管理分支 === 192 | 193 | 列出所有分支: 194 | 195 | $ git branch 196 | 197 | 預設你從叫 ``master'' 的分支開始。一些人主張別碰“master”分支,而是創建你自 198 | 己版本的新分支。 199 | 200 | 選項 *-d* 和 *-m* 允許你來刪除和移動(重命名)分支。參見 *git help branch* 。 201 | 202 | 分支``master'' 是一個有用的慣例。其他人可能假定你的倉庫有一個叫這個名字的分 203 | 支,並且該分支包含你項目的官方版本。儘管你可以重命名或抹殺 ``master'' 分支, 204 | 你最好還是尊重這個約定。 205 | 206 | === 臨時分支 === 207 | 208 | 很快你會發現你經常會因為一些相似的原因創建短期的分支:每個其它分支只是為了保 209 | 存當前狀態,那樣你就可以直接跳到較老狀態以修復高優先順序的臭蟲之類。 210 | 211 | 可以和電視的換台做類比,臨時切到別的頻道,來看看其它台那正放什麼。但並不是簡 212 | 單地按幾個按鈕,你不得不創建,檢出,合併,以及刪除臨時分支。幸運的是,Git已經 213 | 有了和電視機遙控器一樣方便的快捷方式: 214 | 215 | $ git stash 216 | 217 | 這個命令保存當前狀態到一個臨時的地方(一個隱藏的地方)並且恢復之前狀態。你的 218 | 工作目錄看起來和你開始編輯之前一樣,並且你可以修復臭蟲,引入之前變更等。當你 219 | 想回到隱藏狀態的時候,鍵入: 220 | 221 | $ git stash apply # 你可能需要解決一些衝突 222 | 223 | 你可以有多個隱藏,並用不同的方式來操作他們。參見 *git help slash* 。也許你已 224 | 經猜到,Git維護在這個場景之後的分支以執行魔法技巧. 225 | 226 | === 按你希望的方式工作 === 227 | 228 | 你可能猶疑于分支是否值得一試。畢竟,克隆也几乎一樣快,並且你可以用 *cd* 來在 229 | 彼此之間切換,而不是用Git深奧的命令。 230 | 231 | 考慮一下瀏覽器。為什麼同時支持多標籤和多窗口?因為允許兩者同時接納納了多種風 232 | 格的用戶。一些用戶喜歡只保持一個打開的窗口,然後用標籤瀏覽多個網頁。一些可能 233 | 堅持另一個極端:任何地方都沒有標籤的多窗口。一些喜好處在兩者之間。 234 | 235 | 分支類似你工作目錄的標籤,克隆類似打開的瀏覽器新窗口。這些是本地操作很快,那 236 | 為什麼不試着找出最適合你的組合呢?Git讓你按你確實所希望的那樣工作。 237 | -------------------------------------------------------------------------------- /zh_tw/clone.txt: -------------------------------------------------------------------------------- 1 | == 克隆周邊 == 2 | 3 | 在較老一代的版本控制系統裡,checkout是獲取檔案的標準操作。你將獲得一組特定保 4 | 存狀態的檔案。 5 | 6 | 在Git和其他分散式版本控制系統裡,克隆是標準的操作。通過創建整個倉庫的克隆來 7 | 獲得檔案。或者說,你實際上把整個中心伺服器做了個鏡像。凡是主倉庫上能做的事, 8 | 你都能做。 9 | 10 | === 計算機間同步 === 11 | 12 | 我可以忍受製作tar包或利用rsync來作備份和基本同步。但我有時在我筆記本上編輯, 13 | 其他時間在台式機上,而且這倆之間也許並不交互。 14 | 15 | 在一個機器上初始化一個Git倉庫並提交你的檔案。然後轉到另一台機器上: 16 | 17 | $ git clone other.computer:/path/to/files 18 | 19 | 以創建這些檔案和Git倉庫的第二個拷貝。從現在開始, 20 | 21 | $ git commit -a 22 | $ git pull other.computer:/path/to/files HEAD 23 | 24 | 將把另一台機器上特定狀態的檔案“拉”到你正工作的機器上。如果你最近對同一個文 25 | 件做了有衝突的修改,Git將通知你,而你也應該在解決衝突之後再次提交。 26 | 27 | === 典型源碼控制 === 28 | 29 | 為你的檔案初始化Git倉庫: 30 | 31 | $ git init 32 | $ git add . 33 | $ git commit -m "Initial commit" 34 | 35 | 在中心伺服器,在某個目錄初始化一個“裸倉庫”: 36 | 37 | $ mkdir proj.git 38 | $ cd proj.git 39 | $ git init --bare 40 | $ touch proj.git/git-daemon-export-ok 41 | 42 | 如需要的話,啟動Git守護進程: 43 | 44 | $ git daemon --detach # 它也許已經在運行了 45 | 46 | 對一些Git伺服服務,按照其指導來初始化空Git倉庫。一般是在網頁上填一個表單。 47 | 48 | 把你的項目“推”到中心伺服器: 49 | $ git push central.server/path/to/proj.git HEAD 50 | 51 | 撿出源碼,可以鍵入: 52 | 53 | $ git clone central.server/path/to/proj.git 54 | 55 | 做了改動之後,開發保存變更到本地: 56 | 57 | $ git commit -a 58 | 59 | 更新到最近版本: 60 | 61 | $ git pull 62 | 63 | 所有衝突應被處理,然後提交: 64 | 65 | $ git commit -a 66 | 67 | 把本地改動撿入到中心倉庫: 68 | 69 | $ git push 70 | 71 | 如果主伺服器由於其他開發的活動,有了新的變更,這個撿入會失敗,該開發應該把最 72 | 新版本拿下來,解決合併衝突,然後重試。 73 | 74 | 為使用上面pull和push命令,開發必須有SSH訪問權限。不過,通過鍵入以下命令,任何 75 | 人都可以看到源碼: 76 | 77 | $ git clone git://central.server/path/to/proj.git 78 | 79 | 本地git協議和HTTP類似:並無安全驗證,因此任何人都能拿到項目。因此,預設情況 80 | git協議禁止推操作。 81 | 82 | === 封閉源碼 === 83 | 84 | 閉源項目不要執行touch命令,並確保你從未創建`git-daemon-export-ok`檔案。資源庫 85 | 不再可以通過git協議獲取;只有那些有SSH訪問權限的人才能看到。如果你所有的資源 86 | 庫都是封閉的,那也沒必要運行運行git守護了,因為所有溝通都走SSH。 87 | 88 | === 裸倉庫 === 89 | 90 | 之所以叫裸倉庫是因為其沒有工作目錄;它只包含正常情況下隱藏在`.git`子目錄下 91 | 的檔案。換句話說,它維護項目歷史,而且從不保存任何給定版本的快照。 92 | 93 | 裸倉庫扮演的角色和中心版本控制系統中中心伺服器的角色類似:你項目的中心。開 94 | 發從其中克隆項目,撿入新近改動。典型地裸倉庫存在一個伺服器上,該伺服器除了 95 | 分散數據外並不做啥。開發活動發生在克隆上,因此中心倉庫沒有工作目錄也行。 96 | 97 | 98 | 很多Git命令在裸倉庫上失敗,除非指定倉庫路徑到環境變數`GIT_DIR`,或者指定 99 | `--bare`選項。 100 | 101 | === 推還是拽 === 102 | 103 | 為什麼我們介紹了push命令,而不是依賴熟悉的pull命令?首先,在裸倉庫上pull會 104 | 失敗:除非你必須“fetch”,一個之後我們要討論的命令。但即使我們在中心伺服器上 105 | 保持一個正常的倉庫,拽些東西進去仍然很繁瑣。我們不得不登陸伺服器先,給pull 106 | 命令我們要拽自機器的網絡地址。防火牆會阻礙,並且首先如果我們沒有到伺服器的 107 | shell訪問怎麼辦呢? 108 | 109 | 然而,除了這個案例,我們反對推進倉庫,因為當目標有工作目錄時,困惑隨之而來。 110 | 111 | 簡短截說,學習Git的時候,只在目標是裸倉庫的時候push,否則用pull的方式。 112 | 113 | === 項目分叉 === 114 | 115 | 項目走歪了嗎?或者認為你可以做得更好?那麼在伺服器上: 116 | 117 | $ git clone git://main.server/path/to/files 118 | 119 | 之後告訴每個相關的人你伺服器上項目的分支。 120 | 121 | 在之後的時間,你可以合併來自原先項目的改變,使用命令: 122 | 123 | $ git pull 124 | 125 | === 終極備份 === 126 | 127 | 會有很多散佈在各處,禁止篡改的冗餘存檔嗎? 如果你的項目有很多開發,那乾脆啥也 128 | 別做了。你的每份代碼克隆是一個有效備份。不僅當前狀態,還包括你項目整個歷史。 129 | 感謝哈希加密算法,如果任何人的克隆被損壞,只要他們與其他的交互,這個克隆就會 130 | 被修好。 131 | 132 | 如果你的項目並不是那麼流行,那就找儘可能多的伺服來放克隆吧。 133 | 134 | 真正的偏執狂應該總是把HEAD最近20位元組的SHA1哈希值寫到安全的地方。應該保證安全, 135 | 而不是把它藏起來。比如,把它發佈到報紙上就不錯,因為對攻擊者而言,更改每份報 136 | 紙是很難的。 137 | 138 | === 輕快多任務 === 139 | 140 | 比如你想並行開發多個功能。那麼提交你的項目並運行: 141 | 142 | $ git clone . /some/new/directory 143 | 144 | Git使用硬連結和檔案共享來儘可能安全地創建克隆,因此它一眨眼就完成了,因此你現 145 | 在可以並行操作兩個沒有相互依賴的功能。例如,你可以編輯一個克隆,同時編譯另一 146 | 個。感謝 http://en.wikipedia.org/wiki/Hard_link[hardlinking], 本地克隆比簡單 147 | 備份省時省地。 148 | 149 | 現在你可以同時工作在兩個彼此獨立的特性上。比如,你可以在編譯一個克隆的時候編 150 | 輯另一個克隆。任何時候,你都可以從其它克隆提交並拖拽變更。 151 | 152 | $ git pull /the/other/clone HEAD 153 | 154 | === 游擊版本控制 === 155 | 156 | 你正做一個使用其他版本控制系統的項目, 而你非常思念Git? 那麼在你的工作目錄初 157 | 始化一個Git倉庫: 158 | 159 | $ git init 160 | $ git add . 161 | $ git commit -m "Initial commit" 162 | 163 | 然後克隆它: 164 | 165 | $ git clone . /some/new/directory 166 | 167 | 並在這個目錄工作,按你所想在使用Git。過一會,一旦你想和其他每個人同步,在這種 168 | 情況下,轉到原來的目錄,用其他的版本控制工具同步,並鍵入: 169 | 170 | $ git add . 171 | $ git commit -m "Sync with everyone else" 172 | 173 | 現在轉到新目錄運行: 174 | 175 | $ git commit -a -m "Description of my changes" 176 | $ git pull 177 | 178 | 把你的變更提交給他人的過程依賴于其他版本控制系統。這個新目錄包含你的改動的文 179 | 件。需要運行其他版本控制系統的命令來上載這些變更到中心倉庫。 180 | 181 | Subversion, 或許是最好的中心式版本控制系統,為無數項目所用。 *git svn* 命令為 182 | Subversion倉庫自動化了上面的操作,並且也可以用作 183 | http://google-opensource.blogspot.com/2008/05/export-git-project-to-google-code.html[ 184 | 導出Git項目到Subversion倉庫] 的替代。 185 | 186 | === Mercurial === 187 | 188 | Mercurial是一個類似的的版本控制系統,几乎可以和Git一起無縫工作。使用 189 | `hg-git`插件,一個Mercurial用戶可以無損地往Git倉庫推送,從Git倉庫拖拽。 190 | 191 | 使用Git獲得`hg-git`插件: 192 | 193 | $ git clone git://github.com/schacon/hg-git.git 194 | 195 | 或使用Mercurial: 196 | 197 | $ hg clone http://bitbucket.org/durin42/hg-git/ 198 | 199 | 不好意思,我沒注意Git有類似的插件。因此, 我主張使用Git而不是Mercurial作為主資 200 | 源庫,即使你偏愛Mercurial。使用Mercurial項目,通常一個自願者維護一個平行的 201 | Git項目以適應Git用戶,然而感謝`hg-git`插件,一個Git項目自動地適應Mercurial用 202 | 戶。 203 | 204 | 儘管該插件可以把一個Mercurial倉庫轉成一個Git倉庫,通過推到一個空的倉庫, 205 | 這個差事交給`hg-fast-export.sh`腳本還是更容易些。來自: 206 | 207 | $ git clone git://repo.or.cz/fast-export.git 208 | 209 | 要轉化,只需在一個空目錄運行: 210 | 211 | $ git init 212 | $ hg-fast-export.sh -r /hg/repo 213 | 214 | 注意該腳本應加入你的`$PATH`。 215 | 216 | === Bazaar === 217 | 218 | 我們簡略提一下Bazaar,它畢竟是緊跟Git和Mercurial之後最流行的自由分散式版本控 219 | 制系統。 220 | 221 | Bazaar有後來者的優勢,它相對年輕些;它的設計者可以從前人的錯誤中學習,並且躲 222 | 過去翻歷史上犯過的錯誤。另外,它的開發人員對可移植性以及和與其它版本控制系統 223 | 的互操作性也考慮周全。 224 | 225 | 一個`bzr-git`插件讓Bazaar用戶在一定程度下可以工作在Git倉庫。`tailor`程序轉 226 | 換Bazaar倉庫到Git倉庫,並且可以遞增的方式做,要知道`bzr-fast-export`只是 227 | 在一次性轉換性情況下工作良好。 228 | 229 | === 我偏愛Git的原因 === 230 | 231 | 我起先選擇Git是因為我聽說它能管理不可想象地不可管理的Linux內核源碼。我從來沒 232 | 覺得有離開的必要。Git已經服侍的很好了,並且我也沒有被其瑕疵所困擾。因為我主要 233 | 使用Linux,其他平台上的問題與我無關。 234 | 235 | 還有,我偏愛C程序和bash腳本,以及諸如Python的可執行可腳本:較少依賴,並且我也 236 | 沉迷于快速的執行時間。 237 | 238 | 我考慮過Git才能如何提高,甚至自己寫類似的工具,但只作為研究練練手。即使完成這 239 | 個項目,我也無論如何會繼續使用Git,因為使用一個古裡古怪的系統所獲甚微。 240 | 241 | 自然地,你的需求和期望可能不同,並且你可能使用另一個系統會好些。儘管如此,使 242 | 用Git你都錯不太遠。 243 | -------------------------------------------------------------------------------- /zh_tw/drawbacks.txt: -------------------------------------------------------------------------------- 1 | == 附錄 A: Git的缺點 == 2 | 3 | 有一些Git的問題,我已經藏在毯子下面了。有些可以通過腳本或回調方法輕易地解決, 4 | 有些需要重組或重定義項目,少數剩下的煩惱,還只能等待。或者更好地,投入進來幫 5 | 忙。 6 | 7 | === SHA1 的弱點 === 8 | 9 | 隨着時間的推移,密碼學家發現越來越多的SHA1的弱點。已經發現對對資源雄厚的組織 10 | 哈希衝撞是可能的。在幾年內,或許甚至一個一般的PC也將有足夠計算能力悄悄摧毀一 11 | 個Git倉庫。 12 | 13 | 希望在進一步研究摧毀SHA1之前,Git能遷移到一個更好的哈希算法。 14 | 15 | === 微軟 Windows === 16 | 17 | Git在微軟Windows上可能有些繁瑣: 18 | 19 | - http://cygwin.com/[Cygwin] ,, 一個Windows下的類Linux的環境,包含一個 http://cygwin.com/packages/git/[ 一個Git在Windows下的移植]. 20 | 21 | - http://code.google.com/p/msysgit/[基于MSys的Git] 是另一個,要求最小運行時支持,不過一些命令不能馬上工作。 22 | 23 | === 不相關的檔案 === 24 | 25 | 如果你的項目非常大,包含很多不相關的檔案,而且正在不斷改變,Git可能比其他系統 26 | 更不管用,因為獨立的檔案是不被跟蹤的。Git跟蹤整個項目的變更,這通常才是有益的。 27 | 28 | 一個方案是將你的項目拆成小塊,每個都由相關檔案組成。如果你仍然希望在同一個資 29 | 源庫裡保存所有內容的話,可以使用 *git submodule* 。 30 | 31 | === 誰在編輯什麼? === 32 | 33 | 一些版本控制系統在編輯前強迫你顯示地用某個方法標記一個檔案。儘管這種要求很煩 34 | 人,尤其是需要和中心伺服器通訊時,不過它還是有以下兩個好處的: 35 | 36 | 1. 比較速度快,因為只有被標記的檔案需要檢查。 37 | 38 | 2. 可以知道誰在這個檔案上工作,通過查詢在中心伺服器誰把這個檔案標記為編輯狀 39 | 態。 40 | 41 | 使用適當的腳本,你也可以使Git達到同樣的效果。這要求程序員協同工作,當他編輯一 42 | 個檔案的時候還要運行特定的腳本。 43 | 44 | === 檔案歷史 === 45 | 46 | 因為Git記錄的是項目範圍的變更,重造單一檔案的變更歷史比其他跟蹤單一檔案的版本 47 | 控制系統要稍微麻煩些。 48 | 49 | 好在麻煩還不大,也是值得的,因為Git其他的操作難以置信地高效。例如,`git 50 | checkout`比`cp -a`都快,而且項目範圍的delta壓縮也比基于檔案的delta集合的做法 51 | 好多了。 52 | 53 | === 初始克隆 === 54 | 55 | The initial cost is worth paying in the long run, as most future operations will then be fast and offline. However, in some situations, it may be preferable to create a shallow clone with the `--depth` option. This is much faster, but the resulting clone has reduced functionality. 56 | 57 | 當一個項目歷史很長後,與在其他版本系統裡的檢出代碼相比,創建一個克隆的開銷會 58 | 大的多。 59 | 60 | 長遠來看,開始付出的代價還是值得付出的,因為大多將來的操作將由此變得很快,並 61 | 可以離線完成。然而,在一些情況下,使用`--depth`創建一個淺克隆比較划算些。這種 62 | 克隆初始化的更快,但得到克隆的功能有所削減。 63 | 64 | === 不穩定的項目 === 65 | 66 | 變更的大小決定寫入的速度快慢是Git的設計。一般人做了小的改動就會提交新版本。這 67 | 裡一行臭蟲修改,那裡一個新功能,修改掉的註釋等等。但如果你的檔案在相鄰版本之 68 | 間存在極大的差異,那每次提交時,你的歷史記錄會以整個項目的大小增長。 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 任何版本控制系統對此都束手無策,但標準的Git用戶將遭受更多,因為一般來說,歷史 79 | 記錄也會被克隆。 80 | 81 | 應該檢查一下變更巨大的原因。或許檔案格式需要改變一下。小修改應該僅僅導致幾個 82 | 檔案的細小改動。 83 | 84 | 或許,資料庫或備份/打包方案才是正選,而不是版本控制系統。例如,版本控制就不適 85 | 宜用來管理網絡攝像頭周期性拍下的照片。 86 | 87 | 如果這些檔案實在需要不斷更改,他們實在需要版本控制,一個可能的辦法是以中心的 88 | 方式使用Git。可以創建淺克隆,這樣檢出的較少,也沒有項目的歷史記錄。當然,很多 89 | Git工具就不能用了,並且修復必須以補丁的形式提交。這也許還不錯,因為似乎沒人需 90 | 要大幅度變化的不穩定檔案歷史。 91 | 92 | 另一個例子是基于韌體的項目,使用巨大的二進制檔案形式。用戶對韌體檔案的變化歷 93 | 史沒有興趣,更新的壓縮比很低,因此韌體修訂將使倉庫無謂的變大。 94 | 95 | 這種情況,源碼應該保存在一個Git倉庫裡,二進制檔案應該單獨保存。為了簡化問題, 96 | 應該發佈一個腳本,使用Git克隆源碼,對韌體只做同步或Git淺克隆。 97 | 98 | === 全局計數器 === 99 | 100 | 一些中心版本控制系統維護一個正整數,當一個新提交被接受的時候這個整數就增長。Git則是通過哈希值來記錄所有變更,這在大多數情況下都工作的不錯。 101 | 102 | 但一些人喜歡使用整數的方法。幸運的是,很容易就可以寫個腳本,這樣每次更新,中心Git倉庫就增大這個整數,或使用tag的方式,把最新提交的哈希值與這個整數關聯起來。 103 | 104 | 每個克隆都可以維護這麼個計數器,但這或許沒什麼用,因為只有中心倉庫以及它的計數器對每個人才有意義。 105 | 106 | === 空子目錄 === 107 | 108 | 空子目錄不可加入管理。可以通過創建一個空檔案以繞過這個問題。 109 | 110 | Git的當前實現,而不是它的設計,是造成這個缺陷的原因。如果運氣好,一旦Git得到 111 | 更多關注,更多用戶要求這個功能,這個功能就會被實現。 112 | 113 | === 初始提交 === 114 | 115 | 傳統的計算機系統從0計數,而不是1。不幸的是,關於提交,Git並不遵從這一約定。很 116 | 多命令在初始提交之前都不友好。另外,一些極少數的情況必須作特別地處理。例如重 117 | 訂一個使用不同初始提交的分支。 118 | 119 | Git將從定義零提交中受益:一旦一個倉庫被創建起來,HEAD將被設為包含20個零位元組 120 | 的字元串。這個特別的提交代表一棵空的樹,沒有父節點,早于所有Git倉庫。 121 | 122 | 然後運行git log,比如,通知用戶至今還沒有提交過變更,而不是報告致命錯誤並退出。 123 | 這與其他工具類似。 124 | 125 | 每個初始提交都隱式地成為這個零提交的後代。 126 | 127 | 不幸的是還有更糟糕的情況。如果把幾個具有不同初始提交的分支合併到一起,之後的 128 | 重新修訂不可避免的需要人員的介入。 129 | 130 | === 介面怪癖 === 131 | 132 | 對提交A和提交B,表達式“A..B”和“A...B”的含義,取決於命令期望兩個終點還是一 133 | 個範圍。參見 *git help diff* 和 *git help rev-parse* 。 134 | -------------------------------------------------------------------------------- /zh_tw/grandmaster.txt: -------------------------------------------------------------------------------- 1 | == Git大師技 == 2 | 3 | 到現在,你應該有能力查閲 *git help* 頁,並理解几乎所有東西。然而,查明解決特 4 | 定問題需要的確切命令可能是乏味的。或許我可以省你點功夫:以下是我過去曾經需要 5 | 的一些食譜。 6 | 7 | === 源碼發佈 === 8 | 9 | 就我的項目而言,Git完全跟蹤了我想打包並發佈給用戶的檔案。創建一個源碼包,我運 10 | 行: 11 | 12 | $ git archive --format=tar --prefix=proj-1.2.3/ HEAD 13 | 14 | === 提交變更 === 15 | 16 | 對特定項目而言,告訴Git你增加,刪除和重命名了一些檔案很麻煩。而鍵入如下命令會容易的多: 17 | 18 | $ git add . 19 | $ git add -u 20 | 21 | Git將查找當前目錄的檔案並自己算出具體的情況。除了用第二個add命令,如果你也打 22 | 算這時提交,可以運行`git commit -a`。關於如何指定應被忽略的檔案,參見 *git 23 | help ignore* 。 24 | 25 | 你也可以用一行命令完成以上任務: 26 | 27 | $ git ls-files -d -m -o -z | xargs -0 git update-index --add --remove 28 | 29 | 這裡 *-z* 和 *-0* 選項可以消除包含特殊字元的檔案名引起的不良副作用。注意這個 30 | 命令也添加應被忽略的檔案,這時你可能需要加上 `-x` 或 `-X` 選項。 31 | 32 | === 我的提交太大了! === 33 | 34 | 是不是忽視提交太久了?痴迷地編碼,直到現在才想起有源碼控制工具這回事?提交一 35 | 系列不相關的變更,因為那是你的風格? 36 | 37 | 別擔心,運行: 38 | 39 | $ git add -p 40 | 41 | 為你做的每次修改,Git將展示給你變動的代碼,並詢問該變動是否應是下一次提交的一 42 | 部分。回答“y”或者“n”。也有其他選項,比如延遲決定;鍵入“?”來學習更多。 43 | 44 | 一旦你滿意,鍵入 45 | 46 | $ git commit 47 | 48 | 來精確地提交你所選擇的變更(階段變更)。確信你沒加上 *-a* 選項,否則Git將提交 49 | 所有修改。 50 | 51 | 如果你修改了許多地方的許多檔案怎麼辦?一個一個地查看變更令人沮喪,心態麻木。 52 | 這種情況下,使用 *git add -i* , 它的界面不是很直觀,但更靈活。敲幾個鍵,你可 53 | 以一次決定階段或非階段性提交幾個檔案,或查看並只選擇特定檔案的變更。作為另一 54 | 種選擇,你還可以運行 *git commit --interactive* ,這個命令會在你操作完後自動 55 | 進行提交。 56 | 57 | === 索引:Git的中轉區域 === 58 | 59 | 當目前為止,我們已經忽略Git著名的'索引‘概念,但現在我們必須面對它,以解釋上 60 | 面發生的。索引是一個臨時中轉區。Git很少在你的項目和它的歷史之間直接倒騰數據。 61 | 通常,Git先寫數據到索引,然後拷貝索引中的數據到最終目的地。 62 | 63 | 例如, *commit -a* 實際上是一個兩步過程。第一步把每個追蹤檔案當前狀態的快照放 64 | 到索引中。第二步永久記錄索引中的快照。 沒有 *-a* 的提交只執行第二步,並且只在 65 | 運行不知何故改變索引的命令才有意義,比如 *git add* 。 66 | 67 | 通常我們可以忽略索引並假裝從歷史中直接讀並直接寫。在這個情況下,我們希望更好 68 | 地控制,因此我們操作索引。我們放我們變更的一些的快照到索引中,而不是所有的, 69 | 然後永久地記錄這個小心操縱的快照。 70 | 71 | === 別丟了你的HEAD === 72 | 73 | HEAD好似一個游標,通常指向最新提交,隨最新提交向前移動。一些Git命令讓你來移動 74 | 它。 例如: 75 | 76 | $ git reset HEAD~3 77 | 78 | 將立即向回移動HEAD三個提交。這樣所有Git命令都表現得好似你沒有做那最後三個提交, 79 | 然而你的檔案保持在現在的狀態。具體應用參見幫助頁。 80 | 81 | 但如何回到將來呢?過去的提交對將來一無所知。 82 | 83 | 如果你有原先Head的SHA1值,那麼: 84 | 85 | $ git reset 1b6d 86 | 87 | 但假設你從來沒有記下呢?別擔心,像這些命令,Git保存原先的Head為一個叫 88 | ORGI_HEAD的標記,你可以安全體面的返回: 89 | 90 | $ git reset ORIG_HEAD 91 | 92 | === HEAD捕獵 === 93 | 94 | 或許ORG_HEAD不夠。或許你剛認識到你犯了個歷史性的錯誤,你需要回到一個早已忘記 95 | 分支上一個遠古的提交。 96 | 97 | 預設,Git保存一個提交至少兩星期,即使你命令Git摧毀該提交所在的分支。難點是找 98 | 到相應的哈希值。你可以查看在.git/objects裡所有的哈希值並嘗試找到你期望的。但 99 | 有一個更容易的辦法。 100 | 101 | Git把算出的提交哈希值記錄在“.git/logs”。這個子目錄引用包括所有分支上所有活 102 | 動的歷史,同時檔案HEAD顯示它曾經有過的所有哈希值。後者可用來發現分支上一些不 103 | 小心丟掉提交的哈希值。 104 | 105 | The reflog command provides a friendly interface to these log files. Try 106 | 107 | 命令reflog為訪問這些日誌檔案提供友好的介面,試試 108 | 109 | $ git reflog 110 | 111 | 而不是從reflog拷貝粘貼哈希值,試一下: 112 | 113 | $ git checkout "@{10 minutes ago}" 114 | 115 | 或者撿出後五次訪問過的提交,通過: 116 | 117 | $ git checkout "@{5}" 118 | 119 | 更多內容參見 *git help rev-parse* 的``Specifying Revisions''部分。 120 | 121 | 你或許期望去為已刪除的提交設置一個更長的保存周期。例如: 122 | 123 | $ git config gc.pruneexpire "30 days" 124 | 125 | 意思是一個被刪除的提交會在刪除30天後,且運行 *git gc* 以後,被永久丟棄。 126 | 127 | 你或許還想關掉 *git gc* 的自動運行: 128 | 129 | $ git config gc.auto 0 130 | 131 | 在這種情況下提交將只在你手工運行 *git gc* 的情況下才永久刪除。 132 | 133 | === 基于Git構建 === 134 | 135 | 依照真正的UNIX風格設計,Git允許其易於用作其他程序的底層組件,比如圖形界面, 136 | Web界面,可選擇的命令行界面,補丁管理工具,導入和轉換工具等等。實際上,一些 137 | Git命令它們自己就是站在巨人肩膀上的腳本。通過一點修補,你可以定製Git適應你的 138 | 偏好。 139 | 140 | 一個簡單的技巧是,用Git內建alias命令來縮短你最常使用命令: 141 | 142 | $ git config --global alias.co checkout 143 | $ git config --global --get-regexp alias # 顯示當前別名 144 | alias.co checkout 145 | $ git co foo # 和“git checkout foo”一樣 146 | 147 | 另一個技巧,在提示符或窗口標題上打印當前分支。調用: 148 | 149 | $ git symbolic-ref HEAD 150 | 151 | 顯示當前分支名。在實際應用中,你可能最想去掉“refs/heads/”並忽略錯誤: 152 | 153 | $ git symbolic-ref HEAD 2> /dev/null | cut -b 12- 154 | 155 | 子目錄 +contrib+ 是一個基于Git工具的寶庫。它們中的一些時時會被提升為官方命令。 156 | 在Debian和Ubuntu,這個目錄位於 +/usr/share/doc/git-core/contrib+ 。 157 | 158 | 一個受歡迎的居民是 +workdir/git-new-workdir+ 。通過聰明的符號連結,這個腳本創 159 | 建一個新的工作目錄,其歷史與原來的倉庫共享: 160 | 161 | $ git-new-workdir an/existing/repo new/directory 162 | 163 | 這個新的目錄和其中的檔案可被視為一個克隆,除了既然歷史是共享的,兩者的樹自動 164 | 保持同步。不必合併,推入或拉出。 165 | 166 | === 大膽的特技 === 167 | 168 | 這些天,Git使得用戶意外摧毀數據變得更困難。但如若你知道你在做什麼,你可以突破 169 | 為通用命令所設的防衛保障。 170 | 171 | *Checkout*:未提交的變更會導致撿出失敗。銷毀你的變更,並無論如何都checkout一 172 | 個指定的提交,使用強制標記: 173 | 174 | $ git checkout -f HEAD^ 175 | 176 | 另外,如果你為撿出指定特別路徑,那就沒有安全檢查了。提供的路徑將被不加提示地 177 | 覆蓋。如你使用這種方式的檢出,要小心。 178 | 179 | *Reset*: 如有未提交變更重置也會失敗。強制其通過,運行: 180 | 181 | $ git reset --hard 1b6d 182 | 183 | *Branch*: 引起變更丟失的分支刪除會失敗。強制刪除,鍵入: 184 | 185 | $ git branch -D dead_branch # instead of -d 186 | 187 | 類似,通過移動試圖覆蓋分支,如果隨之而來有數據丟失,也會失敗。強制移動分支,鍵入: 188 | 189 | $ git branch -M source target # 而不是 -m 190 | 191 | 不像checkout和重置,這兩個命令延遲數據銷毀。這個變更仍然存儲在.git的子目錄裡, 192 | 並且可以通過恢復.git/logs裡的相應哈希值獲取(參見上面 上面“HEAD獵捕”)。默 193 | 認情況下,這些數據會保存至少兩星期。 194 | 195 | *Clean*: 一些Git命令拒絶執行,因為它們擔心會重裝未納入管理的檔案。如果你確信 196 | 所有未納入管理的檔案都是消耗,那就無情地刪除它們,使用: 197 | 198 | $ git clean -f -d 199 | 200 | 下次,那個討厭的命令就會工作! 201 | 202 | === 阻止壞提交 === 203 | 204 | 愚蠢的錯誤污染我的倉庫。最可怕的是由於忘記 *git add* 而引起的檔案丟失。較小 205 | 的罪過是行末追加空格並引起合併衝突:儘管危害少,我希望浙西永遠不要出現在公開 206 | 記錄裡。 207 | 208 | 不過我購買了傻瓜保險,通過使用一個_鈎子_來提醒我這些問題: 209 | 210 | $ cd .git/hooks 211 | $ cp pre-commit.sample pre-commit # 對舊版本Git,先運行chmod +x 212 | 213 | 現在Git放棄提交,如果檢測到無用的空格或未解決的合併衝突。 214 | 215 | 對本文檔,我最終添加以下到 *pre-commit* 鈎子的前面,來防止缺魂兒的事: 216 | 217 | if git ls-files -o | grep '\.txt$'; then 218 | echo FAIL! Untracked .txt files. 219 | exit 1 220 | fi 221 | 222 | 幾個git操作支持鈎子;參見 *git help hooks* 。我們早先激活了作為例子的 223 | *post-update* 鈎子,當討論基于HTTP的Git的時候。無論head何時移動,這個鈎子都會 224 | 運行。例子腳本post-update更新Git在基于Git並不知曉的傳輸協議,諸如HTTP,通訊時 225 | 所需的檔案。 226 | 227 | -------------------------------------------------------------------------------- /zh_tw/history.txt: -------------------------------------------------------------------------------- 1 | == 關於歷史 == 2 | 3 | Git分散式本性使得歷史可以輕易編輯。但你若篡改過去,需要小心:只重寫你獨自擁有 4 | 的那部分。正如民族間會無休止的爭論誰犯下了什麼暴行一樣,如果在另一個人的克隆 5 | 裡,歷史版本與你的不同,當你們的樹互操作時,你會遇到一致性方面的問題。 6 | 7 | 一些開發人員強烈地感覺歷史應該永遠不變,不好的部分也不變所有都不變。另一些覺 8 | 得代碼樹在向外發佈之前,應該整得漂漂亮亮的。Git同時支持兩者的觀點。像克隆,分 9 | 支和合併一樣,重寫歷史只是Git給你的另一強大功能,至于如何明智地使用它,那是你 10 | 的事了。 11 | 12 | === 我認錯 === 13 | 14 | 剛提交,但你期望你輸入的是一條不同的信息?那麼鍵入: 15 | 16 | $ git commit --amend 17 | 18 | 來改變上一條信息。意識到你還忘記了加一個檔案?運行git add來加,然後運行上面的 19 | 命令。 20 | 21 | 希望在上次提交裡包括多一點的改動?那麼就做這些改動並運行: 22 | 23 | $ git commit --amend -a 24 | 25 | === 更複雜情況 === 26 | 27 | 假設前面的問題還要糟糕十倍。在漫長的時間裡我們提交了一堆。但你不太喜歡他們的 28 | 組織方式,而且一些提交信息需要重寫。那麼鍵入: 29 | 30 | $ git rebase -i HEAD~10 31 | 32 | 並且後10個提交會出現在你喜愛的$EDITOR。一個例子: 33 | 34 | pick 5c6eb73 Added repo.or.cz link 35 | pick a311a64 Reordered analogies in "Work How You Want" 36 | pick 100834f Added push target to Makefile 37 | 38 | 之後: 39 | 40 | - 通過刪除行來移去提交。 41 | - 通過為行重新排序行來重新排序提交。 42 | - 替換 `pick` 使用: 43 | * `edit` 標記一個提交需要修訂。 44 | * `reword` 改變日誌信息。 45 | * `squash` 將一個提交與其和前一個合併。 46 | * `fixup` 將一個提交與其和前一個合併,並丟棄日誌信息。 47 | 48 | 保存退出。如果你把一個提交標記為可編輯,那麼運行 49 | 50 | $ git commit --amend 51 | 52 | 否則,運行: 53 | 54 | $ git rebase --continue 55 | 56 | 這樣儘早提交,經常提交:你之後還可以用rebase來規整。 57 | 58 | === 本地變更之後 === 59 | 60 | 你正在一個活躍的項目上工作。隨着時間推移,你做了幾個本地提交,然後你使用合併 61 | 與官方版本同步。在你準備好提交到中心分支之前,這個循環會重複幾次。 62 | 63 | 但現在你本地Git克隆摻雜了你的改動和官方改動。你更期望在變更列表裡,你所有的變 64 | 更能夠連續。 65 | 66 | 這就是上面提到的 *git rebase* 所做的工作。在很多情況下你可以使用 *--onto* 標 67 | 記以避免交互。 68 | 69 | 另外參見 *git help rebase* 以獲取這個讓人驚奇的命令更詳細的例子。你可以拆分提 70 | 交。你甚至可以重新組織一棵樹的分支。 71 | 72 | === 重寫歷史 === 73 | 74 | 偶爾,你需要做一些代碼控制,好比從正式的照片中去除一些人一樣,需要從歷史記錄 75 | 裡面徹底的抹掉他們。例如,假設我們要發佈一個項目,但由於一些原因,項目中的某 76 | 個檔案不能公開。或許我把我的信用卡號記錄在了一個文本檔案裡,而我又意外的把它 77 | 加入到了這個項目中。僅僅刪除這個檔案是不夠的,因為從別的提交記錄中還是可以訪 78 | 問到這個檔案。因此我們必須從所有的提交記錄中徹底刪除這個檔案。 79 | 80 | $ git filter-branch --tree-filter 'rm top/secret/file' HEAD 81 | 82 | 參見 *git help filter-branch* ,那裡討論了這個例子並給出一個更快的方法。一般 83 | 地, *filter-branch* 允許你使用一個單一命令來大範圍地更改歷史。 84 | 85 | 此後,+.git/refs/original+目錄描述操作之前的狀態。檢查命令filter-branch的確做 86 | 了你想要做的,然後刪除此目錄,如果你想運行多次filter-branch命令。 87 | 88 | 最後,用你修訂過的版本替換你的項目克隆,如果你想之後和它們交互的話。 89 | 90 | === 製造歷史 === 91 | 92 | [[makinghistory]] 93 | 想把一個項目遷移到Git嗎?如果這個項目是在用比較有名氣的系統,那可以使用一些其 94 | 他人已經寫好的腳本,把整個項目歷史記錄導出來放到Git裡。 95 | 96 | 否則,查一下 *git fast-import* ,這個命令會從一個特定格式的文本讀入,從頭來創 97 | 建Git歷史記錄。通常可以用這個命令很快寫一個腳本運行一次,一次遷移整個項目。 98 | 99 | 作為一個例子,粘貼以下所列到臨時檔案,比如/tmp/history: 100 | 101 | ---------------------------------- 102 | commit refs/heads/master 103 | committer Alice <alice@example.com> Thu, 01 Jan 1970 00:00:00 +0000 104 | data <<EOT 105 | Initial commit. 106 | EOT 107 | 108 | M 100644 inline hello.c 109 | data <<EOT 110 | #include <stdio.h> 111 | 112 | int main() { 113 | printf("Hello, world!\n"); 114 | return 0; 115 | } 116 | EOT 117 | 118 | 119 | commit refs/heads/master 120 | committer Bob <bob@example.com> Tue, 14 Mar 2000 01:59:26 -0800 121 | data <<EOT 122 | Replace printf() with write(). 123 | EOT 124 | 125 | M 100644 inline hello.c 126 | data <<EOT 127 | #include <unistd.h> 128 | 129 | int main() { 130 | write(1, "Hello, world!\n", 14); 131 | return 0; 132 | } 133 | EOT 134 | 135 | ---------------------------------- 136 | 137 | 之後從這個臨時檔案創建一個Git倉庫,鍵入: 138 | 139 | $ mkdir project; cd project; git init 140 | $ git fast-import --date-format=rfc2822 < /tmp/history 141 | 142 | 你可以從這個項目checkout出最新的版本,使用: 143 | 144 | $ git checkout master . 145 | 146 | 命令*git fast-export* 轉換任意倉庫到 *git fast-import* 格式,你可以研究其輸 147 | 出來寫導出程序, 也以可讀格式傳送倉庫。的確,這些命令可以發送倉庫文本檔案 148 | 通過只接受文本的渠道。 149 | 150 | 151 | === 哪兒錯了? === 152 | 153 | 你剛剛發現程序裡有一個功能出錯了,而你十分確定幾個月以前它運行的很正常。天啊! 154 | 這個臭蟲是從哪裡冒出來的?要是那時候能按照開發的內容進行過測試該多好啊。 155 | 156 | 現在說這個已經太晚了。然而,即使你過去經常提交變更,Git還是可以精確的找出問題所在: 157 | 158 | $ git bisect start 159 | $ git bisect bad HEAD 160 | $ git bisect good 1b6d 161 | 162 | Git從歷史記錄中檢出一個中間的狀態。在這個狀態上測試功能,如果還是有問題: 163 | 164 | $ git bisect bad 165 | 166 | 如果可以工作了,則把"bad"替換成"good"。Git會再次幫你找到一個以確定的好版本和 167 | 壞版本之間的狀態,通過這種方式縮小範圍。經過一系列的迭代,這種二分搜索會幫你 168 | 找到導致這個錯誤的那次提交。一旦完成了問題定位的調查,你可以返回到原始狀態, 169 | 鍵入: 170 | 171 | $ git bisect reset 172 | 173 | 不需要手工測試每一次改動,執行如下命令可以自動的完成上面的搜索: 174 | 175 | $ git bisect run my_script 176 | 177 | Git使用指定命令(通常是一個一次性的腳本)的返回值來決定一次改動是否是正確的: 178 | 命令退出時的代碼0代表改動是正確的,125代表要跳過對這次改動的檢查,1到127之間 179 | 的其他數值代表改動是錯誤的。返回負數將會中斷整個bisect的檢查。 180 | 181 | 你還能做更多的事情: 幫助文檔解釋了如何展示bisects, 檢查或重放bisect的日誌,並 182 | 可以通過排除對已知正確改動的檢查,得到更好的搜索速度。 183 | 184 | === 誰讓事情變糟了? === 185 | 186 | 和其他許多版本控制系統一樣,Git也有一個"blame"命令: 187 | 188 | $ git blame bug.c 189 | 190 | 這個命令可以標註出一個指定的檔案裡每一行內容的最後修改者,和最後修改時間。但 191 | 不像其他版本控制系統,Git的這個操作是在綫下完成的,它只需要從本地磁碟讀取信息。 192 | 193 | === 個人經驗 === 194 | 195 | 在一個中心版本控制系統裡,歷史的更改是一個困難的操作,並且只有管理員才有權這 196 | 麼做。沒有網絡,克隆,分支和合併都沒法做。像一些基本的操作如瀏覽歷史,或提交 197 | 變更也是如此。在一些系統裡,用戶使用網絡連接僅僅是為了查看他們自己的變更,或 198 | 打開檔案進行編輯。 199 | 200 | 中心繫統排斥離線工作,也需要更昂貴的網絡設施,特別是當開發人員增多的時候。最 201 | 重要的是,所有操作都一定程度變慢,一般在用戶避免使用那些能不用則不用的高級命 202 | 令時。在極端的情況下,即使是最基本的命令也會變慢。當用戶必須運行緩慢的命令的 203 | 時候,由於工作流被打斷,生產力降低。 204 | 205 | 我有這些的一手經驗。Git是我使用的第一個版本控制系統。我很快學會適應了它,用了 206 | 它提供的許多功能。我簡單地假設其他系統也是相似的:選擇一個版本控制系統應該和 207 | 選擇一個編輯器或瀏覽器沒啥兩樣。 208 | 209 | 在我之後被迫使用中心繫統的時候,我被震驚了。我那有些脆弱的網絡沒給Git帶來大麻 210 | 煩,但是當它需要像本地硬碟一樣穩定的時候,它使開發困難重重。另外,我發現我自 211 | 己有選擇地避免特定的命令,以避免踏雷,這極大地影響了我,使我不能按照我喜歡的 212 | 方式工作。 213 | 214 | 當我不得不運行一個慢的命令的時候,這種等待極大地破壞了我思緒連續性。在等待服 215 | 務器通訊完成的時候,我選擇做其他的事情以度過這段時光,比如查看郵件或寫其他的 216 | 文檔。當我返回我原先的工作場景的時候,這個命令早已結束,並且我還需要浪費時間 217 | 試圖記起我之前正在做什麼。人類不擅長場景間的切換。 218 | 219 | 還有一個有意思的大眾悲劇效應:預料到網絡擁擠,為了減少將來的等待時間,每個人 220 | 將比以往消費更多的頻寬在各種操作上。共同的努力加劇了擁擠,這等於是鼓勵個人下 221 | 次消費更多頻寬以避免更長時間的等待。 222 | 223 | 224 | -------------------------------------------------------------------------------- /zh_tw/intro.txt: -------------------------------------------------------------------------------- 1 | == 入門 == 2 | 3 | 我將用類比方式來介紹版本控制的概念。更嚴謹的解釋參見 4 | http://en.wikipedia.org/wiki/Revision_control[維基百科版本修訂控制條目]。 5 | 6 | === 工作是玩 === 7 | 8 | 我從小就玩電腦遊戲。相反,我只是在長大後才開始使用版本控制系統。我想我並不特 9 | 殊,並且,對比兩者工作方式可使這些概念更易解釋,也易於理解。 10 | 11 | 編寫代碼,或編輯文檔和玩遊戲差不多。在你做出了很多進展之後,你最好保存一下。 12 | 去做這個,會點擊你所信任的編輯器保存按鈕就好了。 13 | 14 | 但這將覆蓋老版本。就像那些學校裡玩的老遊戲,只有一個存檔:你確實可以保存,但 15 | 你不能回到更老的狀態了。這真讓人掃興,因為那個狀態可能恰好保存了這個遊戲特別 16 | 有意思一關,說不定哪天你想再玩一下呢。或者更糟糕的,你當前的保存是個必敗局, 17 | 這樣你就不得不從頭開始玩了。 18 | 19 | === 版本控制 === 20 | 21 | 在編輯的時候,如果想保留舊版本,你可以將檔案“另存為”一個不同的檔案,或在保 22 | 存之前將檔案拷貝到別處。你可能壓縮這些檔案以節省空間。這是一個初級的靠手工的 23 | 版本控制方式。遊戲軟件早就提高了這塊,很多都提供多個基于時間戳的自動存檔槽。 24 | 25 | 讓我們看看稍稍複雜的情況。比如你有很多放在一起的檔案,比如項目源碼,或網站文 26 | 件。現在如你想保留舊版本,你不得不把整個目錄存檔。手工保存多個版本很不方便, 27 | 而且很快會耗費巨大。 28 | 29 | 在一些電腦遊戲裡,一個存檔真的包含在一個充滿檔案的目錄裡。這些遊戲為玩家屏蔽 30 | 了這些細節,並提供一個方便易用的界面來管理該目錄的不同版本。 31 | 32 | 版本控制系統也沒有兩樣。兩者提供友好的界面,來管理目錄裡的東西。你可以頻繁保 33 | 存,也可以之後加載任一保存。不像大多計算機遊戲,版本控制系統通常精於節省存儲 34 | 空間。一般情況如果兩個版本間只有少數檔案的變更,每個檔案的變更也不大,那就只 35 | 存儲差異的部分,而不是把全部拷貝的都保存下來,以節省存儲空間。 36 | 37 | === 分佈控制 === 38 | 39 | 現在設想一個很難的遊戲。太難打了,以至于世界各地很多骨灰級玩家決定組隊,分享 40 | 他們遊戲存檔以攻克它。Speedrun們就是實際中的例子:在同一個遊戲裡,玩家們分別 41 | 攻克不同的等級,協同工作以創造驚人戰績。 42 | 43 | 你如何搭建一個系統,使得他們易於得到彼此的存檔?並易於上載新的存檔? 44 | 45 | 在過去,每個項目都使用中心式版本控制。某個伺服器上放所有保存的遊戲記錄。其他 46 | 人就不用了。每個玩家在他們機器上最多保留幾個遊戲記錄。當一個玩家想更新進度時 47 | 候,他們需要把最新進度從主伺服器下載下來,玩一會兒,保存並上載到主伺服器以供 48 | 其他人使用。 49 | 50 | 假如一個玩家由於某種原因,想得到一個較舊版本的遊戲進度怎麼樣?或許當前保存的 51 | 遊戲是一個注定的敗局,因為某人在第三級忘記撿某個物品;他們希望能找到最近一個 52 | 可以完成的遊戲記錄。或者他們想比較兩個舊版本間的差異,來估算某個特定玩家幹了 53 | 多少活。 54 | 55 | 查看舊版本的理由有很多,但檢查的辦法都是一樣的。他們必須去問中心伺服器要那個 56 | 舊版本的記錄。需要的舊版本越多,和伺服器的交互就越多。 57 | 58 | 新一代的版本控制系統,Git就是其中之一,是分散式的,可以被認作廣義上的中心式系 59 | 統。從主伺服器下載時玩家會得到所有保存的記錄,而不僅是最新版。這看起來他們好 60 | 像把中心伺服器做了個鏡像。 61 | 62 | 最初的克隆操作可能比較費時,特別當有很長歷史的時,但從長遠看這是值得的。一個 63 | 顯而易見的好處是,當查看一個舊版本時,不再需要和中心伺服器通訊了。 64 | 65 | === 一個誤區 === 66 | 67 | 一個很常見的錯誤觀念是,分散式系統不適合需要官方中心倉庫的項目。這與事實並不 68 | 相符。給誰照相也不會偷走他們的靈魂。類似地,克隆主倉庫並不降低它的重要性。 69 | 70 | 一般來說,一個中心版本控制系統能做的任何事,一個良好設計的分散式系統都能做得 71 | 更好。網絡資源總要比本地資源耗費更費。不過我們應該在稍後分析分散式方案的缺點, 72 | 這樣人們才不會按照習慣做出錯誤的比較。 73 | 74 | 一個小項目或許只需要分散式系統提供的一小部分功能,但是,在項目很小的時候,應 75 | 該用規劃不好的系統?就好比說,在計算較小數目的時候應該使用羅馬數字? 76 | 77 | 而且,你的項目的增長可能會超出你最初的預期。從一開始就使用Git好似帶著一把瑞士 78 | 軍刀,儘管你很多時候只是用它來開開瓶蓋。某天你迫切需要一把改錐,你就會慶幸你 79 | 所有的不單單是一個啟瓶器。 80 | 81 | === 合併衝突 === 82 | 83 | 對於這個話題,電腦遊戲的類比顯得不夠用。那讓我們再來看看文檔編輯的情況吧。 84 | 85 | 假設Alice在文檔開頭插入一行,並且Bob在文檔末尾添加一行。他們都上傳了他們的改 86 | 動。大多數系統將自動給出一個合理的處理方式:接受且合併他們的改動,這樣Alice和 87 | Bob兩人的改動都會生效。 88 | 89 | 現在假設Alice和Bob對檔案的同一行做了不同的改動。如果沒有人工參與的話,這個沖 90 | 突是無法解決的。第二個人在上載檔案時,會收到 _合併衝突_ 的通知,要麼用一個人 91 | 的改動覆蓋另一個的,要麼完全修訂這一行。 92 | 93 | 更複雜的情況也可能出現。版本控制系統自己處理相對簡單的情況,把困難的情況留給 94 | 人來處理。它們的行為通常是可配置的。 95 | 96 | -------------------------------------------------------------------------------- /zh_tw/multiplayer.txt: -------------------------------------------------------------------------------- 1 | == 多人Git == 2 | 3 | 我最初在一個私人項目上使用Git,那裡我是唯一的開發。在與Git分散式本性有關的命 4 | 令中,我只用到了 *pull* 和 *clone*,用以在不同地方保持同一個項目。 5 | 6 | 後來我想用Git發佈我的代碼,並且包括其他貢獻者的變更。我不得不學習如何管理有來 7 | 自世界各地的多個開發的項目,幸運的是,這是Git的長處,也可以說是其存在的理由。 8 | 9 | === 我是誰? === 10 | 11 | 每個提交都有一個作者姓名和電子信箱,這顯示在 *git log* 裡。預設, Git使用系統 12 | 設定來填充這些域。要顯示地設定,鍵入: 13 | 14 | $ git config --global user.name "John Doe" 15 | $ git config --global user.email johndoe@example.com 16 | 17 | 去掉global選項設定只對當前倉庫生效。 18 | 19 | === Git在SSH, HTTP上 === 20 | 21 | 假設你有ssh訪問權限,以訪問一個網頁伺服器,但上面並沒有安裝Git。儘管比着它的 22 | 原生協議效率低,Git也是可以通過HTTP來進行通信的。 23 | 24 | 那麼在你的帳戶下,下載,編譯並安裝Git。在你的網頁目錄裡創建一個Git倉庫: 25 | 26 | $ GIT_DIR=proj.git git init 27 | $ cd proj.git 28 | $ git --bare update-server-info 29 | $ cp hooks/post-update.sample hooks/post-update 30 | 31 | 對較老版本的Git,只拷貝還不夠,你應運行: 32 | 33 | $ chmod a+x hooks/post-update 34 | 35 | 現在你可以通過SSH從隨便哪個克隆發佈你的最新版本: 36 | 37 | $ git push web.server:/path/to/proj.git master 38 | 39 | 那隨便誰都可以通過如下命令得到你的項目: 40 | 41 | $ git clone http://web.server/proj.git 42 | 43 | === Git在隨便什麼上 === 44 | 45 | 想無需伺服器,甚至無需網絡連接的時候同步倉庫?需要在緊急時期湊合一下?我們 46 | 已經看過<<makinghistory, *git fast-export* 和 *git fast-import* 可以轉換資源 47 | 庫到一個單一檔案以及轉回來>>。 我們可以來來會會傳送這些檔案以傳輸git倉庫, 48 | 通過任何媒介,但一個更有效率的工具是 *git bundle* 。 49 | 50 | 發送者創建一個“檔案包”: 51 | 52 | $ git bundle create somefile HEAD 53 | 54 | 然後傳輸這個檔案包, +somefile+ ,給某個其他參與者:電子郵件,優盤,一個 55 | *xxd* 打印品和一個OCR掃描器,通過電話讀位元組,狼煙,等等。接收者通過鍵入如下命 56 | 令從檔案包獲取提交: 57 | 58 | $ git pull somefile 59 | 60 | 接收者甚至可以在一個空倉庫做這個。不考慮大小, +somefile+ 可以包含整個原先 61 | git倉庫。 62 | 63 | 在較大的項目裡,可以通過只打包其他倉庫缺少的變更消除浪費。例如,假設提交 64 | ``1b6d...''是兩個參與者共享的最近提交: 65 | 66 | $ git bundle create somefile HEAD ^1b6d 67 | 68 | 如果做的頻繁,人可能容易忘記剛發了哪個提交。幫助頁面建議使用標籤解決這個問題。 69 | 即,在你發了一個檔案包後,鍵入: 70 | 71 | $ git tag -f lastbundle HEAD 72 | 73 | 並創建較新檔案包,使用: 74 | 75 | $ git bundle create newbundle HEAD ^lastbundle 76 | 77 | === 補丁:全球貨幣 === 78 | 79 | 補丁是變更的文本形式,易於計算機理解,人也類似。補丁可以通吃。你可以給開發電 80 | 郵一個補丁,不用管他們用的什麼版本控制系統。只要你的觀眾可以讀電子郵件,他們 81 | 就能看到你的修改。類似,在你這邊,你只需要一個電子郵件帳號:不必搭建一個在綫 82 | 的Git倉庫。 83 | 84 | 回想一下第一章: 85 | 86 | $ git diff 1b6d > my.patch 87 | 88 | 輸出是一個補丁,可以粘貼到電子郵件裡用以討論。在一個Git倉庫,鍵入: 89 | 90 | $ git apply < my.patch 91 | 92 | 來打這個補丁。 93 | 94 | 在更正式些的設置裡,當作者名字以及或許簽名應該記錄下的時候,為過去某一刻生成 95 | 補丁,鍵入: 96 | 97 | $ git format-patch 1b6d 98 | 99 | 結果檔案可以給 *git-send-email* 發送,或者手工發送。你也可以指定一個提交範圍: 100 | 101 | $ git format-patch 1b6d..HEAD^^ 102 | 103 | 在接收一端,保存郵件到一個檔案,然後鍵入: 104 | 105 | $ git am < email.txt 106 | 107 | 這就打了補丁並創建了一個提交,包含諸如作者之類的信息。 108 | 109 | 使用瀏覽器郵件客戶端,在保存補丁為檔案之前,你可能需要建一個按鈕,看看郵件內 110 | 容原來的原始形式。 111 | 112 | 對基于mbox的郵件客戶端有些微不同,但如果你在使用的話,你可能是那種能輕易找出 113 | 答案的那種人,不用讀教程。 114 | 115 | === 對不起,移走了 === 116 | 117 | 克隆一個倉庫後,運行 *git push* 或 *git pull* 講自動推到或從原先URL拉。Git 118 | 如何做這個呢?秘密在和克隆一起創建的配置選項。讓我們看一下: 119 | 120 | $ git config --list 121 | 122 | 選項 +remote.origin.url+ 控制URL源;``origin'' 是給源倉庫的暱稱。和 123 | ``master'' 分支的慣例一樣,我們可以改變或刪除這個暱稱,但通常沒有理由這麼做。 124 | 125 | 如果原先倉庫移走,我們可以更新URL,通過: 126 | 127 | $ git config remote.origin.url git://new.url/proj.git 128 | 129 | 選項 +branch.master.merge+ 指定 *git pull* 裡的預設遠端分支。在初始克隆的時候, 130 | 它被設為原倉庫的當前分支,因此即使原倉庫之後挪到一個不同的分支,後來的 131 | pull也將忠實地跟着原來的分支。 132 | 133 | 這個選項只使用我們初次克隆的倉庫,它的值記錄在選項 +branch.master.remote+ 134 | 。如果我們從其他倉庫拉入,我們必須顯示指定我們想要哪個分支: 135 | 136 | $ git pull git://example.com/other.git master 137 | 138 | 以上也解釋了為什麼我們較早一些push和pull的例子沒有參數。 139 | 140 | === 遠端分支 === 141 | 142 | 當你克隆一個倉庫,你也克隆了它的所有分支。你或許沒有注意到因為Git將它們隱藏 143 | 起來了:你必須明確地要求。這使得遠端倉庫裡的分支不至于干擾你的分支,也使 144 | Git對初學者稍稍容易些。 145 | 146 | 列出遠端分支,使用: 147 | 148 | $ git branch -r 149 | 150 | 你應該看到類似: 151 | 152 | origin/HEAD 153 | origin/master 154 | origin/experimental 155 | 156 | 這顯示了遠端倉庫的分支和HEAD,可以用在常用的Git命令裡。例如,假設你已經做了 157 | 很多提交,並希望和最後取到的版本比較一下。你可以搜索適當的SHA1哈希值,但使用 158 | 下面命令更容易些: 159 | 160 | $ git diff origin/HEAD 161 | 162 | 或你可以看看``experimental''分支都有啥: 163 | 164 | $ git log origin/experimental 165 | 166 | === 多遠端 === 167 | 168 | 假設另兩個開發在同一個項目上工作,我們希望保持兩個標籤。我們可以同事跟多個倉庫: 169 | 170 | $ git remote add other git://example.com/some_repo.git 171 | $ git pull other some_branch 172 | 173 | 現在我們已經從第二個倉庫合併到一個分支,並且我們已容易訪問所有倉庫的所有 174 | 分支。 175 | 176 | $ git diff origin/experimental^ other/some_branch~5 177 | 178 | 但如果為了不影響自己的工作,我們只想比較他們的變更怎麼辦呢?換句話說,我們想 179 | 檢查一下他們的分支,又不使他們的變更入侵我們的工作目錄。那不是運行pull命令, 180 | 而是運行: 181 | 182 | $ git fetch # Fetch from origin, the default. 183 | $ git fetch other # Fetch from the second programmer. 184 | 185 | 這只是獲取歷史。儘管工作目錄維持不變,我們可以參考任何倉庫的任何分支,使用 186 | 一個Git命令,因為我們現在有一個本地拷貝。 187 | 188 | 回想一下,在幕後,一個pull是簡單地一個 *fetch* 然後 *merge* 。通常,我們 189 | *pull* 因為我們想在獲取後合併最近提交;這個情況是一個值得注意的例外。 190 | 191 | 關於如何去除遠端倉庫,如何忽略特定分支等更多,參見 *git help remote* 。 192 | 193 | === 我的喜好 === 194 | 195 | 對我手頭的項目,我喜歡貢獻者去準備倉庫,這樣我可以從其中拉。一些Git伺服讓你 196 | 點一個按鈕,擁有自己的分叉項目。 197 | 198 | 在我獲取一個樹之後,我運行Git命令去瀏覽並檢查這些變更,理想情況下這些變更組織 199 | 良好,描述良好。我合併這些變更,也或許做些編輯。直到滿意,我才把變更推入主資 200 | 源庫。 201 | 202 | 儘管我不經常收到貢獻,我相信這個方法擴展性良好。參見 203 | http://torvalds-family.blogspot.com/2009/06/happiness-is-warm-scm.html[ 這篇 204 | 來自Linus Torvalds的博客 ] 205 | 206 | 獃在Git的世界裡比補丁檔案稍更方便,因為不用我將補丁轉換到Git提交。更進一步, 207 | Git處理諸如作者姓名和信箱地址的細節,還有時間和日期,以及要求作者描述他們的提 208 | 交。 209 | -------------------------------------------------------------------------------- /zh_tw/preface.txt: -------------------------------------------------------------------------------- 1 | = Git 魔法 = 2 | Ben Lynn 3 | 2007年8月 4 | 5 | == 前言 == 6 | 7 | http://git.or.cz/[Git] 堪稱版本控制瑞士軍刀。這個可靠、多才多藝、用途多樣的校 8 | 訂工具異常靈活,以致不易掌握,更別說精通了。 9 | 10 | 正如Arthur C. Clarke所說,足夠先進的技術與魔法無二。這是學習Git的好辦法:新手 11 | 不妨忽略Git的內部機理,只當小把戲玩,借助Git其奇妙的能力,逗逗朋友,氣氣敵人。 12 | 13 | 為了不陷入細節,我們對特定功能提供大面上的講解。在反覆應用之後,慢慢地你會理 14 | 解每個小技巧如何工作,以及如何組合這些技巧以滿足你的需求。 15 | 16 | .翻譯 17 | 18 | - link:/\~blynn/gitmagic/intl/zh_cn/[簡體中文]: 俊傑,萌和江薇。 19 | link:/~blynn/gitmagic/intl/zh_tw/[正體中文] 由 + cconv -f UTF8-CN -t 20 | UTF8-TW + 轉換。 21 | - link:/~blynn/gitmagic/intl/fr/[法文]: Alexandre Garel。也在 22 | http://tutoriels.itaapy.com/[itaapy]。 23 | - link:/~blynn/gitmagic/intl/de/[德文]: Benjamin Bellee和Armin Stebich;也在 24 | http://gitmagic.lordofbikes.de/[Armin的網站]。 25 | - http://www.slideshare.net/slide_user/magia-git[葡萄牙文]: Leonardo 26 | Siqueira Rodrigues 27 | [http://www.slideshare.net/slide_user/magia-git-verso-odt[ODT版]]。 28 | - link:/~blynn/gitmagic/intl/ru/[俄文]: Tikhon Tarnavsky, Mikhail Dymskov, 29 | 和其他人。 30 | - link:/~blynn/gitmagic/intl/es/[西班牙]: Rodrigo Toledo和Ariset Llerena 31 | Tapia。 32 | - link:/~blynn/gitmagic/intl/vi/[越南文]: Trần Ngọc Quân; 也在 33 | http://vnwildman.users.sourceforge.net/gitmagic.html[他的網站]. 34 | 35 | .其它版本 36 | 37 | - link:book.html[單一檔案]: 純HTML,無CSS。 38 | - link:book.pdf[PDF檔案]: 打印效果好. 39 | - http://packages.debian.org/gitmagic[Debian包], 40 | http:://packages.ubuntu.com/gitmagic[Ubuntu包]: 本站快速本地拷貝。如果 41 | http://csdcf.stanford.edu/status/[下線了]會方便些。 42 | - http://www.amazon.com/Git-Magic-Ben-Lynn/dp/1451523343/[紙質書 43 | [Amazon.com]]: 64 頁, 15.24cm x 22.86cm, 黑白。 沒有電子設備的時候會方便些。 44 | 45 | === 致謝! === 46 | 47 | 那麼多人對本文檔的翻譯讓我受寵若驚。他們的付出拓寬了讀者群,我非常感激。 48 | 49 | Dustin Sallings、Alberto Bertogli、James Cameron、Douglas Livingstone、 50 | Michael Budde、Richard Albury、Tarmigan、 Derek Mahar、Frode Aannevik、 51 | Keith Rarick、 Andy Somerville、 Ralf Recker、 Øyvind A. Holm、 Miklos Vajna、 52 | Sébastien Hinderer、 Thomas Miedema、 Joe Malin、 和Tyler Breisacher對本文檔 53 | 正確性和優化做出了貢獻。 54 | 55 | François Marier維護Debian包,該Debian包起初由Daniel Baumann創建。 56 | 57 | 感謝其他很多提供幫助和鼓勵的人。名單太長了我無法一一寫下。 58 | 59 | 如果我不小心把你的名字落下,請告訴我或者發一個補丁。 60 | 61 | *免費 Git 主機*: 底下網站可以免費放置公開專案。 62 | 非常感謝底下網站贊助放置手冊。 63 | 64 | - http://repo.or.cz/[http://repo.or.cz/] 65 | - http://gitorious.org/[http://gitorious.org/] 66 | - http://github.com/[http://github.com/] 私有項目收錢。 67 | - http://www.assembla.com/[Assembla]: 私有項目收錢, 雖然有 1 gigabyte 空間免費. 68 | 69 | === 許可 === 70 | 71 | 本指南在http://www.gnu.org/licenses/gpl-3.0.html[ GNU通用公共許可協議版本3 ] 72 | 之下發佈。很自然,源碼保存在一個Git倉庫裡,可以通過以下命令獲得源碼: 73 | 74 | $ git clone git://repo.or.cz/gitmagic.git # 建立 "gitmagic" 目錄. 75 | 76 | 或從以下鏡像得到: 77 | 78 | $ git clone git://github.com/blynn/gitmagic.git 79 | $ git clone git://gitorious.org/gitmagic/mainline.git 80 | $ git clone git://git.assembla.com/gitmagic.git 81 | 82 | -------------------------------------------------------------------------------- /zh_tw/secrets.txt: -------------------------------------------------------------------------------- 1 | == 揭開面紗 == 2 | 3 | 我們揭開Git神秘面紗,往裡瞧瞧它是如何創造奇蹟的。我會跳過細節。更深入的描述參 4 | 見 http://www.kernel.org/pub/software/scm/git/docs/user-manual.html[ 用戶手 5 | 冊]。 6 | 7 | === 大象無形 === 8 | 9 | Git怎麼這麼謙遜寡言呢?除了偶爾提交和合併外,你可以如常工作,就像不知道版本控 10 | 制系統存在一樣。那就是,直到你需要它的時候,而且那是你歡欣的時候,Git一直默默 11 | 注視着你。 12 | 13 | 其他版本控制系統強迫你與繁文縟節和官僚主義不斷鬥爭。檔案的權限可能是隻讀的, 14 | 除非你顯式地告訴中心伺服器哪些檔案你打算編輯。即使最基本的命令,隨着用戶數目 15 | 的增多,也會慢的像爬一樣。中心伺服器可能正跟蹤什麼人,什麼時候check out了什麼 16 | 代碼。當網絡連接斷了的時候,你就遭殃了。開發人員不斷地與這些版本控制系統的種 17 | 種限製作鬥爭。一旦網絡或中心伺服器癱瘓,工作就嘎然而止。 18 | 19 | 與之相反,Git簡單地在你工作目錄下的`.git`目錄保存你項目的歷史。這是你自己的歷 20 | 史拷貝,因此你可以保持離線,直到你想和他人溝通為止。你擁有你的檔案命運完全的 21 | 控制權,因為Git可以輕易在任何時候從`.git`重建一個保存狀態。 22 | 23 | === 數據完整性 === 24 | 25 | 很多人把加密和保持信息機密關聯起來,但一個同等重要的目標是保證信息安全。合理 26 | 使用哈希加密功能可以防止無意或有意的數據損壞行為。 27 | 28 | 一個SHA1哈希值可被認為是一個唯一的160位ID數,用它可以唯一標識你一生中遇到的每 29 | 個位元組串。 實際上不止如此:每個位元組串可供任何人用好多輩子。 30 | 31 | 對一個檔案而言,其整體內容的哈希值可以被看作這個檔案的唯一標識ID數。 32 | 33 | 因為一個SHA1哈希值本身也是一個位元組串,我們可以哈希包括其他哈希值的位元組串。這 34 | 個簡單的觀察出奇地有用:查看“哈希鏈”。我們之後會看Git如何利用這一點來高效地 35 | 保證數據完整性。 36 | 37 | 簡言之,Git把你數據保存在`.git/objects`子目錄,那裡看不到正常檔案名,相反你只 38 | 看到ID。通過用ID作為檔案名,加上一些檔案鎖和時間戳技巧,Git把任意一個原始的文 39 | 件系統轉化為一個高效而穩定的資料庫。 40 | 41 | === 智能 === 42 | 43 | Git是如何知道你重命名了一個檔案,即使你從來沒有明確提及這個事實?當然,你或許 44 | 是運行了 *git mv* ,但這個命令和 *git add* 緊接 *git rm* 是完全一樣的。 45 | 46 | Git啟發式地找出相連版本之間的重命名和拷貝。實際上,它能檢測檔案之間代碼塊的移 47 | 動或拷貝!儘管它不能覆蓋所有的情況,但它已經做的很好了,並且這個功能也總在改 48 | 進中。如果它在你那兒不工作的話,可以嘗試打開開銷更高的拷貝檢測選項,並考慮升 49 | 級。 50 | 51 | === 索引 === 52 | 53 | 為每個加入管理的檔案,Git在一個名為“index”的檔案裡記錄統計信息,諸如大小, 54 | 創建時間和最後修改時間。為了確定檔案是否更改,Git比較其當前統計信息與那些在索 55 | 引裡的統計信息。如果一致,那Git就跳過重新讀檔案。 56 | 57 | 因為統計信息的調用比讀檔案內容快的很多,如果你僅僅編輯了少數幾個檔案,Git几乎 58 | 不需要什麼時間就能更新他們的統計信息。 59 | 60 | 我們前面講過索引是一個中轉區。為什麼一堆檔案的統計數據是一個中轉區?因為添加 61 | 命令將檔案放到Git的資料庫並更新它們的統計信息,而無參數的提交命令創建一個提交, 62 | 只基于這些統計信息和已經在資料庫裡的檔案。 63 | 64 | === Git的源起 === 65 | 66 | 這個 http://lkml.org/lkml/2005/4/6/121[ Linux內核郵件列表帖子] 描述了導致Git 67 | 的一系列事件。整個討論線索是一個令人着迷的歷史探究過程,對Git史學家而言。 68 | 69 | === 對象資料庫 === 70 | 71 | 你數據的每個版本都保存在“對象資料庫”裡,其位於子目錄`.git/objects`;其他位 72 | 于`.git/`的較少數據:索引,分支名,標籤,配置選項,日誌,頭提交的當前位置等。 73 | 對象資料庫樸素而優雅,是Git的力量之源。 74 | 75 | `.git/objects`裡的每個檔案是一個對象。有3中對象跟我們有關:“blob”對象, 76 | “tree”對象,和“commit”對象。 77 | 78 | === Blob對象 === 79 | 80 | 首先來一個小把戲。去一個檔案名,任意檔案名。在一個空目錄: 81 | 82 | $ echo sweet > YOUR_FILENAME 83 | $ git init 84 | $ git add . 85 | $ find .git/objects -type f 86 | 87 | 你將看到 +.git/objects/aa/823728ea7d592acc69b36875a482cdf3fd5c8d+ 。 88 | 89 | 我如何在不知道檔案名的情況下知道這個?這是因為以下內容的SHA1哈希值: 90 | 91 | "blob" SP "6" NUL "sweet" LF 92 | 93 | 是 aa823728ea7d592acc69b36875a482cdf3fd5c8d,這裡SP是一個空格,NUL是一個0位元組, 94 | LF是一個換行符。你可以驗證這一點,鍵入: 95 | 96 | $ printf "blob 6\000sweet\n" | sha1sum 97 | 98 | Git基于“內容定址”:檔案並不按它們的檔案名存儲,而是按它們包含內容的哈希值, 99 | 在一個叫“blob對象”的檔案裡。我們可以把檔案內容的哈希值看作一個唯一ID,這樣 100 | 在某種意義上我們通過他們內容放置檔案。開始的“blob 6”只是一個包含對象類型與 101 | 其長度的頭;它簡化了內部存儲。 102 | 103 | 這樣我可以輕易語言你所看到的。檔案名是無關的:只有裡面的內容被用作構建blob對象。 104 | 105 | 你可能想知道對相同的檔案什麼會發生。試圖加一個你檔案的拷貝,什麼檔案名都行。 106 | 在 +.git/objects+ 的內容保持不變,不管你加了多少。Git只存儲一次數據。 107 | 108 | 順便說一句,在 +.git/objects+ 裡的檔案用zlib壓縮,因此你不應該直接查看他們。 109 | 可以通過http://www.zlib.net/zpipe.c[zpipe -d] 管道, 或者鍵入: 110 | 111 | $ git cat-file -p aa823728ea7d592acc69b36875a482cdf3fd5c8d 112 | 113 | 這漂亮地打印出給定的對象。 114 | 115 | === Tree對象 === 116 | 117 | 但檔案名在哪?它們必定在某個階段保存在某個地方。Git在提交時得到檔案名: 118 | 119 | $ git commit # 輸入一些信息。 120 | $ find .git/objects -type f 121 | 122 | 你應看到3個對象。這次我不能告訴你這兩個新檔案是什麼,因為它部分依賴你選擇的文 123 | 件名。我繼續進行,假設你選了``rose''。如果你沒有,你可以重寫歷史以讓它看起來 124 | 像似你做了: 125 | 126 | $ git filter-branch --tree-filter 'mv YOUR_FILENAME rose' 127 | $ find .git/objects -type f 128 | 129 | 現在你硬看到檔案 +.git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9+ ,因為這是以下內容的SHA1哈希值: 130 | 131 | "tree" SP "32" NUL "100644 rose" NUL 0xaa823728ea7d592acc69b36875a482cdf3fd5c8d 132 | 133 | 檢查這個檔案真的包含上面內容通過鍵入: 134 | 135 | $ echo 05b217bb859794d08bb9e4f7f04cbda4b207fbe9 | git cat-file --batch 136 | 137 | 使用zpipe,驗證哈希值是容易的: 138 | 139 | $ zpipe -d < .git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9 | sha1sum 140 | 141 | 與查看檔案相比,哈希值驗證更技巧一些,因為其輸出不止包含原始未壓縮檔案。 142 | 143 | 這個檔案是一個“tree”對象:一組數據包含檔案類型,檔案名和哈希值。在我們的例 144 | 子裡,檔案類型是100644,這意味着“rose”是一個一般檔案,並且哈希值指blob對象, 145 | 包含“rose”的內容。其他可能檔案類型有可執行,連結或者目錄。在最後一個例子裡, 146 | 哈希值指向一個tree對象。 147 | 148 | 在一些過渡性的分支,你會有一些你不在需要的老的對象,儘管有寬限過期之後,它們 149 | 會被自動清除,現在我們還是將其刪除,以使我們比較容易跟上這個玩具例子。 150 | 151 | $ rm -r .git/refs/original 152 | $ git reflog expire --expire=now --all 153 | $ git prune 154 | 155 | 在真實項目裡你通常應該避免像這樣的命令,因為你在破換備份。如果你期望一個乾淨 156 | 的倉庫,通常最好做一個新的克隆。還有,直接操作 +.git+ 時一定要小心:如果 157 | Git命令同時也在運行會怎樣,或者突然停電?一般,引用應由 *git update-ref -d* 158 | 刪除,儘管通常手工刪除 +refs/original+ 也是安全的。 159 | 160 | === Commit對象 === 161 | 162 | 我們已經解釋了三個對象中的兩個。第三個是“commit”對象。其內容依賴于提交信息 163 | 以及其創建的日期和時間。為滿足這裡我們所有的,我們不得不調整一下: 164 | 165 | $ git commit --amend -m Shakespeare # 改提交信息 166 | $ git filter-branch --env-filter 'export 167 | GIT_AUTHOR_DATE="Fri 13 Feb 2009 15:31:30 -0800" 168 | GIT_AUTHOR_NAME="Alice" 169 | GIT_AUTHOR_EMAIL="alice@example.com" 170 | GIT_COMMITTER_DATE="Fri, 13 Feb 2009 15:31:30 -0800" 171 | GIT_COMMITTER_NAME="Bob" 172 | GIT_COMMITTER_EMAIL="bob@example.com"' # Rig timestamps and authors. 173 | $ find .git/objects -type f 174 | 175 | 你現在應看到 +.git/objects/49/993fe130c4b3bf24857a15d7969c396b7bc187+ 是下列 176 | 內容的SHA1哈希值: 177 | 178 | "commit 158" NUL 179 | "tree 05b217bb859794d08bb9e4f7f04cbda4b207fbe9" LF 180 | "author Alice <alice@example.com> 1234567890 -0800" LF 181 | "committer Bob <bob@example.com> 1234567890 -0800" LF 182 | LF 183 | "Shakespeare" LF 184 | 185 | 和前面一樣,你可以運行zpipe或者cat-file來自己看。 186 | 187 | 這是第一個提交,因此沒有父提交,但之後的提交將總有至少一行,指定一個父提交。 188 | 189 | === 沒那麼神 === 190 | 191 | Git的秘密似乎太簡單。看起來似乎你可以整合幾個shell腳本,加幾行C代碼來弄起來, 192 | 也就幾個小時的事:一個基本檔案操作和SHA1哈希化的混雜,用鎖檔案裝飾一下,檔案 193 | 同步保證健壯性。實際上,這準確描述了Git的最早期版本。儘管如此,除了巧妙地打包 194 | 以節省空間,巧妙地索引以省時間,我們現在知道Git如何靈巧地改造檔案系統成為一個 195 | 對版本控制完美的資料庫。 196 | 197 | 例如,如果對象資料庫裡的任何一個檔案由於硬碟錯誤損毀,那麼其哈希值將不再匹配, 198 | 這個錯誤會報告給我們。通過哈希化其他對象的哈希值,我們在所有層面維護數據完整 199 | 性。Commit對象是原子的,也就是說,一個提交永遠不會部分地記錄變更:在我們已經 200 | 存儲所有相關tree對象,blob對象和父commit對象之後,我們才可以計算提交的的哈希 201 | 值並將其存儲在資料庫,對象資料庫不受諸如停電之類的意外中斷影響。 202 | 203 | 我們打敗即使是最狡猾的對手。假設有誰試圖悄悄修改一個項目裡一個遠古版本檔案的 204 | 內容。為使對象據庫看起來健康,他們也必須修改相應blob對象的哈希值,既然它現在 205 | 是一個不同的位元組串。這意味着他們講不得不引用這個檔案的tree對象的哈希值,並反 206 | 過來改變所有與這個tree相關的commit對象的哈希值,還要加上這些提交所有後裔的哈 207 | 希值。這暗示官方head的哈希值與這個壞倉庫不同。通過跟蹤不匹配哈希值線索,我 208 | 們可以查明殘缺檔案,以及第一個被破壞的提交。 209 | 210 | 總之,只要20個位元組代表最後一次提交的是安全的,不可能篡改一個Git倉庫。 211 | 212 | 那麼Git的著名功能怎樣呢?分支?合併?標籤?單純的細節。當前head保存在檔案 213 | +.git /HEAD+ ,其中包含了一個commit對象的哈希值。該哈希值在運行提交以及其他命 214 | 令是更新。分支几乎一樣:它們是保存在 +.git/refs/heads+ 的檔案。標籤也是:它們 215 | 住在住在 +.git/refs/tags+ ,但它們由一套不同的命令更新。 216 | -------------------------------------------------------------------------------- /zh_tw/translate.txt: -------------------------------------------------------------------------------- 1 | == 附錄 B: 本指南的翻譯 == 2 | 3 | 我推薦如下步驟翻譯本指南,這樣我的腳本就可以快速生成HTML和PDF版本,並且所有翻 4 | 譯也可以共存於同一個倉庫。 5 | 6 | 克隆源碼,然後針對不同目標 7 | http://www.iana.org/assignments/language-subtag-registry[語言的IETF tag]創建 8 | 一個目錄。參見 9 | http://www.w3.org/International/articles/language-tags/Overview.en.php[ W3C在 10 | 國際化方面的文章 ]。例如,英語是“en”,日語是“ja”,正體中文是“zh-Hant”。 11 | 然後在新建目錄,翻譯這些來自“en”目錄的 +txt+ 檔案。 12 | 13 | 例如,將本指南譯為 http://en.wikipedia.org/wiki/Klingon_language[ 克林貢語 ], 14 | 你也許鍵入: 15 | 16 | $ git clone git://repo.or.cz/gitmagic.git 17 | $ cd gitmagic 18 | $ mkdir tlh # "tlh" 是克林貢語的IETF語言碼。 19 | $ cd tlh 20 | $ cp ../en/intro.txt . 21 | $ edit intro.txt # 翻譯這個檔案 22 | 23 | 對每個檔案都一樣。 24 | 25 | 打開Makefile檔案,把語言碼加入`TRANSLATIONS`變數,現在你可以時不時查看你的工 26 | 作: 27 | 28 | $ make tlh 29 | $ firefox book-tlh/index.html 30 | 31 | 經常提交你的變更,然後然我知道他們什麼時候完成。GitHub.com提供一個便于fork 32 | “gitmatic”項目的界面,提交你的變更,然後告訴我去合併。 33 | 34 | 但請按照最適合你的方式做:例如,中文譯者就使用 35 | Google Docs。只要你的工作使更多人看到我的工作,我就高興。 36 | 37 | --------------------------------------------------------------------------------