├── .github └── workflows │ └── publish.yaml ├── .gitignore ├── Makefile ├── README-ja.md ├── README.md ├── basic-usage-2.tex ├── basic-usage.tex ├── checkout-after-detached.tex ├── checkout-b-detached.tex ├── checkout-branch.tex ├── checkout-detached.tex ├── checkout-files.tex ├── cherry-pick.tex ├── commit-amend.tex ├── commit-detached.tex ├── commit-main.tex ├── commit-stable.tex ├── common.tex ├── conventions.tex ├── diff.tex ├── goatcounter.js ├── index-de.html ├── index-en.html ├── index-es.html ├── index-fr.html ├── index-it.html ├── index-ja.html ├── index-ko.html ├── index-pl.html ├── index-pt.html ├── index-ru.html ├── index-sk.html ├── index-vi.html ├── index-zh-cn.html ├── index-zh-tw.html ├── index.html ├── merge-ff.tex ├── merge.tex ├── rebase-onto.tex ├── rebase.tex ├── reset-commit.tex ├── reset-files.tex ├── reset.tex ├── translate-en.html ├── visual-git-guide.css └── visual-git-guide.js /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: Publish to GitHub Pages 2 | on: 3 | push: 4 | branches: 5 | - master 6 | workflow_dispatch: 7 | jobs: 8 | deploy: 9 | runs-on: ubuntu-20.04 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | - name: Install Deps 14 | run: sudo apt-get update && sudo apt-get install make texlive-base texlive-fonts-extra pdf2svg imagemagick ghostscript 15 | - name: Fix ImageMagick policy 16 | # https://askubuntu.com/questions/1081895 17 | run: sudo sed -i -e '/domain="coder" rights="none" pattern="PDF"/d' /etc/ImageMagick-?/policy.xml 18 | - name: Build 19 | run: make 20 | - name: Deploy 21 | uses: peaceiris/actions-gh-pages@v3 22 | with: 23 | github_token: ${{ secrets.GITHUB_TOKEN }} 24 | publish_dir: ./build 25 | exclude_assets: '*.aux,*.log' 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PDFLATEX = pdflatex -halt-on-error -file-line-error 2 | PDF2SVG = pdf2svg 3 | PDF2PNG = convert -density 88 4 | 5 | FILES := \ 6 | basic-usage \ 7 | basic-usage-2 \ 8 | checkout-after-detached \ 9 | checkout-b-detached \ 10 | checkout-branch \ 11 | checkout-detached \ 12 | checkout-files \ 13 | cherry-pick \ 14 | commit-amend \ 15 | commit-detached \ 16 | commit-stable \ 17 | commit-main \ 18 | conventions \ 19 | diff \ 20 | merge \ 21 | merge-ff \ 22 | rebase \ 23 | rebase-onto \ 24 | reset \ 25 | reset-commit \ 26 | reset-files 27 | 28 | STATIC := \ 29 | goatcounter.js \ 30 | index.html \ 31 | index-de.html \ 32 | index-en.html \ 33 | index-es.html \ 34 | index-fr.html \ 35 | index-it.html \ 36 | index-ja.html \ 37 | index-ko.html \ 38 | index-pl.html \ 39 | index-pt.html \ 40 | index-ru.html \ 41 | index-sk.html \ 42 | index-vi.html \ 43 | index-zh-cn.html \ 44 | index-zh-tw.html \ 45 | translate-en.html \ 46 | visual-git-guide.css \ 47 | visual-git-guide.js 48 | 49 | STATIC_OUT = $(addprefix build/,$(STATIC)) 50 | PDF_OUT = $(addprefix build/,$(FILES:=.pdf)) 51 | PNG_OUT = $(PDF_OUT:.pdf=.svg.png) 52 | SVG_OUT = $(PDF_OUT:.pdf=.svg) 53 | 54 | all : pdf png svg static 55 | pdf : $(PDF_OUT) 56 | png : $(PNG_OUT) 57 | svg : $(SVG_OUT) 58 | static : $(STATIC_OUT) 59 | 60 | build/% : % | build 61 | cp $^ $@ 62 | 63 | build/%.pdf : %.tex common.tex | build 64 | $(PDFLATEX) -output-directory=build $< 65 | 66 | build/%.svg : build/%.pdf | build 67 | $(PDF2SVG) $^ $@ 68 | 69 | build/%.svg.png : build/%.pdf | build 70 | $(PDF2PNG) $^ $@ 71 | 72 | build : 73 | mkdir -p $@ 74 | 75 | clean : 76 | $(RM) -r build 77 | 78 | .PHONY : clean all pdf png svg static 79 | -------------------------------------------------------------------------------- /README-ja.md: -------------------------------------------------------------------------------- 1 | 図解Git 2 | ======= 3 | 4 | これは Mark Lodato さんによる visual Git reference の日本語訳です。本人 5 | の許可を得て、翻訳しています。 6 | 7 | ブラウザで本文を読みたい場合は、以下のURLにアクセスして下さい。 8 | 9 | 10 | 11 | オリジナルのページは、以下を参照して下さい。 12 | 13 | 14 | 15 | また、オリジナルのソースは、以下を参照して下さい。 16 | 17 | 18 | 19 | お願い 20 | ====== 21 | 22 | * SVG の生成で、フォントがうまく処理されてないようです。どういう設定を 23 | すればうまくいくか知っている方は教えて下さい。 24 | 25 | * SVG の図中の英語も翻訳したいのですが、うまくいきません。TeX のエキス 26 | パートの方がいらっしゃいましたら、どうやればよいか調べていただけると 27 | 嬉しいです。 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A Visual Git Reference 2 | ====================== 3 | 4 | The goal of this website is to be a concise, visual reference for how git 5 | commands work. I often draw pictures like this on a whiteboard for my 6 | colleagues, so I figured I would make a nice electronic version once and for 7 | all. 8 | 9 | Implementation 10 | -------------- 11 | 12 | I chose to draw the images using TeX and 13 | [PGF/Ti*k*Z](http://www.texample.net/tikz/). I originally tried using 14 | [Graphviz](http://www.graphviz.org/), but unfortunately there is no way to 15 | tell it how to lay out the graph exactly. Using Ti*k*Z, I was able to create 16 | a domain-specific language to represent commit graphs, and I think the result 17 | turned out quite well. 18 | 19 | All of the common macros are stored in 20 | [common.tex](http://github.com/MarkLodato/visual-git-guide/blob/main/common.tex). 21 | Each image source includes this file. To see an example of how to use these 22 | macros, look at 23 | [commit-main.tex](http://github.com/MarkLodato/visual-git-guide/blob/main/commit-main.tex). 24 | 25 | To generate the image files, I first create PDFs using 26 | [pdflatex](http://www.tug.org/applications/pdftex/), and from there I create 27 | SVGs and PNGs using 28 | [pdf2svg](http://www.cityinthesky.co.uk/pdf2svg.html) and 29 | [convert](http://www.imagemagick.org/script/convert.php), respectively. 30 | 31 | ### Building from Source 32 | 33 | First, the following must be installed: 34 | 35 | sudo apt-get install make texlive-base texlive-fonts-extra pdf2svg imagemagick ghostscript 36 | 37 | Then, build the images: 38 | 39 | make 40 | 41 | The result is in the `./build` directory. 42 | 43 | ### Pushing to gh-pages 44 | 45 | Done via GitHubActions (`.github/workflows/publish.yaml`). 46 | 47 | License 48 | ------- 49 | 50 | Copyright © 2010, [Mark Lodato](mailto:lodatom@gmail.com). Japanese 51 | translation © 2010, [Kazu Yamamoto](http://github.com/kazu-yamamoto). 52 | Korean translation © 2011, [Sean](mailto:sean@weaveus.com). 53 | Russian translation © 2012, [Alex Sychev](mailto:alex@sychev.com). 54 | French translation © 2012, [Michel Lefranc](mailto:michel.lefranc@gmail.com). 55 | Chinese translation © 2012, [wych](mailto:ellrywych@gmail.com). 56 | Spanish translation © 2012, [Lucas Videla](http://www.delucas.com.ar). 57 | Italian translation © 2012, [Daniel Londero](mailto:daniel.londero@gmail.com). 58 | German translation © 2013, [Martin Funk](mailto:mafulafunk@gmail.com), © 2017, [Mirko Westermeier](mailto:mirko@westermeier.de). 59 | Vietnamese translation © 2013, [Hoat Le](https://github.com/hoatle). 60 | Slovak translation © 2013, [Ľudovít Lučenič](https://github.com/llucenic). 61 | Portuguese translation © 2014, [Gustavo de Oliveira](mailto:goliveira5d@gmail.com). 62 | Traditional Chinese translation © 2015, [Peter Dave Hello](https://github.com/PeterDaveHello). 63 | Polish translation © 2017, [Emil Wypych](mailto:wypychemil@gmail.com). 64 | 65 | This work is licensed under a 66 | [Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States 67 | License](https://creativecommons.org/licenses/by-nc-sa/3.0/us/). 68 | -------------------------------------------------------------------------------- /basic-usage-2.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \geometry{papersize={25\g,9\g}} 3 | \begin{document} 4 | \begin{tikzpicture}[main] 5 | \boundingbox 6 | \historynode[0,2] 7 | \indexnode[0,0] 8 | \worknode[0,-2] 9 | 10 | \path [line] 11 | (work.north east) 12 | edge node[cmd] {} 13 | (index.south east) 14 | (work.north east) 15 | edge node[cmd] {git commit (\emph{files}|-a)} 16 | (head.south east) 17 | (head.south west) 18 | edge node[cmd] {git checkout HEAD -- \emph{files}} 19 | (work.north west) 20 | (head.south west) 21 | edge 22 | (index.north west) 23 | ; 24 | \end{tikzpicture} 25 | \end{document} 26 | -------------------------------------------------------------------------------- /basic-usage.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \geometry{papersize={21\g,9\g}} 3 | \begin{document} 4 | \begin{tikzpicture}[main] 5 | \boundingbox 6 | \historynode[0,2] 7 | \indexnode[0,0] 8 | \worknode[0,-2] 9 | 10 | \path [line] 11 | (work.north east) 12 | edge node[cmd] {git add \emph{files}} 13 | (index.south east) 14 | (index.north east) 15 | edge node[cmd] {git commit} 16 | (head.south east) 17 | (index.south west) 18 | edge node[cmd] {git checkout -- \emph{files}} 19 | (work.north west) 20 | (head.south west) 21 | edge node[cmd] {git reset -- \emph{files}} 22 | (index.north west) 23 | ; 24 | \end{tikzpicture} 25 | \end{document} 26 | -------------------------------------------------------------------------------- /checkout-after-detached.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \commit 2eecb (2) -> B; 7 | \branch main -> E; 8 | \branch stable -> A; 9 | \olddetachedHEAD -> 2; 10 | \HEAD -> main; 11 | 12 | \node [cmd] at (0,3.75) {git checkout main}; 13 | 14 | \path [line] 15 | (E) edge [bend left=20] (index) 16 | (E) edge [bend left=35] (work) 17 | (old HEAD) edge [dashed, bend left=15] (HEAD label) 18 | ; 19 | 20 | \end{tikzpicture} 21 | \end{document} 22 | -------------------------------------------------------------------------------- /checkout-b-detached.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \commit 2eecb (2) -> B; 7 | \branch main -> E; 8 | \branch stable -> A; 9 | \olddetachedHEAD -> 2; 10 | 11 | \begin{pgfonlayer}{HEAD} 12 | \node [branch, double shadow, above right=.4\g of 2, draw=none, fill=none] 13 | {}; 14 | \end{pgfonlayer} 15 | \node [branch, above right=.4\g of 2] (new) {new}; 16 | \path [branch line] (new) edge (2); 17 | \HEAD -> new; 18 | 19 | \node [cmd] at (-3,3.75) {git checkout -b new}; 20 | 21 | \path [line] 22 | (old HEAD) edge [dashed, bend left=15] (HEAD label) 23 | ; 24 | 25 | \end{tikzpicture} 26 | \end{document} 27 | -------------------------------------------------------------------------------- /checkout-branch.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \branch main -> E; 7 | \branch stable -> A; 8 | \oldHEAD -> main; 9 | \HEAD -> stable; 10 | 11 | \node [cmd] at (0, 3.75) {git checkout stable}; 12 | 13 | \path [line] 14 | (A) edge [bend right=22] (index) 15 | (A) edge [bend right=35] (work) 16 | (old HEAD label) edge [dashed, bend right=10] (HEAD label) 17 | ; 18 | 19 | \end{tikzpicture} 20 | \end{document} 21 | -------------------------------------------------------------------------------- /checkout-detached.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \branch main -> E; 7 | \branch stable -> A; 8 | \oldHEAD -> main; 9 | \detachedHEAD -> B; 10 | 11 | \node [cmd] at (0, 3.75) {git checkout main\~{}3}; 12 | 13 | \path [line] 14 | (B) edge [bend right=20] (index) 15 | (B) edge [bend right=40] (work) 16 | (old HEAD label) edge [dashed, bend right=10] (HEAD) 17 | ; 18 | 19 | \end{tikzpicture} 20 | \end{document} 21 | -------------------------------------------------------------------------------- /checkout-files.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \branch main -> E; 7 | \branch stable -> A; 8 | \HEAD -> main; 9 | 10 | \node [cmd] at (0, 3.75) {git checkout HEAD\~{} \emph{files}}; 11 | 12 | \path [line] 13 | (D) edge [bend left=20] (index) 14 | (D) edge [bend left=45] (work) 15 | ; 16 | 17 | \end{tikzpicture} 18 | \end{document} 19 | -------------------------------------------------------------------------------- /cherry-pick.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \newcommit f142b (F) -> E; 7 | \commit 169a6 (1) -> A; 8 | \commit 2c33a (2) -> 1; 9 | \commit 3ba22 (3) -> 2; 10 | \branch topic -> 3; 11 | 12 | \oldbranch main -> E; 13 | \oldHEAD -> old main; 14 | \branch main -> F; 15 | \HEAD -> main; 16 | 17 | \node [cmd] at (0, 3.75) {git cherry-pick 2c33a}; 18 | 19 | \path [line] 20 | (F) edge [bend left=20] (index) 21 | (F) edge [bend left=30] (work) 22 | (old HEAD) edge [dashed, bend left=50] (HEAD) 23 | (2) edge [loosely dashed, bend right=35] (F) 24 | ; 25 | 26 | \end{tikzpicture} 27 | \end{document} 28 | -------------------------------------------------------------------------------- /commit-amend.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | 7 | % trick the code to draw the commit below instead of above 8 | \pgfkeys{/child count/D=-1} 9 | \newcommit 4ca87 (4) -> D; 10 | 11 | % this is a special case, so I won't make high level commands for this 12 | \refbelow [branch] "main" : main -> 4; 13 | \addHEADbelow [attached HEAD] "HEAD" : HEAD -> main; 14 | 15 | \branch stable -> A; 16 | \oldbranch main -> E; 17 | \oldHEAD -> old main; 18 | 19 | \node [cmd] at (0, 3.75) {git commit --amend}; 20 | 21 | \path [line] 22 | (index) edge [bend right=10] (4) 23 | (old HEAD) edge [dashed, bend left=60] (HEAD) 24 | ; 25 | 26 | \end{tikzpicture} 27 | \end{document} 28 | -------------------------------------------------------------------------------- /commit-detached.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \newcommit 2eecb (2) -> B; 7 | \branch main -> E; 8 | \branch stable -> A; 9 | \olddetachedHEAD -> B; 10 | \detachedHEAD -> 2; 11 | 12 | \node [cmd] at (0, 3.75) {git commit}; 13 | 14 | % Put a white border underneath the line since it croses over the graph. 15 | \path [background line] 16 | ($ (index.north) + (1,0) $) edge [-, bend right=20] 17 | ($ (2.south east) + (-.09,.01) $); 18 | \path [line] 19 | ($ (index.north) + (1,0) $) edge [bend right=20] 20 | ($ (2.south east) + (-.09,.01) $) 21 | (old HEAD) edge [dashed, bend left=15] (HEAD) 22 | ; 23 | 24 | \end{tikzpicture} 25 | \end{document} 26 | -------------------------------------------------------------------------------- /commit-main.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \newcommit f0cec (F) -> E; 7 | \oldbranch main -> E; 8 | \branch main -> F; 9 | \branch stable -> A; 10 | \oldHEAD -> old main; 11 | \HEAD -> main; 12 | 13 | \node [cmd] at (0, 3.75) {git commit}; 14 | 15 | \path [line] 16 | (index) edge [bend right=20] (F) 17 | (old HEAD) edge [dashed, bend left=50] (HEAD) 18 | ; 19 | 20 | \end{tikzpicture} 21 | \end{document} 22 | -------------------------------------------------------------------------------- /commit-stable.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \newcommit 1800b (1) -> A; 7 | \branch main -> E; 8 | \oldbranch stable -> A; 9 | \branch stable -> 1; 10 | \oldHEAD -> old stable; 11 | \HEAD -> stable; 12 | 13 | \node [cmd] at (0, 3.75) {git commit}; 14 | 15 | % Put a white border underneath the line since it croses over the graph. 16 | \path [background line] 17 | ($ (index.north) + (-.8,0) $) edge [-, bend right=13] 18 | ($ (1.south east) + (-.09,.01) $); 19 | \path [line] 20 | ($ (index.north) + (-.8,0) $) edge [bend right=13] 21 | ($ (1.south east) + (-.09,.01) $) 22 | (old HEAD label) edge [dashed, bend left=10] (HEAD label) 23 | ; 24 | 25 | \end{tikzpicture} 26 | \end{document} 27 | -------------------------------------------------------------------------------- /common.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{article} 2 | \usepackage[latin1]{inputenc} 3 | \usepackage{cmbright} 4 | \usepackage[pdftex,margin=0pt,noheadfoot]{geometry} 5 | \usepackage{tikz} 6 | \usetikzlibrary{shapes,arrows,shadows,positioning,calc} 7 | 8 | \colorlet{HEAD}{gray!50} 9 | \colorlet{branch}{orange!50} 10 | \colorlet{commit}{green!50} 11 | \colorlet{index}{blue!40} 12 | \colorlet{work}{red!40} 13 | \colorlet{old HEAD}{HEAD!50} 14 | \colorlet{old branch}{branch!50} 15 | 16 | % Global Scaling Factors 17 | % Values that seem reasonable: 18 | % 1cm / 1pt / \Large 19 | % .5cm / .5pt / \scriptsize 20 | \newlength\g 21 | \setlength\g{1cm} 22 | \newlength\gLine 23 | \setlength\gLine{1pt} 24 | \newcommand\gFont{\Large} 25 | 26 | \geometry{papersize={24\g,14\g}} 27 | 28 | \tikzset{ 29 | index/.style={rectangle, text width=5\g, text centered, rounded corners, 30 | minimum height=1.5\g, line width=3\gLine, fill=#1!50, draw=#1}, 31 | index/.default={index}, 32 | history/.style={index=commit, fill=commit!40}, 33 | work/.style={index=work}, 34 | % 35 | object/.style={rectangle, text width=2\g, text centered, rounded corners, 36 | minimum height=1\g, line width=3\gLine, fill=#1!50, draw=#1}, 37 | object/.default={red}, 38 | commit/.style={object=commit, fill=commit!40}, 39 | new commit/.style={commit, double shadow}, 40 | branch/.style={object=branch}, 41 | HEAD/.style={object=HEAD}, 42 | old branch/.style={object=old branch, text=black!30}, 43 | old HEAD/.style={object=old HEAD, text=black!30}, 44 | attached HEAD/.style={HEAD, minimum height=2\g}, 45 | attached HEAD label/.style={object, draw=none, fill=none}, 46 | old attached HEAD/.style={old HEAD, minimum height=2\g}, 47 | old attached HEAD label/.style={attached HEAD label, text=black!30}, 48 | % 49 | double shadow/.style={ 50 | preaction={fill=#1,transform canvas={xshift=.2\g,yshift=-.2\g}}, 51 | preaction={fill=#1,transform canvas={xshift=-.2\g,yshift=.2\g}}, 52 | }, 53 | double shadow/.default={yellow!75}, 54 | % 55 | line/.style={>=stealth', line width=1.5\gLine, draw=black!70, auto=right, 56 | bend right}, 57 | object line/.style={>=stealth, line width=1.5\gLine}, 58 | commit line/.style={object line, color=commit}, 59 | new commit line/.style={commit line}, 60 | HEAD line/.style={object line, color=HEAD}, 61 | branch line/.style={object line, color=branch}, 62 | old HEAD line/.style={object line, color=old HEAD}, 63 | old branch line/.style={object line, color=old branch}, 64 | cancel ref/.style={cross out, draw=black!70, line width=1\gLine}, 65 | % 66 | background line/.style={draw=white, line width=6\gLine, 67 | shorten >=6\gLine, shorten <=6\gLine}, 68 | % 69 | cmd/.style={color=black, font={\gFont\ttfamily}}, 70 | % 71 | main/.style={node distance=.7\g, bend angle=35, font={\gFont}, 72 | x=1.5\g, y=1.5\g}, 73 | every edge/.style={draw, ->}, 74 | } 75 | 76 | \pgfdeclarelayer{HEAD} 77 | \pgfsetlayers{HEAD,main} 78 | 79 | \newcommand\boundingbox{\clip (-.5\textwidth,-.5\textheight) rectangle 80 | (.5\textwidth,.5\textheight);} 81 | 82 | \newcommand\historynode[1][0,.5]{\node [history] (head) at (#1) {History};} 83 | \newcommand\indexnode[1][0,-1]{\node [index] (index) at (#1) {Stage (Index)};} 84 | \newcommand\worknode[1][0,-2.5]{\node [work] (work) at (#1) {Working Directory};} 85 | \newcommand\normalcommits[1][-6,.75]{ 86 | \commitTerminal cT at (#1); 87 | \commit a47c3 (A) -> cT; 88 | \commit b325c (B) -> A; 89 | \commit c10b9 (C) -> B; 90 | \commit da985 (D) -> C; 91 | \commit ed489 (E) -> D; 92 | } 93 | \newcommand\usualsetup{ 94 | \normalcommits 95 | \indexnode 96 | \worknode 97 | } 98 | 99 | \def\ref [#1] "#2" : #3 -> #4;{ 100 | \node [#1, above=.4\g of #4] (#3) {#2}; 101 | \path [#1 line] (#3) edge (#4); 102 | } 103 | \def\oldref [#1] "#2" : #3 -> #4;{ 104 | \ref [old #1] "#2" : old #3 -> #4; 105 | \node [cancel ref, above=.2\g of #4, anchor=center] {}; 106 | } 107 | \def\refbelow [#1] "#2" : #3 -> #4;{ 108 | \node [#1, below=.4\g of #4] (#3) {#2}; 109 | \path [#1 line] (#3) edge (#4); 110 | } 111 | 112 | \newcounter{tmp} 113 | \def\commitTerminal #1 at (#2);{ 114 | \node (#1) at (#2) {\LARGE$\cdots$}; 115 | \pgfkeys{/child count/#1/.initial=0} 116 | } 117 | \def\commitcommon [#1] #2 (#3) -> [#4] #5;{ 118 | \setcounter{tmp}{\pgfkeysvalueof{/child count/#5}} 119 | \node [#1, anchor=west] (#3) at ($ (#5.east) + (.5,\value{tmp}) $) {#2}; 120 | \draw [#4] (#3) edge (#5); 121 | \addtocounter{tmp}{1} 122 | \pgfkeys{/child count/#3/.initial=0} 123 | \pgfkeys{/child count/#5=\value{tmp}} 124 | } 125 | \def\commit #1 (#2) -> #3;{\commitcommon [commit] #1 (#2) -> [commit line] #3;} 126 | \def\newcommit #1 (#2) -> #3;{\commitcommon [new commit] #1 (#2) -> 127 | [new commit line] #3;} 128 | 129 | \def\branch #1 -> #2;{\ref [branch] "#1" : #1 -> #2;} 130 | \def\oldbranch #1 -> #2;{\oldref [branch] "#1" : #1 -> #2;} 131 | 132 | \def\addHEAD [#1] "#2" : #3 -> #4;{ 133 | \begin{pgfonlayer}{HEAD} 134 | \node [#1, anchor=south] (#3) at (#4.south) {}; 135 | \node [#1 label, anchor=south] (#3 label) at ($(#4.north)+(0,-3\gLine) 136 | $) {#2}; 137 | \end{pgfonlayer} 138 | } 139 | \def\addHEADbelow [#1] "#2" : #3 -> #4;{ 140 | \begin{pgfonlayer}{HEAD} 141 | \node [#1, anchor=north] (#3) at (#4.north) {}; 142 | \node [#1 label, anchor=north] (#3 label) at ($(#4.south)+(0,3\gLine) 143 | $) {#2}; 144 | \end{pgfonlayer} 145 | } 146 | 147 | 148 | \def\HEAD -> #1;{\addHEAD [attached HEAD] "HEAD" : HEAD -> #1;} 149 | \def\oldHEAD -> #1;{\addHEAD [old attached HEAD] "HEAD" : old HEAD -> #1;} 150 | 151 | \def\detachedHEAD -> #1;{\ref [HEAD] "HEAD" : HEAD -> #1;} 152 | \def\olddetachedHEAD -> #1;{\oldref [HEAD] "HEAD" : HEAD -> #1;} 153 | 154 | \pagestyle{empty} 155 | \setlength{\parindent}{0pt} 156 | -------------------------------------------------------------------------------- /conventions.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \branch stable -> A; 7 | \branch main -> E; 8 | \HEAD -> main; 9 | 10 | \path [>=stealth', draw=black!50, very thick] 11 | (5,3.75) node {reference to current branch} edge [->] (HEAD label) 12 | (6.5,2) node {current branch} edge [->] (main) 13 | (-5,3) node {another branch} edge [->] (stable) 14 | (-5,-0.5) node {files to go in next commit} edge [->] (index) 15 | (-5,-2) node {files that you ``see''} edge [->] (work) 16 | (5,-1) node [text width=6\g, text badly centered] 17 | {commit objects, identified by SHA-1 hash} 18 | edge [->] (E) 19 | edge [->] (D) 20 | edge [->] (C) 21 | 22 | (-1,2.25) node {child points to parent} edge [->] ($ (B)!.5!(C) $) 23 | ; 24 | 25 | \end{tikzpicture} 26 | \end{document} 27 | -------------------------------------------------------------------------------- /diff.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \normalcommits 6 | \indexnode[0,-1.5] 7 | \worknode[0,-3.5] 8 | \branch main -> E; 9 | \branch stable -> A; 10 | \HEAD -> main; 11 | 12 | \path [line, bend right=20] 13 | (index) edge node[cmd, auto=left] {git diff} (work) 14 | (E) edge[bend left=20] node[cmd] {git diff --cached} (index) 15 | (E) edge[bend left=30, auto=left] node[cmd] {git diff HEAD} (work) 16 | (A) edge node[cmd] {git diff stable} (work) 17 | (B) edge[bend left=25,auto=left] node[cmd] {git diff b325c da985} (D) 18 | ; 19 | 20 | \end{tikzpicture} 21 | \end{document} 22 | -------------------------------------------------------------------------------- /goatcounter.js: -------------------------------------------------------------------------------- 1 | // GoatCounter: https://www.goatcounter.com 2 | // This file (and *only* this file) is released under the ISC license: 3 | // https://opensource.org/licenses/ISC 4 | ;(function() { 5 | 'use strict'; 6 | 7 | if (window.goatcounter && window.goatcounter.vars) // Compatibility with very old version; do not use. 8 | window.goatcounter = window.goatcounter.vars 9 | else 10 | window.goatcounter = window.goatcounter || {} 11 | 12 | // Load settings from data-goatcounter-settings. 13 | var s = document.querySelector('script[data-goatcounter]') 14 | if (s && s.dataset.goatcounterSettings) { 15 | try { var set = JSON.parse(s.dataset.goatcounterSettings) } 16 | catch (err) { console.error('invalid JSON in data-goatcounter-settings: ' + err) } 17 | for (var k in set) 18 | if (['no_onload', 'no_events', 'allow_local', 'allow_frame', 'path', 'title', 'referrer', 'event'].indexOf(k) > -1) 19 | window.goatcounter[k] = set[k] 20 | } 21 | 22 | var enc = encodeURIComponent 23 | 24 | // Get all data we're going to send off to the counter endpoint. 25 | var get_data = function(vars) { 26 | var data = { 27 | p: (vars.path === undefined ? goatcounter.path : vars.path), 28 | r: (vars.referrer === undefined ? goatcounter.referrer : vars.referrer), 29 | t: (vars.title === undefined ? goatcounter.title : vars.title), 30 | e: !!(vars.event || goatcounter.event), 31 | s: [window.screen.width, window.screen.height, (window.devicePixelRatio || 1)], 32 | b: is_bot(), 33 | q: location.search, 34 | } 35 | 36 | var rcb, pcb, tcb // Save callbacks to apply later. 37 | if (typeof(data.r) === 'function') rcb = data.r 38 | if (typeof(data.t) === 'function') tcb = data.t 39 | if (typeof(data.p) === 'function') pcb = data.p 40 | 41 | if (is_empty(data.r)) data.r = document.referrer 42 | if (is_empty(data.t)) data.t = document.title 43 | if (is_empty(data.p)) data.p = get_path() 44 | 45 | if (rcb) data.r = rcb(data.r) 46 | if (tcb) data.t = tcb(data.t) 47 | if (pcb) data.p = pcb(data.p) 48 | return data 49 | } 50 | 51 | // Check if a value is "empty" for the purpose of get_data(). 52 | var is_empty = function(v) { return v === null || v === undefined || typeof(v) === 'function' } 53 | 54 | // See if this looks like a bot; there is some additional filtering on the 55 | // backend, but these properties can't be fetched from there. 56 | var is_bot = function() { 57 | // Headless browsers are probably a bot. 58 | var w = window, d = document 59 | if (w.callPhantom || w._phantom || w.phantom) 60 | return 150 61 | if (w.__nightmare) 62 | return 151 63 | if (d.__selenium_unwrapped || d.__webdriver_evaluate || d.__driver_evaluate) 64 | return 152 65 | if (navigator.webdriver) 66 | return 153 67 | return 0 68 | } 69 | 70 | // Object to urlencoded string, starting with a ?. 71 | var urlencode = function(obj) { 72 | var p = [] 73 | for (var k in obj) 74 | if (obj[k] !== '' && obj[k] !== null && obj[k] !== undefined && obj[k] !== false) 75 | p.push(enc(k) + '=' + enc(obj[k])) 76 | return '?' + p.join('&') 77 | } 78 | 79 | // Show a warning in the console. 80 | var warn = function(msg) { 81 | if (console && 'warn' in console) 82 | console.warn('goatcounter: ' + msg) 83 | } 84 | 85 | // Get the endpoint to send requests to. 86 | var get_endpoint = function() { 87 | var s = document.querySelector('script[data-goatcounter]') 88 | if (s && s.dataset.goatcounter) 89 | return s.dataset.goatcounter 90 | return (goatcounter.endpoint || window.counter) // counter is for compat; don't use. 91 | } 92 | 93 | // Get current path. 94 | var get_path = function() { 95 | var loc = location, 96 | c = document.querySelector('link[rel="canonical"][href]') 97 | if (c) { // May be relative or point to different domain. 98 | var a = document.createElement('a') 99 | a.href = c.href 100 | if (a.hostname.replace(/^www\./, '') === location.hostname.replace(/^www\./, '')) 101 | loc = a 102 | } 103 | return (loc.pathname + loc.search) || '/' 104 | } 105 | 106 | // Run function after DOM is loaded. 107 | var on_load = function(f) { 108 | if (document.body === null) 109 | document.addEventListener('DOMContentLoaded', function() { f() }, false) 110 | else 111 | f() 112 | } 113 | 114 | // Filter some requests that we (probably) don't want to count. 115 | goatcounter.filter = function() { 116 | if ('visibilityState' in document && document.visibilityState === 'prerender') 117 | return 'visibilityState' 118 | if (!goatcounter.allow_frame && location !== parent.location) 119 | return 'frame' 120 | if (!goatcounter.allow_local && location.hostname.match(/(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/)) 121 | return 'localhost' 122 | if (!goatcounter.allow_local && location.protocol === 'file:') 123 | return 'localfile' 124 | if (localStorage && localStorage.getItem('skipgc') === 't') 125 | return 'disabled with #toggle-goatcounter' 126 | return false 127 | } 128 | 129 | // Get URL to send to GoatCounter. 130 | window.goatcounter.url = function(vars) { 131 | var data = get_data(vars || {}) 132 | if (data.p === null) // null from user callback. 133 | return 134 | data.rnd = Math.random().toString(36).substr(2, 5) // Browsers don't always listen to Cache-Control. 135 | 136 | var endpoint = get_endpoint() 137 | if (!endpoint) 138 | return warn('no endpoint found') 139 | 140 | return endpoint + urlencode(data) 141 | } 142 | 143 | // Count a hit. 144 | window.goatcounter.count = function(vars) { 145 | var f = goatcounter.filter() 146 | if (f) 147 | return warn('not counting because of: ' + f) 148 | 149 | var url = goatcounter.url(vars) 150 | if (!url) 151 | return warn('not counting because path callback returned null') 152 | 153 | var img = document.createElement('img') 154 | img.src = url 155 | img.style.position = 'absolute' // Affect layout less. 156 | img.style.bottom = '0px' 157 | img.style.width = '1px' 158 | img.style.height = '1px' 159 | img.loading = 'eager' 160 | img.setAttribute('alt', '') 161 | img.setAttribute('aria-hidden', 'true') 162 | 163 | var rm = function() { if (img && img.parentNode) img.parentNode.removeChild(img) } 164 | img.addEventListener('load', rm, false) 165 | document.body.appendChild(img) 166 | } 167 | 168 | // Get a query parameter. 169 | window.goatcounter.get_query = function(name) { 170 | var s = location.search.substr(1).split('&') 171 | for (var i = 0; i < s.length; i++) 172 | if (s[i].toLowerCase().indexOf(name.toLowerCase() + '=') === 0) 173 | return s[i].substr(name.length + 1) 174 | } 175 | 176 | // Track click events. 177 | window.goatcounter.bind_events = function() { 178 | if (!document.querySelectorAll) // Just in case someone uses an ancient browser. 179 | return 180 | 181 | var send = function(elem) { 182 | return function() { 183 | goatcounter.count({ 184 | event: true, 185 | path: (elem.dataset.goatcounterClick || elem.name || elem.id || ''), 186 | title: (elem.dataset.goatcounterTitle || elem.title || (elem.innerHTML || '').substr(0, 200) || ''), 187 | referrer: (elem.dataset.goatcounterReferrer || elem.dataset.goatcounterReferral || ''), 188 | }) 189 | } 190 | } 191 | 192 | Array.prototype.slice.call(document.querySelectorAll("*[data-goatcounter-click]")).forEach(function(elem) { 193 | if (elem.dataset.goatcounterBound) 194 | return 195 | var f = send(elem) 196 | elem.addEventListener('click', f, false) 197 | elem.addEventListener('auxclick', f, false) // Middle click. 198 | elem.dataset.goatcounterBound = 'true' 199 | }) 200 | } 201 | 202 | // Add a "visitor counter" frame or image. 203 | window.goatcounter.visit_count = function(opt) { 204 | on_load(function() { 205 | opt = opt || {} 206 | opt.type = opt.type || 'html' 207 | opt.append = opt.append || 'body' 208 | opt.path = opt.path || get_path() 209 | opt.attr = opt.attr || {width: '200', height: (opt.no_branding ? '60' : '80')} 210 | 211 | opt.attr['src'] = get_endpoint() + 'er/' + enc(opt.path) + '.' + enc(opt.type) + '?' 212 | if (opt.no_branding) opt.attr['src'] += '&no_branding=1' 213 | if (opt.style) opt.attr['src'] += '&style=' + enc(opt.style) 214 | if (opt.start) opt.attr['src'] += '&start=' + enc(opt.start) 215 | if (opt.end) opt.attr['src'] += '&end=' + enc(opt.end) 216 | 217 | var tag = {png: 'img', svg: 'img', html: 'iframe'}[opt.type] 218 | if (!tag) 219 | return warn('visit_count: unknown type: ' + opt.type) 220 | 221 | if (opt.type === 'html') { 222 | opt.attr['frameborder'] = '0' 223 | opt.attr['scrolling'] = 'no' 224 | } 225 | 226 | var d = document.createElement(tag) 227 | for (var k in opt.attr) 228 | d.setAttribute(k, opt.attr[k]) 229 | 230 | var p = document.querySelector(opt.append) 231 | if (!p) 232 | return warn('visit_count: append not found: ' + opt.append) 233 | p.appendChild(d) 234 | }) 235 | } 236 | 237 | // Make it easy to skip your own views. 238 | if (location.hash === '#toggle-goatcounter') { 239 | if (localStorage.getItem('skipgc') === 't') { 240 | localStorage.removeItem('skipgc', 't') 241 | alert('GoatCounter tracking is now ENABLED in this browser.') 242 | } 243 | else { 244 | localStorage.setItem('skipgc', 't') 245 | alert('GoatCounter tracking is now DISABLED in this browser until ' + location + ' is loaded again.') 246 | } 247 | } 248 | 249 | if (!goatcounter.no_onload) 250 | on_load(function() { 251 | // 1. Page is visible, count request. 252 | // 2. Page is not yet visible; wait until it switches to 'visible' and count. 253 | // See #487 254 | if (!('visibilityState' in document) || document.visibilityState === 'visible') 255 | goatcounter.count() 256 | else { 257 | var f = function(e) { 258 | if (document.visibilityState !== 'visible') 259 | return 260 | document.removeEventListener('visibilitychange', f) 261 | goatcounter.count() 262 | } 263 | document.addEventListener('visibilitychange', f) 264 | } 265 | 266 | if (!goatcounter.no_events) 267 | goatcounter.bind_events() 268 | }) 269 | })(); 270 | -------------------------------------------------------------------------------- /index-es.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Una referencia visual de Git 6 | 7 | 8 | 10 | 11 | 12 |

Una referencia visual de Git

13 | 14 |
15 | Otros Idiomas: 16 | 32 |
33 | 34 | 36 | 37 | 39 | 40 |

Esta página da una referencia breve y visual para los comandos más comunes 41 | en git. Una vez que conozcas un poco sobre la forma de trabajo de git, este sitio puede fortalecer 42 | tu entendimiento. Si estás interesado en cómo se creó este sitio, mirá mi 43 | repositorio de GitHub.

44 | 45 |

Contenidos

46 |
    47 |
  1. Uso Básico
  2. 48 |
  3. Convenciones
  4. 49 |
  5. Comandos en Detalle 50 |
      51 |
    1. Diff
    2. 52 |
    3. Commit
    4. 53 |
    5. Checkout
    6. 54 |
    7. Commiteando con un HEAD Detachado
    8. 55 |
    9. Reset
    10. 56 |
    11. Merge
    12. 57 |
    13. Cherry Pick
    14. 58 |
    15. Rebase
    16. 59 |
    60 |
  6. 61 |
  7. Notas Técnicas
  8. 62 |
63 | 64 |

Uso Básico

65 | 66 |
67 | 68 |

Los cuatro comandos de arriba copian archivos entre el directorio de trabajo, el 69 | stage (también llamado index), y la historia (en la forma de commits).

70 | 71 |
    72 | 73 |
  • git add archivos copia archivos (en su 74 | estado actual) al stage.
  • 75 | 76 |
  • git commit guarda una snapshot del stage como un commit.
  • 77 | 78 |
  • git reset -- archivos quita archivos de stage; esto es, 79 | que copia archivos del último commit al stage. Usá este 80 | comando para "deshacer" un git add archivos. También podés usar 81 | git reset para quitar de stage todo lo que hayas agregado.
  • 82 | 83 |
  • git checkout -- archivos copia archivos desde 84 | el stage al directorio de trabajo. Usá esto para descartar los cambios locales.
  • 85 | 86 |
87 | 88 |

Podés usar git reset -p, git checkout -p, o 89 | git add -p en lugar de (o en combinación con) especificar archivos 90 | particulares para elegir interactivamente qué partes copiar.

91 | 92 |

También es posible, además, saltarse el stage y hacer check-out de los archivos directamente 93 | desde los archivos de commit sin hacer primero el staging.

94 | 95 |
96 | 97 |
    98 | 99 |
  • git commit -a es equivalente a utilizar el comando git add 100 | en todos los archivos que hubo en el último commit, y correr luego el comando 101 | git commit.
  • 102 | 103 |
  • git commit archivos crea un nuevo commit incluyendo 104 | los contenidos del último commit, además de un snapshot de archivos tomado 105 | del directorio de trabajo. Adicionalmente, los archivos se copian 106 | al stage.
  • 107 | 108 |
  • git checkout HEAD -- archivos copia archivos 109 | del último commit a stage y al directorio de trabajo (a ambos)
  • 110 | 111 |
112 | 113 |

Convenciones

114 | 115 |

En el resto del documento, usaremos gráficos de la siguiente forma.

116 | 117 |
118 | 119 |

Los commits se muestran en verde como identificadores de 5 caracteres, y apuntan a sus 120 | padres. Los branch se muestran en naranja, y apuntan a un commit en particular. 121 | El branch actual se identifica por medio de una referencia especial 122 | HEAD, que es "adjuntada" al branch. En esta imagen, se muestran 123 | los cinco últimos commits, con ed489 siendo el más reciente. 124 | main (el branch actual) apunta a este commit, mientras que 125 | stable (otro branch) apunta a un antecesor del commit de main.

126 | 127 |

Comandos en Detalle

128 | 129 |

Diff

130 | 131 |

Hay varias formas de ver las diferencias entre commits. Debajo están 132 | algunos ejemplos comunes. Cualquiera de esos comandos pueden tomar opcionalmente 133 | como argumento nombres de archivos que limiten las diferencias a los archivos nombrados.

134 | 135 |
136 | 137 |

Commit

138 | 139 |

Cuando commiteás, git crea un nuevo objeto de commit utilizando los archivos del 140 | stage y establece el padre al commit actual. Entonces apunta el presente branch a 141 | este nuevo commit. En la imagen debajo, el branch actual es main. 142 | Antes de que se ejecutase el comando, main apuntaba a 143 | ed489. Luego, un nuevo commit, f0cec, se crea, con el 144 | padre ed489, y luego main se mueve al nuevo commit.

145 | 146 |
147 | 148 |

Este mismo proceso sucede aún cuando el branch actual es un ancestro de 149 | otro. Debajo, un commit ocurre en el branch stable, el cual fue un 150 | ancestro de main, resultando en 1800b. Luego, 151 | stable no es más un ancestro de main. Para reunir las dos 152 | historias, será necesario un merge (o rebase).

153 | 154 |
155 | 156 |

A veces pueden cometerse errores en un commit, pero son fáciles de corregir con 157 | git commit --amend. Cuando usás este comando, git crea un nuevo commit 158 | con el mismo padre que el commit actual. (El commit anterior será descartado 159 | si nada más lo referencia.)

160 | 161 |
162 | 163 |

Un cuarto caso es commitear con un HEAD detachado, 164 | como explicaremos después.

165 | 166 |

Checkout

167 | 168 |

El comando checkout se usa para copiar archivos de los commits (o desde stage) 169 | al directorio de trabajo, y para opcionalmente intercambiar branches.

170 | 171 |

Cuando un nombre de archivo (y/o -p) se proporciona, git copia esos archivos 172 | desde el commit dado hacia stage y el directorio de trabajo. Por ejemplo, 173 | git checkout HEAD~ foo.c copia el archivo foo.c 174 | desde el commit llamado HEAD~ (el padre del commit actual) al 175 | directorio de trabajo, y además lo pasa a stage. (Si no se proporciona nombre de commit, 176 | los archivos se copiarán desde stage.) Notá que el branch actual no se cambia.

177 | 178 |
179 | 180 |

Cuando not se proporciona un nombre de archivo, pero la referencia es 181 | un branch (local), HEAD se mueve a ese branch (esto es, nosotros "cambiamos" ese 182 | branch), y entonces el stage y el directorio de trabajo se establecen para coincidir con 183 | los contenidos de ese commit. Cualquier archivo que existe en el nuevo commit 184 | (a47c3 debajo) se copia; cualquier archivo que exista en el anterior commit 185 | (ed489) pero no en el que está borrado; y cualquier archivo que exista 186 | será ignorado.

187 | 188 |
189 | 190 |

Cuando not se proporciona un nombre de archivo y la referencia no es 191 | un branch (local) — digamos, es un tag, un branch remoto, un identificador SHA-1, o 192 | algo como main~3 — obtenemos un branch anónimo, llamado 193 | un HEAD detachado. Esto es útil para saltar a través de la historia. 194 | Digamos que querés compilar la versión 1.6.6.1 de git. Podés hacer git checkout 195 | v1.6.6.1 (que es un tag, no un branch), compilar, instalar, y luego 196 | cambiar de nuevo a otro branch, digamos git checkout main. 197 | Sin embargo, commitear trabajos levemente diferentes con un HEAD detachado; esto es 198 | cubierto debajo.

199 | 200 |
201 | 202 |

Commiteando con un HEAD detachado

203 | 204 |

Cuando el HEAD está detachado, commit trabaja como siempre, excepto 205 | que en un branch sin nombre. (Podés pensar en esto como un branch anónimo.)

206 | 207 |
208 | 209 |

Una vez que hacés un check-out de algo más, digamos main, el commit 210 | (supuestamente) no es referenciado más por nada, y se pierde. Notá que 211 | luego de ese comando, no hay nada referenciando 2eecb.

212 | 213 |
214 | 215 |

Si, por otro lado, querés guardar este estado, podés crear un nuevo 216 | branch con nombre usando git checkout -b nombre.

217 | 218 |
219 | 220 |

Reset

221 | 222 |

El comando reset mueve el branch actual a otra posición, y opcionalmente 223 | actualiza el stage y el directorio de trabajo. Además se usa para 224 | copiar archivos desde los commits a stage sin tocar el directorio de trabajo.

225 | 226 |

Si un commit se hace sin especificar nombres de archivos, el branch actual 227 | se mueve a ese commit, y luego el stage se actualiza para coincidir con ese commmit. 228 | Si se proporciona el parámetro --hard el directorio de trabajo también se 229 | actualiza. Si se proporciona el parámetro --soft ninguno se actualiza.

230 | 231 |
232 | 233 |

Si no se proporciona un commit, por defecto se refiere a HEAD. En este caso, 234 | el branch no se mueve, pero se pasa a stage (y opcionalmente al directorio de trabajo si 235 | se especifica el parámetro --hard) y reinicia a los contenidos del último commit.

236 | 237 |
238 | 239 |

Si se proporciona un nombre de archivo (y/o -p), entonces el comando trabaja 240 | en forma similar al checkout con un nombre de archivo, excepto que solo 241 | el stage (y no el directorio de trabajo) se actualice. (Además deberías especificar 242 | el commit del cual tomar los archivos, en lugar de HEAD.)

243 | 244 |
245 | 246 |

Merge

247 | 248 |

Un merge crea un nuevo commit que incorpora cambios de otros commit. 249 | Antes de mezclar, el stage debe coincidir con el commit actual. El caso 250 | trivial es si el otro commit es un ancestro del commit actual, en cuyo 251 | caso no se hace nada adicional. El siguiente más simple es si el commit actual 252 | es un ancestro del otro commit. Esto resulta en una mezcla fast-forward. 253 | La referencia simplemente se mueve, y luego al nuevo commit se le hace check out.

254 | 255 |
256 | 257 |

De otro modo, una mezcla "real" debe ocurrir. Podés elegir otras estrategias, 258 | pero por defecto se realiza una mezcla "recursive", la cual básicamente toma el commit 259 | actual (ed489 debajo), el otro commit (33104), 260 | y su ancestro común (b325c), y realiza una mezcla de tres vías. 262 | El resultado se guarda al directorio de trabajo y al stage, y luego ocurre 263 | un commit, con un padre adicional (33104) para el nuevo commit. 264 |

265 | 266 |
267 | 268 |

Cherry Pick

269 | 270 |

El comando cherry-pick "copia" un commit, creando un nuevo commit en el 271 | branch actual con el mismo mensaje y patch que otro commit.

272 | 273 |
274 | 275 |

Rebase

276 | 277 |

Un rebase es una alternativa al merge para combinar 278 | múltiples branches. Mientras que un merge crea un solo commit con dos 279 | padres, dejando una historia no lineal, un rebase reproduce los commits del 280 | branch actual en otro, dejando una historia lineal. En esencia, esta es 281 | una forma automatizada de realizar muchas cherry-pick de una vez.

283 | 284 |
285 | 286 |

El comando de arriba toma todos los commits que existen en topic pero 287 | no en main (nombrados 169a6 y 2c33a), los reproduce 288 | dentro de main, y luego mueve el branch head al nuevo punto. 289 | Notá que los commits viejos serán recogidos por el recolector de basura si no son 290 | referenciados.

291 | 292 |

Para limitar qué tanto va hacia atrás, usá la opción --onto. El 293 | siguiente comando reproduce dentro de main el más reciente commit del 294 | branch actual desde 169a6 (exclusivo), concretamente 2c33a.

295 | 296 |
297 | 298 |

Además existe git rebase --interactive, que permite hacer 299 | cosas más complicadas que simplemente reproducir commits, descartar, reordenar, 300 | modificar o juntar commits. No hay una imagen obvia para graficar este concepto; ver git-rebase(1) 302 | para más detalles.

303 | 304 |

Notas Técnicas

305 | 306 |

Los contenidos de los archivos no se almacenan en realidad en el índice 307 | (.git/index) o en objetos commit. En su lugar, cada archivo se almacena en 308 | el objeto database (.git/objects) como un blob, identificado 309 | por su hash SHA-1. El archivo de índice lista los nombres de los archivos junto con el 310 | identificador del blob asociado, así como otros datos. Para los commits, 311 | hay un tipo de dato adicional, un tree, también identificado por su hash. 312 | Los trees se corresponden con directorios del directorio de trabajo, y contienen 313 | una lista de trees y blobs que se corresponden a cada nombre de archivo dentro de ese 314 | directorio. Cada commit almacena el identificador de su tree de alto nivel, el cual 315 | a su vez contiene todos los blobs y otros trees asociados con ese commit.

316 | 317 |

Si hacés un commit usando un HEAD detachado, el último commit es el que se 318 | referencia por algo: el reflog para HEAD. Sin embargo, esto expirará 319 | luego de un tiempo, por eso el commit eventualmente será recogido por el garbage 320 | collector, de forma similar a los commits descartados con git commit --amend 321 | o git rebase.

322 | 323 |
324 | 325 |

Copyright © 2010, 326 | Mark Lodato. 327 | Spanish translation © 2012, 328 | Lucas Videla. 329 |

330 | 331 |

334 | Este trabajo está licenciado bajo una Creative 336 | Commons Attribution-Noncommercial-Share Alike 3.0 United States 337 | License.

338 | 339 |

¿Querés traducirlo a otro idioma?

340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /index-fr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Une Référence Visuelle de Git 6 | 7 | 8 | 10 | 11 | 12 |

Une Référence Visuelle de Git

13 | 14 |
15 | Autres langues : 16 | 32 |
33 | 34 | 36 | 37 | 39 | 40 |

Cette page donne une brève référence visuelle des principales commandes 41 | git. Une fois que vous connaissez un peu comment fonctionne git, cette page 42 | vous permettra d'asseoir votre compréhension. 43 | Si vous voulez savoir comment ce site a été créé, allez voir mon 44 | dépôt GitHub.

45 | 46 |

Sommaire

47 |
    48 |
  1. Utilisation basique
  2. 49 |
  3. Conventions
  4. 50 |
  5. Les commandes en détail 51 |
      52 |
    1. Diff
    2. 53 |
    3. Commit
    4. 54 |
    5. Checkout
    6. 55 |
    7. Faire un commit avec une HEAD détachée
    8. 56 |
    9. Reset
    10. 57 |
    11. Merge
    12. 58 |
    13. Cherry Pick
    14. 59 |
    15. Rebase
    16. 60 |
    61 |
  6. 62 |
  7. Notes techniques
  8. 63 |
64 | 65 |

Utilisation basique

66 | 67 |
68 | 69 |

Les quatre commandes ci-dessus copient des fichiers entre la working copy (copie de travail), 70 | le stage (aussi appelé l'index), et l'histoire (sous la forme de commits).

71 | 72 |
    73 | 74 |
  • git add fichiers copie les fichiers (dans leur 75 | état courant) vers le stage.
  • 76 | 77 |
  • git commit fait un "cliché" du stage sous la forme d'un 78 | commit.
  • 79 | 80 |
  • git reset -- fichiers supprime les fichiers du stage ; i.e. elle 81 | copie les fichiers du dernier commit vers le stage. Utilisez cette 82 | commande pour annuler une commande git add fichiers. Vous pouvez aussi faire un 83 | git reset pour vider complètement le stage.
  • 84 | 85 |
  • git checkout -- fichiers copie les fichiers du 86 | stage vers la working copy (copie de travail). Utilisez cette commande pour annuler 87 | des changements locaux (ceux de votre copie de travail).
  • 88 | 89 |
90 | 91 |

Vous pouvez utiliser git reset -p, git checkout -p, ou 92 | git add -p au lieu de (ou en plus de) spécifier des fichiers particuliers 93 | pour choisir interactivement quels morceaux doivent être copiés.

94 | 95 |

Il est également possible de contourner complètement le stage et de sortir (check out) les fichiers 96 | directement de l'histoire, ou de commiter les fichiers sans les faire passer préalablement par le stage.

97 | 98 |
99 | 100 |
    101 | 102 |
  • git commit -a revient à exécuter successivement git add 103 | sur tous les fichiers qui existaient dans le dernier commit, puis 104 | git commit.
  • 105 | 106 |
  • git commit fichiers crée un nouveau commit 107 | incluant le contenu du dernier commit, plus un cliché des fichiers pris 108 | dans la working copy. De plus, les fichiers sont copiés dans 109 | le stage.
  • 110 | 111 |
  • git checkout HEAD -- fichiers copie les fichiers 112 | depuis le dernier commit vers à la fois le stage et la working copy.
  • 113 | 114 |
115 | 116 |

Conventions

117 | 118 |

Dans la suite de ce document, nous allons utiliser des graphiques de 119 | la forme suivante.

120 | 121 |
122 | 123 |

Les commits sont représentés en vert, avec des IDs à 5 caractères et 124 | ils pointent vers leurs parents. Les branches sont représentées en orange, 125 | et elles pointent vers des commits particuliers. La branche courante est 126 | idendifiée par la référence HEAD, qui est "attachée" à cette branche. 127 | Dans cette image les cinq derniers commits sont représentés, ed489 étant 128 | le plus récent. 129 | main (la branche courante) pointe vers ce commit, alors que 130 | stable (une autre branche) pointe vers un ancêtre du commit main. 131 |

132 | 133 |

Les commandes en détail

134 | 135 |

Diff

136 | 137 |

Il y a plusieurs façons de visualiser les différences entre commits. Vous 138 | trouverez ci-dessous quelques exemples courants. Toutes ces commandes peuvent également 139 | prendre des noms de fichers comme arguments supplémentaires. Ils restreignent alors les différences 140 | affichées aux fichiers désignés.

141 | 142 |
143 | 144 |

Commit

145 | 146 |

Quand vous commitez, git crée un nouvel objet de type "commit" en utilisant 147 | les fichiers présents dans le stage, et en prenant comme parent le commit courant. 148 | Il déplace aussi la branche courante vers ce nouveau commit. Sur l'image ci-dessous, 149 | la branche courante est 150 | main. Avant que la commande ne soit exécutée, main pointait sur 151 | ed489. Après l'exécution de la commande, un nouveau commit f0cec est créé, 152 | avec ed489 comme parent, et main est déplacé pour pointer sur ce nouveau 153 | commit.

154 | 155 |
156 | 157 |

Ce fonctionnement est systématique, même si la branche courante est un ancêtre d'une autre. 158 | Ci-dessous, un commit a lieu sur une branche stable, qui est un ancêtre de main. 159 | Le commit résultant est : 1800b ; stable n'est alors plus un ancêtre de main. 160 | Pour consolider ces deux histoires (maintenant divergentes), un merge 161 | (ou un rebase) va être nécessaire.

162 | 163 |
164 | 165 |

Si vous commettez une erreur dans un commit, il est facile de la corriger avec 166 | git commit --amend. Quand vous utilisez cette commande, git crée un 167 | nouveau commit avec le même parent que le commit courant. (L'ancien commit sera supprimé 168 | s'il n'y a plus aucun élément — une branche par exemple — qui le référence).

169 | 170 |
171 | 172 |

Une quatrième situation un peu particulière consiste à commiter avec une detached 173 | HEAD (HEAD détachée), comme expliqué ci-après.

174 | 175 |

Checkout

176 | 177 |

La commande checkout est utilisée pour copier des fichiers de l'histoire (ou du stage) 178 | vers la working copy, mais également pour passer d'une branche à une autre.

179 | 180 |

Quand un nom de fichier (ou -p) est passé en paramètre, git copie ces fichiers 181 | depuis le commit concerné vers le stage et vers la working copy. Par exemple, 182 | git checkout HEAD~ foo.c copie le fichier foo.c 183 | depuis le commit nommé HEAD~ (le parent du commit courant) vers 184 | la working copy, et le place aussi dans le stage. (Si aucun nom de commit n'est donné, 185 | les fichiers sont copiés depuis le stage). Notez que la branche courante n'est pas modifiée.

186 | 187 |
188 | 189 |

Quand aucun nom de fichier n'est passé en argument, et que la référence est 190 | une branche (locale), HEAD est déplacée vers cette branche (i.e. on "bascule" 191 | sur cette branche), et le stage ainsi que la working copy s'ajustent pour correspondre au contenu 192 | de ce commit. Les fichiers qui existent dans le nouveau commit (a47c3 ci-dessous) sont copiés ; 193 | les fichiers qui existent dans l'ancien commit (ed489) mais pas dans le nouveau sont supprimés ; 194 | et les fichiers qui n'existent dans aucun des deux sont ignorés.

195 | 196 |
197 | 198 |

Quand aucun nom de fichier n'est donné et que la référence n'est pas une 199 | banche (locale) — i.e. c'est un tag, une branche distante, un ID SHA-1 ou un truc du genre 200 | main~3 — on se retrouve avec une branche anonyme appelée 201 | une detached HEAD. Ceci est utile pour se déplacer rapidement dans l'histoire. 202 | Supposons que vous souhaitiez compiler la version 1.6.6.1 de git. Vous pouvez faire un 203 | git checkout v1.6.6.1 (qui est un tag, et non une branche), compiler, installer, 204 | et rebasculer sur une autre branche, avec par exemple git checkout main. 205 | Cela dit, commiter fonctionne légèrement différemment avec une "detached HEAD" ; 206 | voir les détails ci-dessous.

207 | 208 |
209 | 210 |

Commiter avec une "Detached HEAD"

211 | 212 |

Quand votre HEAD est détachée, la commande commit fonctionne normalement, 213 | excepté le fait qu'aucune branche (nommée) n'est mise à jour. 214 | (Vous pouvez voir ça comme une branche anonyme).

215 | 216 |
217 | 218 |

Une fois que vous basculez sur une autre branche, par exemple main, 219 | le commit n'est (possiblement) plus référencé par aucun élément (branche, tag, ...), 220 | et est perdu. Notez qu'après la commande, le commit 2eecb n'est plus référencé.

221 | 222 |
223 | 224 |

Si, au contraire, vous souhaitez conserver cet état, vous pouvez créer une nouvelle 225 | branche (nommée), en utilisant git checkout -b nom_de_la_branche.

226 | 227 |
228 | 229 |

Reset

230 | 231 |

La commande reset déplace la branche courante à une autre position et 232 | met éventuellement à jour le stage et la working copy. Elle est également utilisée 233 | pour copier des fichiers depuis l'histoire vers le stage, sans toucher à la working copy.

234 | 235 |

Si un commit est passé en argument, sans nom de fichier, la branche courante est 236 | déplacée vers ce commit, et le stage est mis à jour pour correspondre à ce commit. 237 | Si l'option --hard est passée en argument, la working copy est aussi mise à jour. 238 | Si l'option --soft est passée en argument, aucun des deux n'est mis à jour.

239 | 240 |
241 | 242 |

Si aucun commit n'est passé en argument, la valeur par défaut est HEAD. 243 | Dans ce cas, la branche n'est pas déplacée, mais le stage (et éventuellement la working copy, 244 | si l'option --hard est passée en argument) sont remis à zéro pour correspondre 245 | au contenu du dernier commit.

246 | 247 |
248 | 249 |

Si un fichier (et/ou l'option -p) est passé en argument, alors la commande 250 | se comporte comme checkout avec un nom de fichier, hormis le fait 251 | que seul le stage (et pas la working copy) est mis à jour. (Vous pouvez aussi spécifier 252 | le commit à partir duquel prendre les fichiers, au lieu de HEAD.)

253 | 254 |
255 | 256 |

Merge

257 | 258 |

Un merge crée un nouveau commit qui incorpore les changements d'autres commits. 259 | Avant de merger, le stage doit correspondre au contenu du commit courant. 260 | Le cas trivial est si l'autre commit correspond à un ancêtre du commit courant. Dans ce 261 | cas, rien n'est fait. Un autre cas simple, est si le commit courant est un ancêtre de 262 | l'autre commit. L'opération résultante est nommée fast-forward (avance rapide) ; 263 | la référence est alors simplement déplacée, et le nouveau commit est "checked out".

264 | 265 |
266 | 267 |

Dans les autres cas, un "vrai" merge est effectué. Vous pouvez choisir d'autres stratégies, 268 | mais par défaut c'est un merge "récursif" qui est effectué. Il consiste à prendre le commit courant 269 | (ed489 ci-dessous), et l'autre commit (33104), 270 | et leur ancêtre commun (b325c), et à effectuer un "three-way merge". 272 | Le résultat est placé dans la working copy et dans le stage, et un commit 273 | est effectué, avec un parent supplémentaire (33104).

274 | 275 |
276 | 277 |

Cherry Pick

278 | 279 |

La commande cherry-pick copie un commit, en créant un nouveau commit sur la branche 280 | courante, avec le même message et le même "patch" que le commit désigné.

281 | 282 |
283 | 284 |

Rebase

285 | 286 |

Un "rebase" est une alternative au merge pour combiner 287 | plusieurs branches. Alors q'un merge crée un commit unique avec deux parents, produisant 288 | une histoire non linéaire, un rebase rejoue les commits de la branche courante sur une autre branche, 289 | produisant une histoire linéaire. En fait, c'est une façon automatique d'effectuer 290 | plusieurs cherry-picks à la fois.

291 | 292 |
293 | 294 |

La commande ci-dessus prend tous les commits qui existent dans topic 295 | mais pas dans main (i.e. 169a6 et 2c33a), les rejoue 296 | sur main, puis déplace la branche (topic) en conséquence. 297 | Notez que les anciens commits seront supprimés (garbage collection) s'ils ne sont 298 | plus référencés.

299 | 300 |

Pour indiquer jusqu'où vous souhaitez remonter dans l'histoire, utilisez 301 | l'otpion --onto. 302 | La command suivante rejoue sur main les commits les plus récents 303 | de la branche courante depuis 169a6 (exclu), autrement dit 304 | 2c33a.

305 | 306 |
307 | 308 |

Il y aussi git rebase --interactive, qui permet d'effectuer 309 | des opérations plus complexes, au delà de simplement rejouer des commits. 310 | Comme par exemple supprimer des commits, réordonner des commits, modifier des commits, 311 | ou rassembler plusieurs commit en un seul. Il n'y a pas de schéma évident pour ces opérations ; voir 312 | git-rebase(1) 313 | pour les détails.

314 | 315 |

Notes techniques

316 | 317 |

Le contenu des fichiers n'est pas vraiment stocké dans l'index 318 | (.git/index) ou dans les commits. En réalité, chaque fichier est stocké 319 | dans la base de données d'objets (.git/objects) sous forme d'un blob, 320 | identifié par son hash SHA-1. Le fichier d'index liste les noms de fichier ainsi que 321 | l'identifiant du blob associé et quelques autres données. 322 | Pour les commits, il existe un autre type de donnée appelé tree, lui 323 | aussi identifié par son hash. Un "tree" correpond à un dossier dans la 324 | working copy, et contient une liste de "trees" et de "blobs" représentant 325 | respectivement ses sous-dossiers et ses sous-fichiers. 326 | Chaque commit stocke l'identifiant de son "tree" de plus haut niveau, 327 | qui lui-même contient tous les "blobs" et "trees" associés avec ce 328 | commit.

329 | 330 |

Si vous commitez avec une "detached HEAD", le dernier commit est en fait toujours 331 | référencé par quelque chose : le "reflog" de HEAD. Néanmoins, il finira par 332 | expirer, et le commit sera finalement perdu (garbage collection), de même que 333 | les commits neutralisés par un git commit --amend ou un git 334 | rebase.

335 | 336 |
337 | 338 |

Copyright © 2010, 339 | Mark Lodato. 340 | French translation © 2012, 341 | Michel Lefranc. 342 |

343 | 344 |

347 | Cette oeuvre est mise à disposition selon les termes de la Licence 349 | Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage 350 | à l'Identique 3.0 États-Unis.

351 | 352 | 353 | 354 | -------------------------------------------------------------------------------- /index-it.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Guida visuale a Git 6 | 7 | 8 | 10 | 11 | 12 |

Guida visuale a Git

13 | 14 |
15 | Other Languages: 16 | 32 |
33 | 34 | 36 | 37 | 39 | 40 |

Questa pagina offre una breve guida visuale per i comandi più comuni di Git. Una 41 | volta comprese le basi di Git, questo sito potrà aiutarti a fissare questi concetti. 42 | Se ti interessa conoscere come è stato creato questo sito visita il mio 43 | repository GitHub.

44 | 45 |

Contenuti

46 |
    47 |
  1. Utilizzo di Base
  2. 48 |
  3. Convenzioni
  4. 49 |
  5. Comandi nei dettagli 50 |
      51 |
    1. Diff
    2. 52 |
    3. Commit
    4. 53 |
    5. Checkout
    6. 54 |
    7. Commit di una HEAD isolata
    8. 55 |
    9. Reset
    10. 56 |
    11. Merge
    12. 57 |
    13. Cherry Pick
    14. 58 |
    15. Rebase
    16. 59 |
    60 |
  6. 61 |
  7. Note tecniche
  8. 62 |
63 | 64 |

Utilizzo di Base

65 | 66 |
67 | 68 |

I quattro comandi precedenti copiano i file tra la working directory, 69 | lo stage (chiamato anche index) e l'history (rapprestentata dai commit).

70 | 71 |
    72 | 73 |
  • git add file copia i file (nel loro 74 | stato corrente) nello stage.
  • 75 | 76 |
  • git commit crea uno snapshot dello stage sotto forma di 77 | commit.
  • 78 | 79 |
  • git reset -- file rimuove i file dallo stage; 80 | ovvero copia i file dell'ultimo commit nello stage. Utilizza 81 | questo comando per annullare un git add file. Puoi anche utilizzare 82 | git reset per rimuovere tutto dallo stage.
  • 83 | 84 |
  • git checkout -- file copia i file dallo 85 | stage alla working directory. Utilizza questo comando per eliminare tutte le 86 | modifiche locali.
  • 87 | 88 |
89 | 90 |

Puoi usare git reset -p, git checkout -p, oppure 91 | git add -p al posto di (o in aggiunta di) specificare i file 92 | specifici, per determinare in modo interattivo, che blocchi copiare.

93 | 94 |

È anche possibile evitare lo stage ed eseguire il check out di file 95 | direttamente dall'history o eseguire il commit senza inserire prima i 96 | file nello stage.

97 | 98 |
99 | 100 |
    101 | 102 |
  • git commit -a è equivalente ad eseguire git add 103 | su tutti i file esistenti nell'ultimo commit, seguito da 104 | git commit.
  • 105 | 106 |
  • git commit file crea un nuovo commit contenente 107 | i contenuti dell'ultimo commit oltre allo snapshot dei file presi 108 | dalla working directory. Inoltre i file vengono copiati nello stage.
  • 109 | 110 |
  • git checkout HEAD -- file copia i file 111 | dall'ultimo commit sia allo stage che alla working directory.
  • 112 | 113 |
114 | 115 |

Convenzioni

116 | 117 |

Nel resto di questo documento useremo grafici come quello seguente.

118 | 119 |
120 | 121 |

I commit sono mostrati in verde con ID da 5 caratteri, essi puntano al 122 | loro genitore. I branch sono mostrati in arancione, essi puntano a specifici 123 | commit. Il branch corrente è identificato dalla speciale referenza 124 | HEAD, che è "attaccata" a quel branch. In questa immagine vengono 125 | mostrati gli ultimi 5 commit, il più recente è il ed489. 126 | main (il branch corrente) punta a questo commit, mentre 127 | stable (un altro branch) punta ad un antenato del commit del main.

128 | 129 |

Comandi nei Dettagli

130 | 131 |

Diff

132 | 133 |

Esistono diversi modi per verificare le differenze tra i commit. Di seguito 134 | alcuni esempi comuni. Ognuno di questi comandi può opzionalmente ricevere 135 | nomi di file come ulteriori parametri per limitare le differenze solo ai file 136 | specificati.

137 | 138 |
139 | 140 |

Commit

141 | 142 |

Quando si esegue un commit git crea un nuovo oggetto commit utilizzando 143 | i file dello stage ed impostando il genitore al commit attuale. Successivamente 144 | punta il branch corrente a questo nuovo commit. Nell'immagine seguente il 145 | branch corrente è main. Prima dell'esecuzione del comando main 146 | puntava a ed489. In seguito, un nuovo commit, f0cec, è stato creato 147 | con genitore ed489, quindi main è stato spostato sul nuovo commit.

148 | 149 |
150 | 151 |

Lo stesso processo avviene anche quando il branch corrente è un antenato 152 | di un altro. Di seguito vediamo un commit sul branch stable, che è un 153 | antenato di main, risultante in 1800b. Di conseguenza, 154 | stable non è più un antenato di main. Per unire le due 155 | history sarà necessario un merge (o un rebase).

156 | 157 |
158 | 159 |

A volte può capitare di commettere un errore in un commit, questo è facile 160 | da correggere con git commit --amend. Quando si utilizza questo 161 | comando git crea un nuovo commit con lo stesso genitore del commit corrente. 162 | (Il vecchio commit verrà scartato se non ha referenze da nessuno.)

163 | 164 |
165 | 166 |

Un quarto caso è rappresentato dal commit con HEAD isolata, 167 | come verrà spiegato in seguito.

168 | 169 |

Checkout

170 | 171 |

Il comando checkout viene utilizzato per copiare i file dall'history 172 | (o dallo stage) alla working directory, opzionalmente per scambiare i branch.

173 | 174 |

Quando un file (e/o -p) viene passato, git copia questi file 175 | da un certo commit allo stage ed alla working directory. Per esempio, 176 | git checkout HEAD~ foo.c copia il file foo.c 177 | dal commit chiamato HEAD~ (il genitore del commit corrente) alla 178 | working directory, oltre ad inserirlo nello stage. (Se non viene specificato 179 | un commit, i file vengono copiati dallo stage.) Si noti che il branch corrente 180 | non è cambiato.

181 | 182 |
183 | 184 |

Quando il nome di un file non viene passato ma la referenza è 185 | un branch (locale), HEAD viene associata a quel branch (ovvero si fa 186 | lo "switch a" quel branch), in seguito lo stage e la working directory vengono 187 | impostate per rispecchiare i contenuti di quel commit. Ogni file esistente nel 188 | nuovo commit (a47c3 qui sotto) viene copiato; ogni file esistente nel 189 | vecchio commit (ed489) ma non nel nuovo viene eliminato; ogni file 190 | esistente in entrambi viene ignorato.

191 | 192 |
193 | 194 |

Quando il nome di un file non viene passato e la referenza non 195 | è ad un branch (locale) — si ipotizzi sia un tag, un branch remoto, un 196 | ID SHA-1 o qualcosa tipo main~3 — abbiamo a che fare con un 197 | branch anonimo chiamato HEAD isolata. Questo è utile per muoversi 198 | liberamente nell'history. Supponiamo di voler compilare la versione 1.6.6.1 di git. 199 | Si può ricorrere a git checkout v1.6.6.1 (che è un tag, non un branch), 200 | compilare, installare, e successivamente tornare ad un altro branch, per esempio 201 | git checkout main. 202 | Tuttavia eseguire dei commit con HEAD isolata richiede una procedura leggermente 203 | diversa; ne parliamo di seguito.

204 | 205 |
206 | 207 |

Commit con HEAD isolata

208 | 209 |

Quando HEAD è isolata, i commit funzionano normalmente, l'unica 210 | eccezione è data dal fatto che il branch senza nome viene aggiornato. (Si 211 | può pensare ad esso come ad un branch anonimo.)

212 | 213 |
214 | 215 |

Una volto eseguito il checkout di qualcos'altro, per esempio di main, 216 | il commit (presumibilmente) non essendo più referenziato da nessun altro 217 | viene perso. Si noti come dopo il comando non ci sia più alcuna referenza 218 | a 2eecb.

219 | 220 |
221 | 222 |

Se, d'altronde, si volesse memorizzare questo stato, sarebbe necessario 223 | creare un nuovo branch con nome utilizzando git checkout -b name.

224 | 225 |
226 | 227 |

Reset

228 | 229 |

Il comando reset sposta il branch corrente in un'altra posizione 230 | ed opzionalmente aggiorna lo stage e la working directory. Viene anche 231 | utilizzato per copiare file dall'history allo stage senza tirare in ballo 232 | la working directory.

233 | 234 |

Se un commit viene passato senza nomi di file il branch corrente viene 235 | spostato a quel commit e quindi lo stage viene aggiornato per rispecchiare 236 | quel commit. Se viene utilizzato --hard viene aggiornata anche 237 | la working directory. Se viene passato --soft non viene aggiornato 238 | nulla.

239 | 240 |
241 | 242 |

Se non viene passato un commit il default utilizzato è HEAD. 243 | In questo caso il branch non viene spostato, ma lo stage (ed opzionalmente 244 | anche la working directory se viene passato --hard) vengono 245 | resettati ai contenuti dell'ultimo commit.

246 | 247 |
248 | 249 |

Se viene passato un nome di file (e/o -p) allora il comando 250 | si comporta in modo simile a checkout con un nome di file, 251 | l'unica differenza è che solo lo stage viene aggiornato (e non la working directory). 252 | (È anche possibile specificare il commit dal quale prendere i file al posto di 253 | HEAD.)

254 | 255 |
256 | 257 |

Merge

258 | 259 |

Merge crea un nuovo commit che include modifiche provenienti da altri commit. 260 | Prima di eseguire il merge lo stage deve corrispondere al commit corrente. 261 | Il caso banale è quello in cui l'altro commit è un antenato del commit corrente, 262 | non serve fare niente. Un altro caso semplice è quello in cui il commit 263 | corrente è un antenato dell'altro commit. Avremo quindi un merge fast-forward. 264 | La referenza viene semplicemente spostata e viene eseguito il checkout sul 265 | nuovo commit.

266 | 267 |
268 | 269 |

Negli altri casi avremo un merge "reale". Si possono scegliere altre 270 | strategie ma quella di default è rappresentata dal merge "ricorsivo" che 271 | semplicemente prende il commit corrente (ed489 below), l'altro commit 272 | (33104), il loro antenato comune (b325c) ed esegue un merge a tre vie. 274 | Il risultato viene memorizzato nella working directory e nello stage, seguirà 275 | un commit con un genitore extra (33104). 276 |

277 | 278 |
279 | 280 |

Cherry Pick

281 | 282 |

Il comando cherry-pick "copia" un commit creandone uno nuovo nel branch 283 | corrente con lo stesso messaggio applicando le modifiche come se fosse 284 | un commit diverso.

285 | 286 |
287 | 288 |

Rebase

289 | 290 |

Rebase è un'alternativa a merge per combinare assieme 291 | più branch. Mentre un merge crea un singolo commit con due genitori, 292 | preservando l'history non lineare, un rebase riporta i commit dal branch corrente 293 | su un altro producendo un history lineare. In sostanza è un modo automatizzato 294 | per eseguire diversi cherry-pickin sequenza.

295 | 296 |
297 | 298 |

Il comando precedente prende tutti i commit esistenti in topic 299 | ma non in main (precisamente 169a6 e 2c33a), li 300 | riporta sul main e poi sposta l'head del branch sulla nuova 301 | estremità.

302 | 303 |

Per limitare quanto andare all'indietro utilizzare l'opzione --onto. 304 | Il comando seguente riporta sul main i commit più recenti del branch corrente 305 | da 169a6 (escluso), precisamente 2c33a.

306 | 307 |
308 | 309 |

Esiste anche git rebase --interactive, che permette di fare 310 | cose più complicate rispetto a riportare semplicemente commit, più precisamente 311 | eliminare, riordinare, modificare i commit. Non esiste un caso evidente 312 | per un'immagine per questo; vedere git-rebase(1) 314 | per maggiori dettagli.

315 | 316 |

Technical Notes

317 | 318 |

I contenuti dei file non sono memorizzati nell'index (.git/index) 319 | o negli oggetti dei commit. Ogni file è memorizzato nel database 320 | degli oggetti (.git/objects) come blob, identificato dal 321 | suo hash SHA-1. Il file index elenca i nomi dei file assieme all'identificatore 322 | del blob associato oltre ad altri dati. Per i commit esiste un ulteriore 323 | tipo di dato, tree, anch'esso identificato da un suo hash. 324 | I tree corrispondono alle directory presenti nella working directory 325 | e contengono una lista di tree e blob corrispondenti ad ogni nome di file 326 | in quella directory. Ogni commit memorizza l'identificatore del suo 327 | tree principale che a sua volta contiene tutti i blob e gli altri tree 328 | associati a quel commit.

329 | 330 |

Se viene eseguito un commit utilizzando un'HEAD isolata l'ultimo commit 331 | viene referenziato da qualcosa: dal reflog per HEAD. Tuttavia questo 332 | scompare in pochi istanti, quindi il commit verrà gestito dal garbage collector 333 | come succede per i commit scartati con git commit --amend o git 334 | rebase.

335 | 336 |
337 | 338 |

Copyright © 2010, 339 | Mark Lodato. 340 | Italian translation © 2012, 341 | Daniel Londero. 342 |

343 | 344 |

347 | This work is licensed under a Creative 349 | Commons Attribution-Noncommercial-Share Alike 3.0 United States 350 | License.

351 | 352 |

Want to translate into another 353 | language?

354 | 355 | 356 | 357 | -------------------------------------------------------------------------------- /index-ja.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 図解 Git 6 | 7 | 8 | 10 | 11 | 12 |

図解 Git

13 | 14 |
15 | 他の言語 16 | 32 |
33 | 34 | 36 | 37 | 39 | 40 |

このページのオリジナルは、Mark Lodato さんが執筆した A Visual Git Referenceです。

41 | 42 |

このページでは、よく使われる git のコマンドを簡潔に図を用いて説明します。 43 | git について少し知識があるなら、このページはその知識を整理するのに役立つかもしれません。このページがどのようにして作られたのか興味があるなら、私のGitHub リポジトリを見て下さい。(日本語訳の GitHub リポジトリ)

44 |

内容

45 |
    46 |
  1. 基本的な使い方
  2. 47 |
  3. 凡例
  4. 48 |
  5. コマンドの詳細 49 |
      50 |
    1. Diff
    2. 51 |
    3. Commit
    4. 52 |
    5. Checkout
    6. 53 |
    7. 分離HEADでの commit
    8. 54 |
    9. Reset
    10. 55 |
    11. Merge
    12. 56 |
    13. Cherry Pick
    14. 57 |
    15. Rebase
    16. 58 |
    59 |
  6. 60 |
  7. 技術メモ
  8. 61 |
62 | 63 |

基本的な使い方

64 | 65 |
66 | 67 |

上記4つのコマンドは、作業ディレクトリ、ステージ(インデックスとも呼ばれる)、および履歴(一連のコミット)間でファイルをコピーします。

68 | 69 |
    70 | 71 |
  • git add filesfiles (の現在の状態)をステージにコピーします。
  • 72 | 73 |
  • git commit は、ステージの内容をコミットとして保存します。
  • 74 | 75 |
  • git reset -- files は、files のステージングを取りやめます。つまり、filesを最新のコミットからステージへコピーします。これは、git add files を取り消すのに使えます。また、git reset として、すべてのステージングを取り消すこともできます。
  • 76 | Use this 77 | 78 |
  • git checkout -- files は、filesをステージから作業ディレクトリへコピーします。ローカルの変更をすべて破棄するには、このコマンドを使って下さい。
  • 79 | 80 |
81 | 82 |

ファイルを特定しないで(あるいはファイルに加えて)、git reset -pgit checkout -p、あるいは 83 | git add -p を使えば、対話的にどのハンクを対象にするのか選べます。

84 | 85 |

凡例

86 | 87 |

これ以降、以下のような図を使っていきます。(訳注:図中の英語を日本語にする方法が分かりません。orz)

88 | 89 |
90 | 91 |

緑色はコミットで、5文字の識別子が付いており、自分の親を指しています。ブランチはオレンジ色で示してあり、ある特定のコミットを指しています。現在のブランチは、特殊な参照である HEAD によって識別され、その情報はブランチに*くっついて*います。この図では、最新の5つのコミットが表示されており、一番新しいコミットには ed489 という識別子が付いています。現在のブランチである main は、このコミットを指しています。一方、もう一つのブランチ stable は、main が指すコミットの祖先を指しています。

92 | 93 |

コマンドの詳細

94 | 95 |

Diff

96 | 97 |

差分を取る方法は、たくさんあります。以下によく使われるコマンドの例を示します。すべてのコマンドには、ファイル名を指定することもでき、その場合は差分の計算をそのファイルに限定します。

98 | 99 |
100 | 101 |

Commit

102 | 103 |

コミットを実行すると、git はステージングされたファイルから、新しいコミットオブジェクトを作り、その親として最新のコミットを設定します。そして、現在のブランチをこの新しいコミットへ移動させます。以下の図では、現在のブランチはmainです。このコマンドを実行する前は、mainは、ed489を指していました。実行後は、新しいコミット f0cec が作られ、親が ed489となり、mainがこの新しいコミットへ移動します。

104 | 105 |
106 | 107 |

たとえ、現在のブランチが中間のコミット(あるコミットの親であるコミット)であっても、同じことが起きます。以下の図では、mainの祖先であるstableでコミットが発生し、その結果が1800bとなりました。これ以降、stableは、mainの祖先ではなくなります。この二つの履歴を統合するには、merge (あるいは rebase) を実行する必要があります。

108 | 109 |
110 | 111 |

ときどき、間違ったコミットを実行してしまうこともあるでしょう。git commit --amend を使えば、簡単に訂正できます。このコマンドを使うと、git は最新のコミットと同じ親を持つ新しいコミットを作ります。(古いコミットは、何からも参照されていなければ破棄されます。)

112 | 113 |
114 | 115 |

4番目の使い方は 分離HEADへのコミットですが、これについては後述します。

116 | 117 |

Checkout

118 | 119 |

checkout コマンドは、履歴(またはステージ)から作業ディレクトリへファイルをコピーするために使います。条件によっては、ブランチを切り替えます。

120 | 121 |

ファイル名(と加えて-pと)が与えられると、git は指定されたファイルを指定されたコミットからステージと作業ディレクトリへコピーします。たとえば、git checkout HEAD~ foo.c はファイル foo.cHEAD~ というコミット(最新のコミットの親)から作業ディレクトリへコピーし、同時にステージングします(もしコミット名が指定されないと、ファイルはステージからコピーされます)。現在のブランチには、何の変更もないことに注意しましょう。

122 | 123 |
124 | 125 |

ファイル名が指定*されず*、参照がローカルのブランチである場合、HEADがそのブランチに移動し(つまり、ブランチが切り替わり)、ステージと作業ディレクトリがそのコミットの内容になるよう設定されます。(下の図では a47c3 という名前の)現在コミットに存在するファイルすべてがコピーされます。(ed489 という名前の)以前のコミットに存在するが、現在のコミットには存在しないファイルは、削除されます。どちらにも存在しないファイルは、そのまま残されます。

126 | 127 |
128 | 129 |

ファイル名が指定されず、参照がローカルのブランチでない場合、すなわちタグやリモートブランチ、SHA-1 の名前、あるいは main~3 のように指定された場合は、無名のブランチができます。これは、分離HEADと呼ばれます。この機能を使えば、履歴の中を飛び回れます。たとえば、git バージョン 1.6.6.1 をコンパイルしたいなら、git checkout v1.6.6.1 (v1.6.6.1 はブランチではなくタグ)とした後に、コンパイルしてインストールし、git checkout main のようにブランチに戻ってくればよいのです。ただし、分離HEADへのコミットは、通常とは若干ことなる動作をします。これについては、以下で説明します。

130 | 131 |
132 | 133 |

分離HEADでの commit

134 | 135 |

HEAD が分離されている場合、名前のついたブランチは何も更新されないという点を除いて、commit は通常と同じ動作をします。(これを無名ブランチだと考えてもよいでしょう。)

136 | 137 |
138 | 139 |

なんらかのコマンド、たとえば main を checkout すると、このコミットは他の何からも参照されなくなるので、削除されます。以下の図で、このコマンドを実行した後、2eecb は何からも参照されていないことに注意して下さい。

140 | 141 |
142 | 143 |

逆にもし、この状態を保存したいなら、git checkout -b name を使って、名前付きのブランチを新しく作ればよいのです。

144 | 145 |
146 | 147 |

Reset

148 | 149 |

reset コマンドは、現在のブランチの位置を他へ移動されます。条件によっては、ステージと作業ディレクトリの内容を更新します。このコマンドは、作業ディレクトリを変更せずに、履歴からステージへファイルをコピーする目的でも使われます。

150 | 151 |

ファイル名なしでコミットが指定されると、現在のブランチがそのコミットに移動し、ステージの内容はそのコミットと同じになります。--hard が指定されると、作業ディレクトリも更新されます。--softが指定されると、どちらも更新されません。

152 | 153 |
154 | 155 |

もしコミットが指定されないと、HEAD が指定されたことになります。この場合、ブランチは移動しませんが、ステージの内容が、最新のコミットの内容にリセットされます。(もし --hard が指定されると、作業ディレクトリもリセットされます。)

156 | 157 |
158 | 159 |

もしファイル名(および -p)が指定されると、ファイル名を指定した checkout のように動作しますが、更新されるのは作業ディレクトリではなく、ステージのみです。(HEAD以外のコミットからファイルをコピーするように、コミットを指定することもできます。)

160 | 161 |
162 | 163 |

Merge

164 | 165 |

merge は、他のコミットから変更を受け入れるための新しいコミットを作成します。merge する前は、ステージが最新のコミットと一致していないといけません。つまらない例としては、他のコミットが現在のコミットの祖先である場合が挙げられます。この場合は、何も起きません。次に簡単な例としては、現在のコミットが他のコミットの祖先である場合です。これは、fast-forward マージとなります。単に参照が移動して、移動先のコミットが checkout されます。

166 | 167 |
168 | 169 |

それ以外の場合では、本当のマージが起こります。マージの戦略は選択可能ですが、通常は再帰マージが選ばれます。この戦略では基本的に、現在のコミット(ed489 below) と指定されたコミット(33104、other) の共通の先祖であるコミット(b325c) が特定され、three-way マージが実行されます。結果は、作業ディレクトリとステージに反映され、commit が実行されます。このコミットでは、二人目の親として (33104)が指定されます。

170 | 171 |
172 | 173 |

Cherry Pick

174 | 175 |

cherry-pick コマンドは、あるコミットからメッセージとパッチをコピーし、現在のブランチに新しいコミットを作ります。

176 | 177 |
178 | 179 |

Rebase

180 | 181 |

rebase は、merge の代替コマンドあり、複数のブランチを接ぎ木します。merge は 2 つの親を持つ 1 つのコミットを作成し、履歴を一直線に保ちませんが、rebase は現在のブランチにあるコミットを他のブランチで再現することで履歴を一直線に保ちます。本質的に、rebase は自動的に連続で cherry-pick をすることに他なりません。

182 | 183 |
184 | 185 |

上記のコマンドは、topicブランチに存在するがmainには存在しないすべてのコミット(すなわち169a62c33a)をmainブランチ上で再現します。そして、ブランチを新しい先端に移動させます。古いコミットは、他から参照されてないので、ゴミとして回収されます。

186 | 187 |

履歴をどれだけたどるかを制限するためには、--onto オプションを使います。次のコマンドは、現在のブランチの 169a6 より後 (それ自体は含まない)のコミット(つまり2c33a)をmainブランチで再現します。 188 | 189 |

190 | 191 |

コミットを再現するだけでなく、もっと複雑なことを指定できるコマンド git rebase --interactive もあります。このコマンドでは、コミットを削除したり、変更したり、コミット同士を統合したりできます。これを表現する適切な図は存在しません。詳細は、git-rebase(1) を参照して下さい。

192 | 193 |

技術メモ

194 | 195 |

ファイルの内容は実際には、インデックスファイル(.git/index)やコミットオブジェクトの中には格納されません。ファイルはオブジェクトデーダベース(.git/objects)にblobとして格納され、SHA-1 ハッシュで識別されます。インデックスファイルは、ファイル名、対応するblobの識別子、そして他のデータの一覧です。他にもtreeというデータ型があって、これもハッシュで識別されます。treeは作業ディレクトリに含まれるディレクトリに対応し、treeやそのディレクトリに含まれるファイルに対応するblobを格納しています。それぞれのコミットは、最上位のtreeの識別子を格納しており、そのtreeは commit されるすべての blob と他のtreeを格納しています。

196 | 197 |

分離HEADを使って commit すると、最後のコミットは HEAD の reflog によって参照されます。しかし、これはしばらくするとなくなり、コミットはゴミとして回収されます。これは、git commit --amendgit rebase で破棄されたコミットと同様です。

198 | 199 |
200 | 201 |

Copyright © 2010, 202 | Mark Lodato. 203 | 訳の著作権は山本和彦に属します。

204 | 205 |

この 作品 は クリエイティブ・コモンズ 表示 - 非営利 - 継承 3.0 アメリカ合衆国 ライセンスの下に提供されています。

206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /index-ko.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | A Visual Git Reference 6 | 7 | 8 | 10 | 11 | 12 |

A Visual Git Reference

13 | 14 |
15 | 다른 언어로 보기 16 | 32 |
33 | 34 | 36 | 37 | 39 | 40 |

이 문서는 Git에서 주로 사용하는 명령들에 대해 여러 그래프와 함께 41 | 요약하여 설명하고 있습니다. 이 문서를 통해 Git이 어떻게 돌아가는지 42 | 한번 살짝 살펴보고 나면 Git을 이해하는데 있어 밝은 등대가 되어줄 것입니다. 43 | 이 문서가 어떻게 만들어졌는지 관심있는 분은 44 | GitHub 저장소로 45 | 찾아와서 살펴보시기 바랍니다.

46 | 47 | 50 |

목차

51 |
    52 |
  1. 기초 사용법
  2. 53 |
  3. 관례
  4. 54 |
  5. 명령어 살펴보기 55 |
      56 |
    1. Diff
    2. 57 |
    3. Commit(커밋)
    4. 58 |
    5. Checkout
    6. 59 |
    7. Detached HEAD와 Commit
    8. 60 |
    9. Reset
    10. 61 |
    11. Merge
    12. 62 |
    13. Cherry Pick
    14. 63 |
    15. Rebase
    16. 64 |
    65 |
  6. 66 |
  7. 기술적인 내용
  8. 67 |
  9. 실습: 명령어들의 결과 보기
  10. 68 |
69 | 70 |

기초 사용법

71 | 72 |
73 | 74 |

위의 네 가지 명령을 사용하여 작업 디렉토리, Stage 영역(Index 라고도 75 | 부르는), 히스토리(저장된 커밋들) 사이에 파일을 복사합니다.

76 | 77 |
    78 | 79 |
  • git add files 명령은 (현재의) files 80 | 파일들을 Stage 영역으로 복사합니다.
  • 81 | 82 |
  • git commit 명령은 Stage 영역의 현재 Snapshot을 83 | 커밋으로 저장합니다.
  • 84 | 85 |
  • git reset -- files 명령은 마지막 커밋에서 86 | Stage 영역으로 files 파일들을 복사합니다. 87 | git add files 명령에 대한 '되돌리기' 명령입니다. 88 | git reset 명령으로 모든 파일을 이전 커밋으로 89 | 복원할 수 있습니다.
  • 90 | 91 |
  • git checkout -- files 명령은 Stage 영역에서 92 | 작업 디렉토리로 파일을 복사합니다. Stage 영역에 추가하지 않은 변경 내용에 93 | 대한 되돌리기 명령입니다.
  • 94 | 95 |
96 | 97 |

git reset -pgit checkout -p 또는 98 | git add -p 명령과 같이 -p 옵션을 사용하여 파일을 지정하지 99 | 않고 어떤 파일에 대해 명령을 적용할 지 대화형 명령을 사용할 수 100 | 있습니다.

101 | 102 |

Stage 영역을 거치지 않고 직접 History로부터 파일을 Checkout 하거나, Stage 103 | 영역을 거치지 않고 직접 Commit을 할 수도 있습니다.

104 | 105 |
106 | 107 |
    108 | 109 |
  • git commit -a 명령은 마지막 커밋에 존재하는 모든 파일들에 대하여 110 | git add 명령을 적용한 후 git commit 명령을 적용하는 것과 다르지 않다.
  • 111 | 112 |
  • git commit files 명령을 실행하면 마지막 커밋을 기반으로 113 | files의 변경된 내용을 포함하는 새로운 커밋을 하나 만든다. 이 때 files은 114 | Stage 영역에 추가된다.
  • 115 | 116 |
  • git checkout HEAD -- files 명령은 files 117 | 을 마지막 커밋으로부터 Stage 영역과 현재 작업 디렉토리에 동시에 복사한다.
  • 118 | 119 |
120 | 121 | 122 |

관례

123 | 124 |

이 문서는 다음과 같은 그래프를 사용하여 Git 사용법을 설명 합니다.

125 | 126 |
127 | 128 |

커밋은 5글자의 ID로 표현하며, 부모 커밋을 화살표로 가리킵니다. 129 | 브랜치는 오렌지색이며 어떤 특정 커밋을 가리키고 있습니다. HEAD 130 | 라는 이름으로 현재 브랜치 가리킬 수 있습니다. 위의 그림에는 5개의 커밋이 131 | 있으며 ed489 커밋이 가장 최근의 커밋입니다. main 132 | 브랜치(현재 선택한 브랜치)는 가장 최근의 커밋을 가리키고 있으며 133 | stable 브랜치는 main 브랜치의 뿌리 부분(Ancestor) 134 | 입니다.

135 | 136 |

명령어 살펴보기

137 | 138 |

Diff

139 | 140 |

커밋간의 변경된 사항을 살펴보는 방법은 여러가지가 있습니다. 아래 예제는 141 | 여러 방법 중 대표적인 것들입니다. 파일 이름을 옵션으로 지정하면 특정 파일에 142 | 대한 변경사항만 확인할 수 도 있습니다.

143 | 144 |
145 | 146 |

Commit(커밋)

147 | 148 |

커밋을 하면 Git은 Stage 영역의 파일들과 부모 커밋 정보 그리고 현재 커밋 149 | 정보를 사용하여 새로운 커밋 개체(Commit Object)를 만듭니다. 그리고 현재 150 | 브랜치가 이 새로 만들어진 커밋을 가리키도록 만듭니다. 아래 그림에 보면 현재 151 | 브랜치는 main 이고 명령을 실행하기 전에는 ed489 커밋을 152 | 가리키고 있습니다. 새로 커밋을 하게 되면 커밋의 부모가 ed489 153 | 인f0cec 커밋이 만들어지고 main 브랜치는 f0cec 154 | 커밋을 가리키게 됩니다.

155 | 156 |
157 | 158 |

이런 새로운 커밋이 추가되는 과정은 현재 브랜치가 다른 브랜치의 뿌리 159 | 부분(Ancestor)이라고 해도 가능한 일입니다. 아래 그림을 보면 160 | main 브랜치의 뿌리가 되는 stable 브랜치에서 커밋을 할 161 | 경우 1800b 커밋이 만들어집니다. 이렇게 되면 stable 브랜치는 162 | main 브랜치의 직접적인 뿌리 부분이 되지는 않습니다. 이 두 개의 163 | 히스토리 내용을 합치기 위해서는 Merge(통합, 병합) 또는 Rebase 명령이 164 | 필요합니다.

165 | 166 |
167 | 168 |

가끔 커밋을 할 때 실수를 할 수 있습니다. 하지만 이미 커밋을 했다고 해도 169 | git commit --amend 명령으로 쉽게 실수를 고칠 수 있습니다. 이 170 | 명령을 사용하면 현재 커밋과 부모가 같은 새 커밋을 만듭니다. (실수했던 커밋을 171 | 다른 커밋이나 브랜치가 사용하지 않았다면 자동으로 없어질 것입니다.)

172 | 173 |
174 | 175 |

마지막 경우는 detached HEAD에서 커밋을 하는 것인데 176 | 아래에서 다시 다루기로 한다.

177 | 178 |

Checkout

179 | 180 |

Checkout 명령은 히스토리나 Stage 영역으로부터 현재 작업 디렉토리로 파일을 181 | 복사하는 명령입니다. 또는 브랜치를 변경할 때 사용하기도 합니다.

182 | 183 |

Checkout 명령에 파일 이름이 주어지면 (또는 -p 옵션) Git은 184 | 해당 파일을 주어진 커밋에서 Stage 영역과 작업 디렉토리로 복사합니다. 185 | 예를 들어 git checkout HEAD~ foo.c 명령을 실행하면 186 | HEAD~ 커밋(현재 커밋보다 한 단계 앞의 커밋)으로부터 187 | foo.c 파일을 작업 디렉토리에 복사하고 Stage 영역에도 추가합니다. 188 | (커밋 이름을 지정하지 않으면 Stage 영역에서 복사해옵니다.) 현재 브랜치가 189 | 가리키는 커밋은 바뀌지 않았다는 점을 주목해봅니다.

190 | 191 |
192 | 193 |

파일 이름을 지정하지 않고 브랜치 이름만 지정하면 Git은 HEAD를 194 | 지정한 브랜치를 가리키도록 변경합니다. 이것은 결과적으로 브랜치를 변경한 195 | 것과 같습니다. 따라서 자동으로 Stage 영역과 작업 디렉토리의 내용은 해당 브랜치의 내용으로 196 | 변경됩니다. a47c3 커밋에 포함된 파일들을 현재 디렉토리로 복사할 것이며 197 | 이전 ed489 커밋에는 포함되었지만 a47c3 커밋에 포함되어있지 198 | 않은 파일들은 삭제될 것입니다. 두 커밋에 모두에 포함되지 않은 파일은 무시될 199 | 것입니다.

200 | 201 |
202 | 203 |

파일 이름을 지정하지 않고, (로컬) 브랜치 이름도 지정하지 않은 경우 - 즉, 태그, 204 | 리모트 브랜치, SHA-1 아이디, 혹은 main~3와 같은 유형을 인자로 지정했다면, 205 | detached HEAD라고 부르는 206 | 익명 브랜치(Anonymous Branch)를 사용하게 되는데 프로젝트의 히스토리를 207 | 옮겨다닐 때 유용하게 사용할 수 있습니다. 'Git 프로젝트'의 1.6.6.1 버전을 컴파일 208 | 해보고 싶다면 git checkout v1.6.6.1 명령으로 소스를 Checkout하여 209 | 컴파일 하고, 그 결과 바이너리들을 설치해볼 수 있습니다(v1.6.6.1은 브랜치는 아니고 210 | 태그입니다). 그리고 나서 다시 git checkout main 명령으로 다른 211 | 브랜치로 변경할 수도 있습니다. detached HEAD에서 커밋을 하면 경우가 좀 212 | 달라지는데 아래에서 다시 살펴볼 것입니다.

213 | 214 |
215 | 216 |

Detached HEAD에서 커밋하기

217 | 218 |

detached HEAD에서의 커밋도 별반 다르지 않습니다. 다만 아무 219 | 브랜치도 업데이트되지 않는다는 것만 다를 뿐입니다. (익명의 브랜치라고 220 | 생각해볼 수 있습니다.)

221 | 222 |
223 | 224 |

detached HEAD에서 다른 브랜치로 변경하게 되면(예를 들어 225 | main 같은) detached HEAD의 커밋을 가리키는 어떤 이름도 226 | 갖지 못하게 되어 접근할 길을 잃고 맙니다. 아래 그림을 보면 브랜치를 227 | 변경 후 어떤 이름도 2eecb를 가리키고 있지 않습니다.

228 | 229 |
230 | 231 |

하지만 이 커밋을 가리키도록 새 브랜치를 만들 수 있는데 git checkout 232 | -b name 명령을 사용할 수 있습니다.

233 | 234 |
235 | 236 |

Reset

237 | 238 |

Reset 명령은 현재 브랜치가 가리키고 있는 커밋을 이동시킬 때 사용하며 239 | Stage 영역과 작업 디렉토리의 내용을 갱신합니다. 또한 실제 작업 디렉토리 240 | 내용을 변경하지 않은 채로 이전 커밋에서 파일을 Stage 영역으로 복사할 때에도 241 | 사용합니다.

242 | 243 |

파일 이름 없이 커밋만 지정하는 경우 브랜치가 해당 커밋을 가리키도록 244 | 변경합니다. Stage 영역 또한 해당 커밋에 맞게 갱신됩니다. --hard 245 | 옵션이 주어지면 작업 디렉토리 또한 갱신됩니다. --soft 옵션이 246 | 주어지면 작업디렉토리 및 Stage 영역 둘 다 갱신하지 않습니다.

247 | 248 |
249 | 250 |

커밋 이름이 지정되지 않으면 HEAD를 대신 사용합니다. 251 | 이 경우에는 브랜치가 가리키는 위치는 변경되지 않고 Stage 영역의 내용(또는 252 | --hard 옵션이 주어지면 작업 디렉토리 까지)이 가장 마지막 커밋의 253 | 내용으로 갱신됩니다.

254 | 255 |
256 | 257 |

파일 이름을 지정하면 (또는 -p 옵션을 사용하면) 258 | Checkout 명령과 비슷한 역할을 합니다. 다만 Stage 259 | 영역만 갱신된다는 점이 다릅니다. (어떤 시점의 커밋으로부터 파일을 갱신할 260 | 지 HEAD 대신 커밋 이름을 지정하여 선택할 수 있습니다.)

261 | 262 |
263 | 264 |

Merge

265 | 266 |

Merge 명령은 다른 커밋들을 하나로 합쳐서 새로운 커밋을 만듭니다. Merge 267 | 명령을 실행하기 전에 Stage 영역에 작업중인 파일이 없는지 꼭 확인해둡니다. 268 | Merge하는 경우 중 가장 간단한 경우는 Merge할 대상이 현재 커밋의 직접적인 269 | 뿌리가 되는 경우 인데, 이 때는 합칠 내용이 없습니다. 다음은 현재 커밋이 270 | Merge할 대상의 직접적인 뿌리가 되는 경우인데, 이 때는 fast-forward 271 | Merge가 실행되는데 간단히 가리키는 지점이 대상 커밋이 되고 대상 커밋의 272 | 내용을 Checkout 합니다.

273 | 274 |
275 | 276 |

이젠 진짜 Merge를 살펴볼 차례입니다. 다른 Merge 전략을 선택할 수도 있지만 277 | 기본적으로 Git은 재귀적인(Recursive) Merge 전략을 사용합니다. 이 전략은 278 | 현재 커밋(ed489), 대상이 되는 커밋(33104), 그리고 공통의 279 | 뿌리가 되는 커밋(b325c)을 가지고 280 | 3-way Merge를 281 | 수행합니다. Merge한 결과는 작업 디렉토리와 Stage 영역에 저장되며 부모가 282 | 여럿(33104, ed489)인 새 커밋을 만듭니다. 283 |

284 | 285 |
286 | 287 |

Cherry Pick(열매 고르기)

288 | 289 |

Cherry-pick 명령은 커밋을 하나 꺼내서 현재 작업중인 브랜치 마지막 부분에 290 | '복사'를 하면서 해당 커밋이 변경하는 부분을 적용하고 메시지나 저자 정보 등의 291 | 커밋 정보를 함께 저장합니다.

292 | 293 |
294 | 295 |

Rebase

296 | 297 |

여러 브랜치를 하나로 모으고자 할 때 Rebase 명령을 298 | Merge 명령 대신 사용할 수 있습니다. Merge 명령은 두 299 | 부모를 가지는 하나의 새 커밋을 만들기 때문에 히스토리가 직선적이지 않습니다. 300 | Rebase 명령을 사용하면 커밋들을 하나씩 순차적으로 적용해나가면서 히스토리를 301 | 직선으로 만들 수 있습니다. Cherry-pick 명령을 302 | 자동으로 한번에 수행하는 것이라고 보시면 됩니다.

303 | 304 |
305 | 306 |

위의 Rebase 명령은 topic 브랜치에만 포함되어 있는 모든 307 | 커밋들(169a62c33a)을 main 브랜치에 추가합니다. 308 | 커밋들을 추가하고 나서 topic 브랜치가 마지막 커밋을 가리키도록 309 | 이동시킵니다. Rebase하고 나서 더 이상 가리킬(Reference) 수 없는 커밋들은 310 | 쓰레기통으로 사라집니다.

311 | 312 |

--onto 옵션을 사용하면 Rebase에 사용할 커밋을 얼마나 오래 전 313 | 까지의 커밋을 사용할 지 제한할 수 있습니다. 314 | 아래 명령은 169a6 커밋 이후의 모든 커밋들(여기에서는 315 | 2c33a 커밋)을 main 브랜치에 적용시킵니다.

316 | 317 |
318 | 319 |

추가로 git rebase --interactive 명령이 있는데 간단히 커밋을 320 | 적용하는 것 이외에도 더 복잡한 기능, 커밋에 대해서 Namely Dropping, 321 | Reordering, Modifying, Squashing을 할 수 있습니다. 이해하기 쉽게 그릴 수 있는 322 | 그림이 없어 부득이 메뉴얼 문서 git-rebase(1) 링크를 드립니다.

324 | 325 |

기술적인 내용

326 | 327 |

파일의 실제 내용은 사실 Index(.git/index)나 커밋 개체(Commit 328 | Object)에 저장되는 것이 아니라, 개체 데이터베이스(Object Database, 329 | .git/objects)에 SHA-1 해시로 구분하여 blob형태로 저장이 330 | 됩니다. Index는 파일이름의 목록과 파일 blob을 가리키는 Hash를 331 | 저장하고 있습니다. 커밋에는 추가로 tree라는 형식의 데이터가 있는데 332 | 마찬가지로 Hash로 구분하고 디렉토리 구조를 담고 있습니다. 각 디렉토리는 333 | 포함된 파일 목록에 대한 tree 데이터를 담고 있습니다. 각 커밋은 334 | 가장 상위 디렉토리에 대한 tree 정보를 갖고 있어 커밋에 포함된 335 | 디렉토리 및 파일 정보를 접근할 수 있습니다.

336 | 337 |

detached HEAD에서 커밋을 만들게 되면 뭔가 만든 커밋을 가리킬 338 | 것이 필요한데 HEAD에 대한 reflog를 사용할 수 있습니다. 하지만 이 정보는 339 | 시간이 지나면 버려지기 때문에 결국 아무것도 가리키는 것이 없는 커밋은 340 | git commit --amend 명령이나 git rebase 명령으로 341 | 버려지는 커밋 처럼 버려지게 됩니다.

342 | 343 |

실습: 명령어들의 결과 확인

344 | 345 |

Visualizing Git 346 | Concepts with D3를 통해 git 명령어의 결과를 시각적으로 시뮬레이션하는 것처럼, 다음의 347 | 실습을 통해 저장소를 변경해 봄으로써 즉시 명령어의 결과를 확인해 볼 수 있습니다. 유용하게 348 | 사용되기를 바랍니다.

349 | 350 |

먼저 임의의 저장소를 생성합니다:

351 | 352 |
$ git init foo
353 | $ cd foo
354 | $ echo 1 > myfile
355 | $ git add myfile
356 | $ git commit -m "version 1"
357 | 
358 | 359 |

이제 편리하게 상태를 확인하기 위해 다음의 함수를 정의합니다:

360 | 361 |
show_status() {
362 |   echo "HEAD:     $(git cat-file -p HEAD:myfile)"
363 |   echo "Stage:    $(git cat-file -p :myfile)"
364 |   echo "Worktree: $(cat myfile)"
365 | }
366 | 
367 | initial_setup() {
368 |   echo 3 > myfile
369 |   git add myfile
370 |   echo 4 > myfile
371 |   show_status
372 | }
373 | 
374 | 375 |

처음에는 모든 것들의 version 1 상태입니다.

376 | 377 |
$ show_status
378 | HEAD:     1
379 | Stage:    1
380 | Worktree: 1
381 | 
382 | 383 |

add와 commit을 하면 상태가 변경됨을 확인 할 수 있습니다.

384 | 385 |
$ echo 2 > myfile
386 | $ show_status
387 | HEAD:     1
388 | Stage:    1
389 | Worktree: 2
390 | $ git add myfile
391 | $ show_status
392 | HEAD:     1
393 | Stage:    2
394 | Worktree: 2
395 | $ git commit -m "version 2"
396 | [main 4156116] version 2
397 |  1 file changed, 1 insertion(+), 1 deletion(-)
398 | $ show_status
399 | HEAD:     2
400 | Stage:    2
401 | Worktree: 2
402 | 
403 | 404 |

이제 실습을 위해 초기 상태를 만듭니다. 3가지가 모두 다른 상태입니다.

405 | 406 |
$ initial_setup
407 | HEAD:     2
408 | Stage:    3
409 | Worktree: 4
410 | 
411 | 412 |

이제 각 명령어가 어떤 역할을 하는지 확인합니다. 위에 설명된 다이어그램과 일치하는 것을 볼 수 413 | 있습니다.

414 | 415 |

git reset -- myfile은 HEAD에서 stage로 복사합니다:

416 | 417 |
$ initial_setup
418 | HEAD:     2
419 | Stage:    3
420 | Worktree: 4
421 | $ git reset -- myfile
422 | Unstaged changes after reset:
423 | M   myfile
424 | $ show_status
425 | HEAD:     2
426 | Stage:    2
427 | Worktree: 4
428 | 
429 | 430 |

git checkout -- myfile은 stage에서 worktree로 복사합니다:

431 | 432 |
$ initial_setup
433 | HEAD:     2
434 | Stage:    3
435 | Worktree: 4
436 | $ git checkout -- myfile
437 | $ show_status
438 | HEAD:     2
439 | Stage:    3
440 | Worktree: 3
441 | 
442 | 443 |

git checkout HEAD -- myfile은 HEAD에서 stage와 worketree 모두로 444 | 복사합니다:

445 | 446 |
$ initial_setup
447 | HEAD:     2
448 | Stage:    3
449 | Worktree: 4
450 | $ git checkout HEAD -- myfile
451 | $ show_status
452 | HEAD:     2
453 | Stage:    2
454 | Worktree: 2
455 | 
456 | 457 |

git commit myfile은 worktree에서 stage와 HEAD 모두로 복사합니다:

458 | 459 |
$ initial_setup
460 | HEAD:     2
461 | Stage:    3
462 | Worktree: 4
463 | $ git commit myfile -m "version 4"
464 | [main 679ff51] version 4
465 |  1 file changed, 1 insertion(+), 1 deletion(-)
466 | $ show_status
467 | HEAD:     4
468 | Stage:    4
469 | Worktree: 4
470 | 
471 | 472 |
473 | 474 |

Copyright © 2010, 475 | Mark Lodato. 476 | 한국어 번역 © 2011, 477 | Sean Lee. 478 |

479 | 480 |

483 | 이 저작물은 크리에이티브 485 | 커먼즈 저작자표시-비영리-동일조건변경허락 3.0 미국 라이선스에 따라 486 | 이용할 수 있습니다.

487 | 488 | 489 | 490 | -------------------------------------------------------------------------------- /index-pt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uma Referência Visual de Git 6 | 7 | 8 | 10 | 11 | 12 |

Uma Referência Visual do Git

13 | 14 |
15 | Outros Idiomas: 16 | 32 |
33 | 34 | 36 | 37 | 39 | 40 |

Esta página fornece uma breve referência visual para os comandos mais 41 | comuns do git. Uma vez que você saiba um pouco sobre como o git 42 | funciona, esta página pode consolidar o seu entendimento. Se você está 43 | interessado em saber como esta página foi criada, veja o meu repositório no 45 | GitHub.

46 | 47 |

Conteúdo

48 |
    49 |
  1. Uso Básico
  2. 50 |
  3. Convenções
  4. 51 |
  5. Comandos em Detalhe 52 |
      53 |
    1. Diff
    2. 54 |
    3. Commit
    4. 55 |
    5. Checkout
    6. 56 |
    7. Comitando com um HEAD detachado
    8. 57 |
    9. Reset
    10. 58 |
    11. Merge
    12. 59 |
    13. Cherry Pick
    14. 60 |
    15. Rebase
    16. 61 |
    62 |
  6. 63 |
  7. Observações Técnicas
  8. 64 |
65 | 66 |

Uso Básico

67 | 68 |
69 | 70 |

Os quatro comandos acima copiam arquivos entre o diretório de 71 | trabalho, o stage (também chamado de índice), e o histórico (na forma de 72 | commits).

73 | 74 |
    75 | 76 |
  • git add arquivos copia arquivos (em 77 | seus estados atuais) para o stage.
  • 78 | 79 |
  • git commit salva uma cópia do stage como um 80 | commit.
  • 81 | 82 |
  • git reset -- arquivos remove arquivos do 83 | stage; isto é, copia arquivos do último commit para o stage. 84 | Use esse comando para "desfazer" um git add 85 | arquivos. Você também pode executar git 86 | reset para remover todos os arquivos do stage.
  • 87 | 88 |
  • git checkout -- arquivos copia 89 | arquivos do stage para o diretório de trabalho. Use isso 90 | para descartar alterações locais.
  • 91 | 92 |
93 | 94 |

Você pode usar git reset -p, git checkout 95 | -p, ou git add -p em vez de (ou além de) especificar 96 | arquivos para selecionar interativamente partes de arquivos para 97 | copiar.

98 | 99 |

Também é possível passar por cima do stage e copiar (checkout) 100 | arquivos diretamente do histórico ou de commits sem copiar o aquivo para 101 | o stage.

102 | 103 |
104 | 105 |
    106 | 107 |
  • git commit -a é equivalente a executar git 108 | add em todos os arquivos que existiam no último commit, e 109 | então executar git commit.
  • 110 | 111 |
  • git commit arquivos cria um novo commit com 112 | o conteúdo do último commit, mais uma cópia de arquivos no 113 | diretório de trabalho. Além disso, os arquivos são copiados 114 | para o stage.
  • 115 | 116 |
  • git checkout HEAD -- arquivos copia os 117 | arquivos do último commit para ambos o stage e o diretório de 118 | trabalho.
  • 119 | 120 |
121 | 122 |

Convenções

123 | 124 |

No restante deste documento, nós vamos usar gráficos no seguinte 125 | formato.

126 | 127 |
128 | 129 |

commits são mostrados em verde com uma identidade de 5 caracteres, e 130 | eles apontam para os seus pais (parents). Os ramos (branches) são 131 | mostrados em laranja, e eles apontam para commits específicos. O ramo 132 | atual é identificado pela referência especial HEAD, que está 133 | unida àquele ramo. Nessa imagem, os últimos cinco commits são 134 | mostrados, sendo ed489 o mais recente. main (o ramo 135 | atual) aponta para esse commit, enquanto stable (outro ramo) 136 | aponta para um ancestral do commit do main. 137 | 138 |

Comandos em Detalhe

139 | 140 |

Diff

141 | 142 |

Existem várias formas de ver as diferenças entre commits. Abaixo 143 | estão alguns exemplos comuns. Qualquer desses comandos pode 144 | opcionalmente receber nomes de arquivos como argumentos que restringem as 145 | diferenças a esses arquivos.

146 | 147 |
148 | 149 |

Commit

150 | 151 |

Quando você comita, o git cria um novo commit usando os arquivos do 152 | stage e define os pais como o commit atual. Então ele aponta o ramo 153 | atual para esse novo commit. Na figura abaixo, o ramo atual é o 154 | main. Antes do comando ser executado, main 155 | apontava para ed489. Após, um novo commit, f0cec, foi 156 | criado, com ancestral ed489, e então main foi movido 157 | para o novo commit.

158 | 159 |
160 | 161 |

Esse mesmo processo ocorre também quando o ramo atual é um 162 | ancestral de outro ramo. Abaixo, um commit ocorre no ramo 163 | stable, o qual era um ancestral de main, resultando 164 | em 1800b. Após, stable não é mais um ancestral de 165 | main. Para juntar as duas histórias, um merge (ou rebase) será 167 | necessário.

168 | 169 |
170 | 171 |

As vezes um engano ocorre em um commit, mas isso é fácil de corrigir 172 | com git commit --amend. Quando você usa esse comando, o git 173 | cria um novo commit com os mesmos pais do commit atual. (O commit antigo 174 | será descartado se nada fizer referência a ele.)

175 | 176 |
177 | 178 |

Um quarto caso é comitar com o HEAD 179 | detachado, como explicado mais tarde.

180 | 181 |

Checkout

182 | 183 |

O comando checkout é usado para copiar arquivos do histórico, ou 184 | stage, para o diretório de trabalho, e opcionalmente mudar de ramo.

185 | 186 |

Quando um nome de arquivo (e/ou -p) é fornecido, o git 187 | copia esse arquivo do commit para o stage e para o diretório de trabalho. 188 | Por exemplo, git checkout HEAD~ foo.c copia o arquivo 189 | foo.c do commit chamado HEAD~ (os pais do commit 190 | atual) para o diretório de trabalho, e também para o stage. (Se nenhum 191 | commit é fornecido, os arquivos são copiados do stage.) Note que não há 192 | mudança no ramo.

193 | 194 |
195 | 196 |

Quando um nome de arquivo não é fornecido mas a referência é 197 | um ramo (local), HEAD é movido para aquele ramo (isto é, nós 198 | passamos para aquele ramo), e então o stage e o diretório de trabalho 199 | são modificados para coincidir com o conteúdo daquele commit. Qualquer 200 | arquivo que existe no novo commit (a47c3 abaixo) é copiado; 201 | qualquer arquivo que existe no antigo commit (ed489) mas não no 202 | novo commit é excluído; e qualquer arquivo que não existe em ambos é 203 | ignorado.

204 | 205 |
206 | 207 |

Quando um nome de arquivo não é fornecido e a referência 208 | não é um ramo (local) — por exemplo, é uma etiqueta 209 | (tag), um ramo remoto, uma identidade SHA-1, ou algo como 210 | main~3 — nós obtemos um ramo anônimo, chamado HEAD 211 | detachado. Isso é útil para se mover ao longo do histórico. Por 212 | exemplo, suponha que você queira compilar a versão 1.6.6.1 do git. Você 213 | poder executar git checkout v1.6.6.1 (que é uma etiqueta, 214 | não um ramo), compilar, instalar, e então passar de volta para outro 215 | ramo, por exemplo executado git checkout main. Todavia, 216 | efetuar um commit funciona um pouco diferente em um HEAD detachado; isso 217 | é discutido abaixo.

218 | 219 |
220 | 221 |

Comitando com um HEAD detachado

222 | 223 |

Quando o HEAD está detachado, comitar funciona da maneira 224 | usual, exceto que nenhum ramo com nome é modificado. (Você pode pensar 225 | nisso como um ramo anônimo.)

226 | 227 |
228 | 229 |

Uma vez que você fizer um checkout de alguma coisa, por exemplo 230 | main, o commit (presumivelmente) não recebe outra referência, 231 | e acaba excluído. Note que após o comando, não há nada fazendo 232 | referência para 2eecb.

233 | 234 |
235 | 236 |

Se, por outro lado, você quiser salvar esse estado, você pode criar 237 | um novo ramo com nome usando git checkout -b 238 | nome.

239 | 240 |
241 | 242 |

Reset

243 | 244 |

O comando reset move o ramo atual para uma nova posição, e 245 | opcionalmente atualiza o stage e o diretório de trabalho. Ele também é 246 | usado para copiar arquivos do histórico para o stage sem alterar o 247 | diretório de trabalho.

248 | 249 |

Se um commit é realizado sem um nome de arquivo, o ramo atual é 250 | movido para aquele commit, e então o stage é atualizado para coincidir 251 | com esse commit. Se --hard é fornecido, o diretório de 252 | trabalho também é atualizado. Se --soft é fornecido, 253 | nem o stage nem o diretório de trabalho são atualizados.

254 | 255 |
256 | 257 |

Se um commit não é fornecido, será usado o HEAD. Nesse 258 | caso, o ramo não é alterado, mas o stage, e opcionalmente o diretório de 259 | trabalho se --hard é fornecido, são atualizados com o 260 | conteúdo do último commit.

261 | 262 |
263 | 264 |

Se um nome de arquivo (e/ou -p) é fornecido, então o 265 | comando funciona similarmente ao comando checkout com um nome de arquivo, exceto que 267 | apenas o stage (e não o diretório de trabalho) é atualizado. (Você pode 268 | também especificar o commit a partir do qual copiar os arquivos, em vez 269 | de HEAD.)

270 | 271 |
272 | 273 |

Merge

274 | 275 |

Um merge cria um novo commit que incorpora mudanças de outros 276 | commits. Antes de executar um merge, o stage deve estar igual ao último 277 | commit. O caso trivial é quando o outro commit é um ancestral do commit 278 | atual; em tal caso nada ocorre. O próximo caso mais simples é quando o 279 | commit atual é um ancestral do outro commit. Isso resulta em um merge 280 | fast-forward. A referência é simplesmente movida, e então é 281 | efetuado um checkout do novo commit.

282 | 283 |
284 | 285 |

Caso contrário, um merge "real" deve ocorrer. Você pode selecionar 286 | outras estratégias, mas o padrão é efetuar um merge "recursivo", o qual 287 | basicamente considera o commit atual (ed489 abaixo), o outro 288 | commit (33104), e o ancestral comum a ambos (b325c), e 289 | efetua um merge 290 | three-way. O resultado é salvo no diretório de trabalho e no 291 | stage, e então um commit é executado, com um ancestral adicional 292 | (33104) para o novo commit.

293 | 294 |
295 | 296 |

Cherry Pick

297 | 298 |

O comando cherry-pick "copia" um commit, criando um novo commit no ramo 299 | atual com a mesma mensagem e modificações de outro commit.

300 | 301 |
302 | 303 |

Rebase

304 | 305 |

Um rebase é uma alternativa a um merge para 306 | combinar vários ramos. Enquanto um merge cria um único commit com dois 307 | pais, gerando um histórico não-linear, um rebase efetua os commits do 308 | ramo atual em outro ramo, gerando um histórico linear. Em essência, isso 309 | é uma forma automática de executar vários cherry-picks em sequência.

311 | 312 |
313 | 314 |

O comando acima considera todos os commits que existem em 315 | topic mas não em main (a saber 169a6 e 316 | 2c33a), executa esses commits em main, e então move 317 | o HEAD para o novo commit. Note que os commits antigos serão descartados 318 | se nada mais fizer referência a eles.

319 | 320 |

Para limitar quanto se quer ir para trás, use a opção 321 | --onto. O seguinte comando executa em main os 322 | commits mais recentes do ramo atual desde 169a6 323 | (exclusivamente), a saber 2c33a.

324 | 325 |
326 | 327 |

Existe também o comando git rebase --interactive, o qual 328 | permite fazer coisas mais complicadas do que simplesmente executar 329 | novamente commits, a saber, remover, reordenar, modificar, e "amassar" 330 | commits (squashing). Não existe uma figura clara para representar isso; 331 | veja git-rebase(1) 333 | para mais detalhes.

334 | 335 |

Observações técnicas

336 | 337 |

O conteúdo dos arquivos não é na verdade armazenado no index 338 | (.git/index) ou em objetos commit. Em vez disso, cada arquivo 339 | é armazenado na base-de-dados de objetos (.git/objects) como um 340 | blob, identificado pelo seu código hash SHA-1. O arquivo index 341 | lista os nomes de arquivos juntamente com o identificador do blob 342 | associado, bem como alguns outros dados. Para commits, existe um tipo de 343 | dado adicional, uma árvore, também identificado pelo seu código 344 | hash. Árvores correspondem aos diretórios no diretório de trabalho, e 345 | contém uma lista das árvores e blobs correspondentes a cada nome de 346 | arquivo naquele diretório. Cada commit armazena o identificador da sua 347 | árvore, que por sua vez contém todos os blobs e outras árvores 348 | associadas àquele commit.

349 | 350 |

Se você realiza um commit usando um HEAD detachado, o último commit é 351 | na verdade referenciado por algo: o reflog para o HEAD. Todavia, esse 352 | possui data de validade, logo em algum momento posterior o commit 353 | será finalmente excluído, de forma similar aos commits excluídos com 354 | git commit --amend ou git rebase.

355 | 356 |
357 | 358 |

Copyright © 2010, 359 | Mark Lodato. 360 | Portuguese translation © 2014, 361 | Gustavo de Oliveira 362 |

363 | 364 |

366 | 367 | Este trabalho está sob a licença 369 | Atribuição-NãoComercial-CompartilhaIgual 3.0 Estados Unidos.

370 | 371 |

Gostaria de traduzir para outro idioma?

372 | 373 | 374 | 375 | -------------------------------------------------------------------------------- /index-ru.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Git: наглядная справка 6 | 7 | 8 | 10 | 11 | 12 |

Git: наглядная справка

13 | 14 |
15 | На других языках: 16 | 32 |
33 | 34 | 36 | 37 | 39 | 40 |

На этой странице представлена краткая наглядная справка для наиболее часто 41 | используемых команд git. Если у вас уже есть небольшой опыт работы с git, 42 | эта страница поможет вам закрепить ваши знания. Если вам интересно, как был 43 | создан этот сайт, загляните на мой 44 | репозиторий на 45 | GitHub.

46 | 47 |

Содержание

48 |
    49 |
  1. Основные команды
  2. 50 |
  3. Соглашения
  4. 51 |
  5. Подробно о командах 52 |
      53 |
    1. Diff
    2. 54 |
    3. Commit
    4. 55 |
    5. Checkout
    6. 56 |
    7. Коммит из состояния «Detached HEAD»
    8. 57 |
    9. Reset
    10. 58 |
    11. Merge
    12. 59 |
    13. Cherry Pick
    14. 60 |
    15. Rebase
    16. 61 |
    62 |
  6. 63 |
  7. Технические заметки
  8. 64 |
65 | 66 |

Основные команды

67 | 68 |
69 | 70 |

Следующие четыре команды предназначены для копирования файлов между 71 | рабочей директорией, сценой, также известной как «индекс», и историей, 72 | представленной в форме коммитов.

73 | 74 |
    75 | 76 |
  • git add файлы копирует файлы в их 77 | текущем состоянии на сцену.
  • 78 | 79 |
  • git commit сохраняет снимок сцены в виде коммита.
  • 80 | 81 |
  • git reset -- файлы восстанавливает файлы на 82 | сцене, а именно копирует файлы из последнего коммита на сцену. 83 | Используйте эту команду для отмены изменений, внесённых командой 84 | git add файлы. Вы также можете выполнить 85 | git reset, чтобы восстановить все файлы на сцене.
  • 86 | 87 |
  • git checkout -- файлы копирует файлы со 88 | сцены в рабочую директорию. Эту команду удобно использовать, чтобы 89 | сбросить нежелательные изменения в рабочей директории.
  • 90 | 91 |
92 | 93 |

Вы можете использовать git reset -p, 94 | git checkout -p, и git add -p вместо имён файлов 95 | или вместе с ними, чтобы в интерактивном режиме выбирать, какие именно 96 | изменения будут скопированы.

97 | 98 |

Также можно перепрыгнуть через сцену и сразу же получить файлы из истории 99 | прямо в рабочую директорию или сделать коммит, минуя сцену.

100 | 101 |
102 | 103 |
    104 | 105 |
  • git commit -a аналогичен запуску двух команд: 106 | git add для всех файлов, которые существовали в предыдущем 107 | коммите, и git commit.
  • 108 | 109 |
  • git commit файлы создаёт новый коммит, в основе 110 | которого лежат уже существующие файлы, добавляя изменения только для 111 | указанных файлов. Одновременно, указанные файлы будут 112 | скопированы на сцену.
  • 113 | 114 |
  • git checkout HEAD -- файлы копирует 115 | файлы из текущего коммита и на сцену, и в рабочую 116 | директорию.
  • 117 | 118 |
119 | 120 |

Соглашения

121 | 122 |

Иллюстрации в этой справке выдержаны в единой цветовой схеме.

123 | 124 |
125 | 126 |

Коммиты раскрашены зелёным цветом и подписаны 5-ти буквенными 127 | идентификаторами. Каждый коммит указывает на своего родителя зелёной 128 | стрелочкой. Ветки раскрашены оранжевым цветом; ветки указывают на коммиты. 129 | Специальная ссылка HEAD указывает на текущую ветку. На иллюстрации 130 | вы можете увидеть последние пять коммитов. Самый последний коммит имеет хеш 131 | ed489. main (текущая ветка) указывает на этот коммит, 132 | stable (другая ветка) указывает на предка main-ового 133 | коммита.

134 | 135 |

Подробно о командах

136 | 137 |

Diff

138 | 139 |

Есть много способов посмотреть изменения между коммитами. Ниже вы 140 | увидите несколько простых примеров. К каждой из этих команд можно добавить 141 | имена файлов в качестве дополнительного аргумента. Так мы выведем 142 | информацию об изменениях только для перечисленных файлов.

143 | 144 |
145 | 146 |

Commit

147 | 148 |

Когда вы делаете коммит, git создаёт новый объект коммита, используя файлы 149 | со сцены, а текущей коммит становится родителем для нового. После этого 150 | указатель текущей ветки перемещается на новый коммит. Вы это видите на 151 | картинке, где main — это текущая ветка. До совершения коммита 152 | main указывал на коммит ed489. После добавления нового 153 | коммита f0cec, родителем которого стал ed489, указатель 154 | ветки main был перемещён на новый коммит.

155 | 156 |
157 | 158 |

То же самое происходит, если одна ветка является предком другой ветки. 159 | Ниже показан пример нового коммита 1800b в ветке stable, 160 | которая является предком ветки main. После этого ветка 161 | stable уже больше не является предком ветки main. И в 162 | случае необходимости объединения работы, проделанной в этих разделённых 163 | ветках, вам следует воспользоваться командой merge (что 164 | более предпочтительно) или rebase.

165 | 166 |
167 | 168 |

Если вы сделали ошибку в последнем коммите, её легко исправить с помощью 169 | команды git commit --amend. Эта команда создаёт новый коммит, 170 | родителем которого будет родитель ошибочного коммита. Старый ошибочный 171 | коммит будет отброшен, конечно же если только на него не будет ещё 172 | каких-либо других ссылок, что маловероятно.

173 | 174 |
175 | 176 |

Четвертый случай коммита из состояния «detached 177 | HEAD» будет рассмотрен далее.

178 | 179 |

Checkout

180 | 181 |

Команда checkout используется для копирования файлов из истории или сцены 182 | в рабочую директорию. Также она может использоваться для переключения между 183 | ветками.

184 | 185 |

Когда вы указываете имя файла (и/или ключ -p), git копирует 186 | эти файлы из указанного коммита на сцену и в рабочую директорию. Например, 187 | git checkout HEAD~ foo.c копирует файл foo.c 188 | из коммита HEAD~ (предка текущего коммита) в рабочую директорию и на 189 | сцену. Если имя коммита не указано, то файл будет скопирован со сцены в 190 | рабочую директорию. Обратите внимание на то, что при выполнении команды 191 | checkout позиция указателя текущей ветки (HEAD) остаётся 192 | прежней, указатель никуда не перемещается.

193 | 194 |
195 | 196 |

В том случае, если мы не указываем имя файла, но указываем имя 197 | локальной ветки, то указатель HEAD будет перемещён на эту ветку, то 198 | есть мы переключимся на эту ветку. При этом сцена и рабочая директория будут 199 | приведены в соответствие с этим коммитом. Любой файл, который присутствует в 200 | новом коммите (a47c3 ниже), будет скопирован из истории; любой файл, 201 | который был в старом коммите (ed489), но отсутствует в новом, будет 202 | удалён; любой файл, который не записан ни в одном коммите, будет 203 | проигнорирован.

204 | 205 |
206 | 207 |

В том случае, если мы не указываем имя файла, и 208 | не указываем имя локальной ветки, а указываем тег, дистанционную 209 | (remote) ветку, SHA-1 хеш коммита или что-то вроде main~3, то мы 210 | получаем безымянную ветку, называемую «Detached HEAD» (оторванная 211 | голова). Это очень полезная штука, если нам надо осмотреться в истории 212 | коммитов. К примеру, вам захочется скомпилировать git версии 1.6.6.1. Вы 213 | можете набрать git checkout v1.6.6.1 (это тег, не ветка), 214 | скомпилировать, установить, а затем вернуться в другую ветку, скажем 215 | git checkout main. Тем не менее, коммиты из состояния 216 | «Detached HEAD» происходят по своим особым важным правилам, и мы рассмотрим 217 | их ниже.

218 | 219 |
220 | 221 |

Коммит из состояния «Detached HEAD»

222 | 223 |

Когда мы находимся в состоянии оторванной головы 224 | (Detached HEAD), коммит совершается по тем же правилам, что и 225 | обычно, за исключением одной маленькой особенности: ни один указатель ветки 226 | не будет изменён или добавлен к новому коммиту. Вы можете представить эту 227 | ситуацию как работу с анонимной веткой.

228 | 229 |
230 | 231 |

Если после такого коммита вы переключитесь в ветку main, 232 | то коммит 2eecb, совершённый из состояния «Detached HEAD», 233 | потеряется и попросту будет уничтожен очередной сборкой мусора только потому, 234 | что нет ни одного объекта, который бы на него ссылался: ни ветки, ни 235 | тега.

236 | 237 |
238 | 239 |

В том случае, если вы хотите сохранить этот коммит на будущее, вы можете 240 | создать на основе него новую ветку командой 241 | git checkout -b new.

242 | 243 |
244 | 245 |

Reset

246 | 247 |

Команда reset перемещает указатель текущей ветки в другую позицию и 248 | дополнительно может обновить сцену и рабочую директорию. Эту команду можно 249 | также использовать для того, чтобы скопировать файл из истории на сцену, не 250 | задевая рабочую директорию.

251 | 252 |

Если коммит указан без имён файлов, указатель ветки будет перемещён на 253 | этот коммит, а затем сцена приведётся в соответствие с этим коммитом. Если 254 | мы используем ключ --soft, то сцена не будет изменена. Если мы 255 | используем ключ --hard, то будет обновлена и сцена, и рабочая 256 | директория.

257 | 258 |
259 | 260 |

Если имя коммита не будет указано, по умолчанию оно будет HEAD. 261 | В этом случае указатель ветки не будет перемещён, но сцена (а также и 262 | рабочая директория, если был использован ключ --hard) будет 263 | приведена к состоянию последнего коммита.

264 | 265 |
266 | 267 |

Если в команде указано имя файла (и/или ключ -p), то команда 268 | работает так же, как checkout с именем файла, за 269 | исключением того, что только сцена (но не рабочая директория) будет 270 | изменена. Если вы подставите имя коммита на место двойной черты, вы сможете 271 | получить состояние файла из этого коммита, тогда как в случае с двойной 272 | чертой вы получите состояние файла из коммита, на который указывает 273 | HEAD.

274 | 275 |
276 | 277 |

Merge

278 | 279 |

Команда merge (слияние) создает новый коммит на основе текущего коммита, 280 | применяя изменения других коммитов. Перед слиянием сцена должна быть 281 | приведена в соответствие с текущим коммитом. Самый простой случай слияния — 282 | это когда другой коммит является предком текущего коммита: в этом случае 283 | ничего не происходит. Другой простой случай слияния — когда текущий коммит 284 | является предком другого коммита: в этом случае происходит быстрая 285 | перемотка (fast-forward). Ссылка текущей ветки будет просто 286 | перемещена на новый коммит, а сцена и рабочая директория будут приведены в 287 | соответствие с новым коммитом.

288 | 289 |
290 | 291 |

Во всех других случаях выполняется «настоящее» слияние. Вы можете 292 | изменить стратегию слияния, но по умолчанию будет выполнено «рекурсивное» 293 | слияние, для которого будет взят текущий коммит (ed489 ниже на 294 | схеме), другой коммит (33104) и их общий предок (b325c); и 295 | для этих трех коммитов будет выполнено 296 | трёхстороннее 297 | слияние. Результат этого слияния будет записан в рабочую директорию и на 298 | сцену, и будет добавлен результирующий коммит со вторым родителем 299 | (33104).

300 | 301 |
302 | 303 |

Cherry Pick

304 | 305 |

Команда cherry-pick («вишенка в тортике») создаёт новый коммит на основе 306 | только одного сладкого «коммита-вишенки», применив все его изменения 307 | и сообщение.

308 | 309 |
310 | 311 |

Rebase

312 | 313 |

Перебазирование (rebase) — это альтернатива слиянию 314 | для задач объединения нескольких веток. Если слияние создаёт новый коммит с 315 | двумя родителями, оставляя нелинейную историю, то перебазирование применяет 316 | все коммиты один за одним из одной ветки в другую, оставляя за собой 317 | линейную историю коммитов. По сути это автоматическое выполнение нескольких 318 | команд cherry-pick подряд.

319 | 320 |
321 | 322 |

На схеме выше вы видите как команда берёт все коммиты, которые есть в 323 | ветке topic, но отсутствуют в ветке main (коммиты 324 | 169a6 and 2c33a), и воспроизводит их в ветке 325 | main. Затем указатель ветки перемещается на новое место. Следует 326 | заметить, что старые коммиты будут уничтожены сборщиком мусора, если на них 327 | уже ничего не будет ссылаться.

328 | 329 |

Используйте ключ --onto чтобы ограничить глубину захвата 330 | объединяемой ветки. На следующей схеме вы можете увидеть как в ветку 331 | main приходят лишь последние коммиты из текущей ветки, а именно 332 | коммиты после (но не включая) 169a6, т. е. 2c33a.

333 | 334 |
335 | 336 |

Есть также интерактивный режим перебазирования git rebase 337 | --interactive, с помощью которого вы сможете сделать вещи похитрее 338 | простого линейного применения коммитов, а именно сбрасывание (dropping), 339 | изменение порядка (reordering), правка (modifying) и выдавливание 340 | (squashing) коммитов. Нет наглядной схемы, чтобы показать эти возможности; 341 | за описанием лучше обратиться к справке по git-rebase(1).

343 | 344 |

Технические заметки

345 | 346 |

Содержание файлов не хранится в индексе (.git/index) или в 347 | объектах коммитов. Правильнее было бы сказать, что каждый файл хранится в 348 | базе данных объектов (.git/objects) в двоичном 349 | представлении; найти этот файл можно по его SHA-1 хешу. В файле индекса 350 | записаны имена файлов, их хеши и дополнительная информация. В информации о 351 | коммитах вы встретите тип данных дерево, для идентификации которого 352 | также используется SHA-1 хеш. Деревья описывают директории в рабочей 353 | директории, а также содержат информацию о других деревьях и файлах, 354 | принадлежащих обозначенному дереву. Каждый коммит хранит идентификатор 355 | своего верхнего дерева, которое содержит все файлы и другие деревья, 356 | изменённые в этом коммите.

357 | 358 |

Если вы делаете коммит из состояния «оторванной головы» (detached HEAD), 359 | то на этот коммит будет ссылаться ссылка истории HEAD. Но рано или поздно 360 | время хранения этой ссылки истечёт, и этот коммит будет уничтожен сборщиком 361 | мусора точно так же, как это делается при выполнении команд 362 | git commit --amend и git rebase.

363 | 364 |
365 | 366 |

Copyright © 2010, 367 | Mark Lodato. 368 | Russian translation © 2012, 369 | Alex Sychev. 370 |

371 | 372 |

375 | Это произведение доступно по лицензии 377 | Creative Commons Attribution-NonCommercial-ShareAlike (Атрибуция — 378 | Некоммерческое использование — С сохранением условий) 3.0 США.

379 | 380 | 381 | 382 | -------------------------------------------------------------------------------- /index-sk.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Príručka Visual Git 6 | 7 | 8 | 10 | 11 | 12 |

Príručka Visual Git

13 | 14 |
15 | Iné jazyky: 16 | 32 |
33 | 34 | 36 | 37 | 39 | 40 |

Táto stránka predstavuje stručnú vizuálnu príručku najpoužívanejších príkazov programu Git. 41 | Je určená k prehĺbeniu vášho pochopenia toho, ako Git funguje. Ak vás zaujíma to, ako bola táto stránka vytvorená, 42 | je vám k dispozícii môj repozitár na GitHub-e.

43 | 44 |

Poznámka k slovenskému prekladu: 45 | V texte je použitý výraz revízia na označenie konkrétnej verzie súborov uložených v histórii projektového archívu. 46 | Výraz komit potom označuje aktivitu vloženia novej revízie do histórie projektového archívu.

47 | 48 |

Obsah

49 |
    50 |
  1. Základné použitie
  2. 51 |
  3. Použité konvencie
  4. 52 |
  5. Podrobne o príkazoch 53 |
      54 |
    1. Rozdielová analýza (diff)
    2. 55 |
    3. Komitovanie (commit)
    4. 56 |
    5. Kopírovanie z archívu do pracovného adresára (checkout)
    6. 57 |
    7. Komitovanie s odpojenou hlavou (detached HEAD)
    8. 58 |
    9. Resetovanie (reset)
    10. 59 |
    11. Spájanie zmien (merge)
    12. 60 |
    13. Zbieranie čerešničiek (cherry-pick)
    14. 61 |
    15. Spájanie vetiev (rebase)
    16. 62 |
    63 |
  6. 64 |
  7. Technické poznámky
  8. 65 |
66 | 67 |

Základné použitie

68 | 69 |
70 | 71 |

Vyššie uvedené štyri príkazy umožňujú kopírovanie súborov medzi pracovným adresárom (working directory), predsieňou (index, stage) a projektovým archívom (history).

72 | 73 |
    74 | 75 |
  • git add súbory kopíruje súbory (v ich aktuálnej podobe) do predsiene.
  • 76 | 77 |
  • git commit uloží aktuálny stav súborov v predsieni (indexe) do projektového archívu (histórie) vo forme revízie.
  • 78 | 79 |
  • git reset -- súbory obnoví súbory v predieni; to znamená, že 80 | súbory sa skopírujú z najnovšej revízie do predsiene. Použite tento príkaz na vrátenie zmien spôsobených príkazom 81 | git add súbory. Na obnovenie celého obsahu v predsieni je tiež možné použiť príkaz git reset.
  • 82 | 83 |
  • git checkout -- súbory skopíruje súbory z predsiene do pracovného adresára. 84 | Týmto príkazom sa zahodia všetky lokálne zmeny (v pracovnom adresári).
  • 85 | 86 |
87 | 88 |

Prepínač príkazového riadku -p v príkazoch git reset -p, git checkout -p alebo 89 | git add -p namiesto definovania konkrétnych súborov (prípadne spolu s tým) umožní používateľovi interaktívny výber častí zmien, ktoré sa skopírujú.

90 | 91 |

Je tiež možné preskočiť predsieň a skopírovať súbory do pracovného adresára priamo z archívu alebo komitovať súbory bez predošlého vloženia do predsiene.

92 | 93 |
94 | 95 |
    96 | 97 |
  • git commit -a je rovnocenné s použitím príkazu git add 98 | s uvedením všetkých názvov súborov, ktoré boli súčasťou posledného komitu a následným spustením príkazu 99 | git commit.
  • 100 | 101 |
  • git commit súbory vytvorí novú revíziu obsahujúcu všetko z predchádzajúcej revízie 102 | plus aktuálny stav súborov z pracovného adresára. Súbory sa skopírujú navyše aj do predsiene.
  • 103 | 104 |
  • git checkout HEAD -- súbory skopíruje súbory 105 | z najnovšej revízie do predsiene i do pracovného adresára.
  • 106 | 107 |
108 | 109 |

Použité konvencie

110 | 111 |

V ďalších vysvetleniach budú použité grafy s nasledujúcim formátom.

112 | 113 |
114 | 115 |

Revízie sú zobrazené zelenou farbou ako 5-ciferné identifikátory, pričom odkazujú na svojich rodičov. 116 | Vetvy sú zobrazené oranžovou farbou, pričom odkazujú na konkrétne revízie. 117 | Aktuálna vetva je identifikovaná špeciálnym odkazom 118 | HEAD (hlava), ktorý je "pripojený" k tejto vetve. Na tomto obrázku je vyobrazených posledných päť revízií, kde najnovšou je revízia identifikovaná ako ed489. 119 | main (aktuálna vetva) odkazuje na túto revíziu, zatiaľ čo 120 | stable (iná vetva) odkazuje na jedného z predkov revízie vo vetve main.

121 | 122 |

Podrobne o príkazoch

123 | 124 |

Rozdielová analýza (diff)

125 | 126 |

Existujú rozličné spôsoby ako nazerať na rozdiely medzi revíziami. Nižšie uvádzame niektoré typické príklady. 127 | Rozsah porovnávania pri ktoromkoľvek z týchto príkazov je možné prostredníctvom dodatočného parametra súbory obmedziť na tieto uvedené súbory.

128 | 129 |
130 | 131 |

Komit (commit)

132 | 133 |

Keď komitujete, Git vytvorí nový objekt komitu (t.j. novú revíziu) použijúc súbory z predsiene, ktorému nastaví odkaz na rodiča na aktuálnu revíziu. 134 | Následne presmeruje odkaz aktuálnej vetvy na túto novú revíziu. Na obrázku nižšie je aktuálnou vetvou vetva 135 | main. Pred spustením príkazu odkazovala vetva main na 136 | ed489. Následne bola vytvorená nová revízia f0cec s rodičom ed489. 137 | Napokon sa odkaz vetvy main presunul na túto novú revíziu.

138 | 139 |
140 | 141 |

Rovnaký priebeh má dokonca i prípad, kedy aktuálna vetva je predkom inej. 142 | Nižšie je zobrazený komit na vetve stable, ktorá bola predkom vetvy main. 143 | Výsledkom je vznik revízie 1800b. Dôsledkom tohto komitu už vetva stable nie je viac predkom vetvy main. 144 | Na neskoršie spojenie zmien z takto vzniknutých dvoch línií histórie bude potrebné použiť príkaz merge (alebo rebase).

145 | 146 |
147 | 148 |

Niekedy sa pritrafí, že komit obsahuje chybu, čo sa však dá ľahko napraviť pomocou príkazu 149 | git commit --amend. Pri použití tohto príkazu, Git vytvorí novú revíziu s rovnakým rodičom ako má tá aktuálna. 150 | (Pôvodná aktuálna revízia bude zahodená, ak sa na ňu už nič viac neodkazuje.)

151 | 152 |
153 | 154 |

Štvrtým prípadom je komitovanie s odpojenou hlavou, čo objasníme neskôr.

155 | 156 |

Kopírovanie z archívu do pracovného adresára (checkout)

157 | 158 |

Príkaz git checkout sa používa na kopírovanie súborov z archívu (alebo z predsiene) do pracovného adresára a na prípadnú zmenu vetiev.

159 | 160 |

Keď sa uvedie názov súboru (a/alebo prepínač -p), Git skopíruje definované súbory z danej revízie 161 | do predsiene a pracovného adresára. Napríklad príkaz git checkout HEAD~ foo.c skopíruje súbor foo.c 162 | z revízie nazvanej HEAD~ (rodič aktuálnej revízie) do pracovného adresára a tiež do predsiene. 163 | (Ak sa neuvedie názov žiadnej revízie, súbory sa skopírujú z predsiene.) 164 | Všimnite si, že aktuálna vetva ostáva nezmenená.

165 | 166 |
167 | 168 |

Keď sa názov súboru neuvedie, ale odkazom je (lokálna) vetva, 169 | hlava (špeciálny odkaz HEAD) sa presunie do tejto vetvy (t.j. "prepneme sa" do tejto vetvy) 170 | a potom sa obsah predsiene i pracovného adresára upraví podľa obsahu aktuálnej revízie v tejto vetve. 171 | Všetky súbory, ktoré existujú v novšej revízii (a47c3 na obrázku nižšie), budú skopírované; akýkoľvek súbor, 172 | ktorý existuje v staršej revízii (ed489), avšak nie v novšej revízii, bude zmazaný; 173 | a akýkoľvek súbor, ktorý nie je súčasťou ani jednej z revízií, bude ignorovaný.

174 | 175 |
176 | 177 |

Keď sa názov súboru neuvedie a odkazom nie je 178 | (lokálna) vetva — povedzme, je to tag, vzdialená vetva, SHA-1 identifikátor revízie alebo referenčný výraz napr. ako 179 | main~3 — dostaneme anonymnú vetvu nazývanú odpojená hlava (detached HEAD). 180 | Toto je užitočné pri prechádzaní cez históriu v archíve. 181 | Povedzme, že chcete skompilovať Git, verziu 1.6.6.1. Môžete spustiť príkaz git checkout 182 | v1.6.6.1 (v tomto prípade ide o tag, nie o vetvu), skompilovať, nainštalovať a napokon sa prepnúť späť do inej vetvy, 183 | napríklad git checkout main. 184 | Komitovanie s odpojenou hlavou však funguje trochu odlišne; toto pokrýva odstavec nižšie.

185 | 186 |
187 | 188 |

Komitovanie s odpojenou hlavou (detached HEAD)

189 | 190 |

Pri odpojení hlavy (HEAD), komitovanie funguje ako obvykle s tým rozdielom, že žiadna pomenovaná vetva sa nezaktualizuje. 191 | (Môžete na to nazerať ako na anonymnú vetvu.)

192 | 193 |
194 | 195 |

Akonáhle skopírujete niektorú inú revíziu z archívu (prostredníctvom príkazu git checkout), napríklad z vetvy main, (je predpoklad, že) na pôvodnú revíziu 196 | už nič iné neodkazuje a táto sa teda stratí. Všimnite si, že po vykonaní príkazu už nič viac neodkazuje na revíziu 2eecb.

197 | 198 |
199 | 200 |

Na druhej strane, ak chcete uložiť tento stav, môžete vytvoriť novú pomenovanú vetvu pomocou príkazu git checkout -b názov-vetvy.

201 | 202 |
203 | 204 |

Resetovanie (reset)

205 | 206 |

Resetovací príkaz git reset presúva aktuálnu vetvu na inú pozíciu a prípadne aktualizuje predsieň a pracovný adresár. 207 | Používa sa tiež na kopírovanie súborov z archívu (z existujúcej revízie) do predsiene bezo zmeny obsahu pracovného adresára.

208 | 209 |

Ak sa uvedie len revízia bez názvov súborov, presunie sa aktuálna vetva na túto revíziu 210 | a následne sa na túto revíziu zaktualizuje aj obsah predsiene. Prepínač 211 | --hard spôsobí aktualizáciu aj pracovného adresára. Prepínač 212 | --soft zachová predsieň i pracovný adresár bezo zmien.

213 | 214 |
215 | 216 |

Neuvedenie revízie sa rovná použitiu špeciálneho odkazu hlava (HEAD). 217 | V tomto prípade sa vetva nepresúva, len obsah predsiene (príp. 218 | s použitím prepínača --hard aj pracovného adresára) sa skopíruje z poslednej revízie.

219 | 220 |
221 | 222 |

Ak sa uvedie názov súboru (a/alebo prepínač -p), 223 | potom príkaz pracuje podobne ako príkaz checkout s názvom súboru 224 | s tým, že sa zaktualizuje iba predsieň (pracovný adresár nie). 225 | (Je tiež možné uviesť revíziu, z ktorej sa má zobrať obsah súborov, inú než hlava (HEAD).)

226 | 227 |
228 | 229 |

Spájanie zmien (merge)

230 | 231 |

Príkaz vytvára novú revíziu, ktorá zahŕňa zmeny z iných revízií. 232 | Pred vykonaním príkazu musí obsah predsiene zodpovedať aktuálnej revízii. 233 | Triviálnym prípadom je ak spájaná revízia je predkom aktuálnej revízie - v tomto prípade sa neudeje nič. 234 | Ďalším najjednoduchším prípadom je ak aktuálna revízia je predkom spájanej revízie. 235 | Toto má za následok spojenie zmien pretočením dopredu (tzv. fast-forward merge), kedy je 236 | odkaz vetvy jednoducho presunutý s následným skopírovaním obsahu nového odkazu (t.j. spájanej revízie) do predsiene.

237 | 238 |
239 | 240 |

V iných prípadoch musí nastať "skutočné" spájanie. Môžete si zvoliť iné stratégie, avšak obvykle sa vykonáva "rekurzívne" spájanie, 241 | kedy sa v princípe vezme aktuálna revízia (ed489 na obrázku nižšie), spájaná revízia (33104) 242 | a ich najnovší spoločný predok (b325c) a vykoná sa trojcestné spájanie. 244 | Výsledok sa uloží do pracovného adresára i do predsiene. Následne nastane komit, pri ktorom vzniká nová revízia s pridaným dodatočným rodičom (33104).

245 | 246 |
247 | 248 |

Zbieranie čerešničiek (cherry-pick)

249 | 250 |

Príkaz git cherry-pick "zreplikuje" komit z inej vetvy do aktuálnej vetvy. V aktuálnej vetve pritom vznikne nová revízia s rovnakým popisom i obsahom ako má referencovaný komit.

251 | 252 |
253 | 254 |

Spájanie vetiev (rebase)

255 | 256 |

Spájanie vetiev je alternatívou k spájaniu zmien pre prípad zlučovania viacerých vetiev. 257 | Zatiaľ čo spájanie zmien (merge) vytvorí jednoduchú revíziu s dvomi rodičmi tvoriac nelineárnu históriu v archíve, 258 | spájanie vetiev (rebase) zreplikuje všetky komity z aktuálnej vetvy do inej vytvoriac lineárnu históriu v archíve. 259 | Vo svojej podstate sa v prípade spájania vetiev jedná o automatizovaný spôsob vykonania viacerých príkazov cherry-pick v rade za sebou.

261 | 262 |
263 | 264 |

Vyššie uvedený príkaz vezme všetky také revízie, ktoré existujú vo vetve topic, nie však vo vetve 265 | main (menovite 169a6 a 2c33a), zreplikuje ich do vetvy main 266 | a následne presunie hlavu vetvy na nový vrchol. 267 | Ak na staré revízie po vykonaní príkazu nič viac neodkazuje, budú tieto odstránené pomocou nástroja na odstraňovanie neplatných položiek 268 | (garbage collected).

269 | 270 |

Pre obmedzenie toho ako ďaleko do histórie sa vracať, použite prepínač --onto. 271 | Nasledujúci príkaz zreplikuje do vetvy main najnovšie komity z aktuálnej vetvy počnúc revíziou nasledujúcou po revízii 169a6, 272 | konkrétne revíziu 2c33a.

273 | 274 |
275 | 276 |

Existuje tiež interaktívny režim príkazu git rebase --interactive, ktorý umožňuje 277 | robiť zložitejšie veci než len jednoduché zreplikovanie komitov, konkrétne zrušenie, preusporiadanie, úpravu či zlučovanie komitov. 278 | Pre toto nie je k dispozícii žiaden zrejmý obrázok; v prípade záujmu o podrobnosti si preštudujte git-rebase(1).

280 | 281 |

Technické poznámky

282 | 283 |

Obsah súborov sa neuchováva priamo v predsieni 284 | (.git/index) alebo v objektoch komitov. Každý súbor sa nachádza v databáze objektov (.git/objects) vo formáte blob (binary large object), 285 | identifikovaný svojim SHA-1 hash-om. Indexový súbor (obsah predsiene) obsahuje zoznam názvov súborov spolu s identifikátorom pridruženého binárneho objektu blob a tiež ďalšie dáta. 286 | Pre revízie existuje dodatočný dátový typ strom, ktorý je rovnako identifikovaný svojim 287 | hash-om. 288 | Stromy zodpovedajú adresárom v pracovnom adresári a obsahujú zoznam stromov a blob-ov prislúchajúcich ku každému názvu súboru v tom adresári. 289 | Každá revízia má uložený identifikátor jeho stromu najvyššej úrovne, ktorý následne obsahuje všetky svoje blob-y a ostatné stromy naviazané na túto revíziu.

290 | 291 |

Ak vytvoríte revíziu pomocou odpojenej hlavy, na túto poslednú revíziu skutočne niečo odkazuje: 292 | tzv. reflog hlavy. Po nejakom čase však tento vyprší, takže túto revíziu napokon odstráni nástroj 293 | na odstraňovanie neplatných položiek, podobne ako pri revíziách po vykonaní príkazu git commit --amend alebo git 294 | rebase.

295 | 296 |
297 | 298 |

Copyright © 2010, 299 | Mark Lodato. 300 | Slovenský preklad © 2013, 301 | Ľudovít Lučenič. 302 |

303 | 304 |

307 | Toto dielo je licencované Creative 309 | Commons Attribution-Noncommercial-Share Alike 3.0 United States 310 | licenciou.

311 | 312 |

Want to translate into another 313 | language?

314 | 315 | 316 | 317 | -------------------------------------------------------------------------------- /index-vi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tham chiếu Git bằng hình ảnh 6 | 7 | 8 | 10 | 11 | 12 |

Tham chiếu Git bằng hình ảnh

13 | 14 |
15 | Ngôn ngữ khác: 16 | 32 |
33 | 34 | 36 | 37 | 39 | 40 |

Trang này đề cập đến tham chiếu bằng hình ảnh ngắn gọn cho các lệnh thông 41 | thường nhất được sử dụng trong git. Nếu bạn biết một chút về cách làm việc của 42 | git thì trang này có thể sẽ củng cố thêm sự hiểu biết của bạn. Nếu bạn quan 43 | tâm trang này được tạo ra như thế nào, mời xem 44 | GitHub repository 45 | của tôi.

46 | 47 |

Nội dung

48 |
    49 |
  1. Cách dùng cơ bản
  2. 50 |
  3. Quy ước
  4. 51 |
  5. Các lệnh chi tiết 52 |
      53 |
    1. Diff
    2. 54 |
    3. Commit
    4. 55 |
    5. Checkout
    6. 56 |
    7. Commit khi HEAD bị tách rời (detached)
    8. 57 |
    9. Reset
    10. 58 |
    11. Merge
    12. 59 |
    13. Cherry Pick
    14. 60 |
    15. Rebase
    16. 61 |
    62 |
  6. 63 |
  7. Ghi chú kỹ thuật
  8. 64 |
65 | 66 |

Cách dùng cơ bản

67 | 68 |
69 | 70 |

Bốn lệnh trên sao chép các tệp tin giữa thư mục làm việc (working directory), 71 | vùng chuyển tiếp (stage) - hay còn gọi là chỉ mục (index) và lịch sử (history) 72 | (dưới dạng các "commit").

73 | 74 |
    75 | 76 |
  • git add files sao chép các tệp tin (ở 77 | trạng thái hiện tại) tới vùng chuyển tiếp.
  • 78 | 79 |
  • git commit lưu trữ bản ghi của vùng chuyển tiếp thành một 80 | "commit".
  • 81 | 82 |
  • git reset -- files bỏ các tệp tin vào khu chuyển 83 | tiếp; cụ thể lệnh này sẽ sao chép các tệp tin từ "commit" mới nhất 84 | tới khu chuyển tiếp. Sử dụng lệnh này để "huỷ bỏ" (undo) lệnh git 85 | add files. Bạn cũng có thể sử dụng lệnh git 86 | reset để bỏ mọi thứ vào khu chuyển tiếp.
  • 87 | 88 |
  • git checkout -- files sao chép các tệp 89 | tin từ khu chuyển tiếp tới thư mục làm việc. Sử dụng lệnh này để bỏ hết 90 | những thay đổi hiện tại ở thư mục làm việc.
  • 91 | 92 |
93 | 94 |

Bạn có thể sử dụng git reset -p, git checkout -p, 95 | hoặc git add -p thay vì phải (hoặc phải làm thêm bước) chỉ rõ các 96 | tệp tin cụ thể để lựa chọn thực hiện thao tác với số lượng tệp tin lớn.

97 | 98 |

Cũng có thể bỏ qua khu chuyển tiếp và "check out" các tệp tin trực tiếp 99 | từ lịch sử hoặc "commit" các tệp tin mà không phải đưa vào vùng chuyển tiếp 100 | trước.

101 | 102 |
103 | 104 |
    105 | 106 |
  • git commit -a tương đương với việc chạy lệnh 107 | git add trên tất cả các tệp tin tồn tại trong "commit" mới nhất, 108 | sau đó chạy lệnh git commit.
  • 109 | 110 |
  • git commit files tạo một "commit" mới chứa nội dung 111 | của "commit" mới nhất, cùng với bản ghi các tệp tin được lấy từ thư 112 | mục làm việc. Ngoài ra, các tệp tin cũng được sao chép tới khu 113 | chuyển tiếp.
  • 114 | 115 |
  • git checkout HEAD -- files sap chép 116 | các tệp tin từ "commit" mới nhất tới cả hai khu chuyển tiếp và thư 117 | mục làm việc.
  • 118 | 119 |
120 | 121 |

Quy ước

122 | 123 |

Trong toàn bộ tài liệu này chúng ta sẽ sử dụng các biểu đồ có dạng như sau. 124 |

125 | 126 |
127 | 128 |

Các commit được biểu thị bằng màu xanh có các id là 5 ký tự và chúng trỏ 129 | tới commit cha. Các nhánh (branch) được biểu thị bằng màu cam và chúng trỏ tới 130 | các commit cụ thể. Nhánh hiện tại được xác định bằng tham chiếu đặc biệt 131 | HEAD được "gắn (attached)" vào nhánh đó. Trong hình này, có 5 132 | "commit" mới nhất được hiển thị, trong đó ed489 là commit mới nhất. 133 | Nhánh main (nhánh hiện tại) trỏ tới commit này, trong khi đó nhánh 134 | stable (một nhánh khác) trỏ tới "commit" tổ tiên (ancestor) của "commit" 135 | trên nhánh main

136 | 137 |

Các lệnh chi tiết

138 | 139 |

Diff

140 | 141 |

Có rất nhiều cách để so sánh sự khác biệt giữa các "commit". Dưới đây là một 142 | số ví dụ thông thường. Các lệnh này có thể tuỳ chọn truyền thêm các đối số là 143 | tên tập tin để giới hạn sự khác biệt chỉ trên những tệp tên được chỉ ra.

144 | 145 |
146 | 147 |

Commit

148 | 149 |

Khi bạn "commit", git tạo một đối tượng "commit" mới sử dụng các tệp tin từ 150 | khu chuyển tiếp và đặt "commit" hiện tại làm cha. Sau đó nó trỏ nhánh hiện tại 151 | tới "commit" mới này. Trong hình dưới đây, nhánh hiện tại là main. 152 | Trước khi lệnh được chạy, main trỏ tới ed489. Sau đó một 153 | "commit" mới, f0cec, được tạo với cha là ed489, và cuối cùng 154 | main được dịch chuyển đến "commit" mới.

155 | 156 |
157 | 158 |

Quá trình này cũng được thực hiện tương tự khi nhánh hiện tại là tổ tiên 159 | của nhánh khác. Theo hình dưới đây, một "commit" xảy ra tại nhánh 160 | stable, đây là nhánh tổ tiên của main, tạo thành 161 | 1800b. Sau đó, stable không còn là nhánh tổ tiên của 162 | main nữa. Để hợp hai lịch sử này cần dùng lệnh 163 | merge (hoặc rebase).

164 | 165 |
166 | 167 |

Đôi khi một "commit" bị lỗi, nhưng có thể dễ dàng sửa lỗi với 168 | git commit --amend. Khi bạn sử dụng lệnh này, git tạo ra một 169 | "commit" mới và lấy "commit" hiện tại làm cha. ("Commit" cũ sẽ bị 170 | loại bỏ nếu không có tham chiếu nào tới nó.)

171 | 172 |
173 | 174 |

Trường hợp thứ tư là "commit" khi HEAD bị tách rời 175 | sẽ được giải thích sau.

176 | 177 |

Checkout

178 | 179 |

Lệnh "checkout" được sử dụng để sao chép các tệp tin từ lịch sử (hay khu 180 | chuyển tiếp) tới thư mục làm việc, và có thể tuỳ chọn chuyển nhánh.

181 | 182 |

Khi chỉ ra tên tệp tin (và/hoặc -p), git sao chép các tệp tin 183 | này từ "commit" được chỉ định tới khu chuyển tiếp và thư mục làm việc. Ví dụ, 184 | git checkout HEAD~ foo.c sẽ sao chép tệp tin foo.c 185 | từ "commit" HEAD~ (cha của "commit" hiện tại) tới thư mục làm việc, 186 | và cũng đưa nó vào khu chuyển tiếp. (Nếu không chỉ ra tên của "commit", các 187 | tệp tin được sao chép từ khu chuyển tiếp.) Chú ý rằng nhánh hiện tại sẽ không 188 | có bất kỳ thay đổi gì.

189 | 190 |
191 | 192 |

Khi không chỉ ra tên tệp tin và tham chiếu là một nhánh nội 193 | vùng (local), HEAD được dịch chuyển tới nhánh đó (hay, hiểu theo cách 194 | khác là "chuyển sang" nhánh đó), và khi đó khu chuyển tiếp và thư mục làm việc 195 | được thiết lập khớp nội dung của "commit" đó. Bất kì tệp tin nào tồn tại trong 196 | "commit" mới (a47c3 theo hình phía dưới) sẽ được sao chép; bất kì tệp 197 | tin nào tồn tại trong "commit" cũ (ed489) nhưng không trong "commit" 198 | mới sẽ bị xoá bỏ; và bất kì tệp tin nào không tồn tại trong cả hai sẽ được bỏ 199 | qua.

200 | 201 |
202 | 203 |

Khi không chỉ ra tên tệp tin và tham chiếu không phải là 204 | nhánh nội vùng — có thể là một thẻ (tag), một nhánh ở xa (remote), 205 | một SHA-1 ID, hoặc có thể main~3 — chúng ta sẽ được chuyển 206 | qua nhánh vô danh (anonymous) và trường hợp này được gọi là HEAD bị tách 207 | rời. Trường hợp này rất hữu ích khi bạn muốn xem lịch sử. Ví dụ như bạn 208 | muốn biên dịch (compile) git phiên bản 1.6.6.1. Bạn có thể git checkout 209 | v1.6.6.1 (đây là thẻ, không phải nhánh), biên dịch, cài đặt (install), 210 | và sau đó chuyển tới một nhánh khác, có thể là git checkout main. 211 | Tuy nhiên, cách làm việc của "commit" hơi khác với HEAD bị tách rời; điều này 212 | sẽ được nói tới sau đây.

213 | 214 |
215 | 216 |

Commit khi HEAD bị tách rời

217 | 218 |

Khi HEAD bị tách rời, "commit" hoạt động như bình thường, ngoại 219 | trừ việc không có nhánh có tên cụ thể nào được cập nhật. (Bạn có thể coi đây 220 | là một nhánh vô danh.)

221 | 222 |
223 | 224 |

Một khi bạn "check out" cái gì khác, có thể main, "commit" đó 225 | (giả sử) không được tham chiếu ở bất kì đâu thì sẽ bị xoá bỏ. Chú ý rằng sau 226 | lệnh này, 2eecb không được tham chiếu từ bất kì đâu.

227 | 228 |
229 | 230 |

Mặt khác nếu bạn muốn lưu trữ trạng thái này, bạn có thể tạo một nhánh mới 231 | có tên cụ thể sử dụng lệnh git checkout -b name.

232 | 233 |
234 | 235 |

Reset

236 | 237 |

Lệnh "reset" sẽ chuyển nhánh hiện tại tới một vị trí khác, và có thể tuỳ chọn 238 | cập nhật khu chuyển tiếp và thư mục làm việc. Nó cũng được sử dụng để sao chép 239 | các tệp tin từ lịch sử tới khu chuyển tiếp mà không ảnh hưởng gì tới thư mục 240 | làm việc.

241 | 242 |

Nếu một "commit" được chỉ định mà không có tên các tệp tin, nhánh hiện tại 243 | sẽ được chuyển tới "commit" đó, và sau đó khu chuyển tiếp được cập nhật để 244 | khớp với "commit" này. Nếu --hard được cung cấp, thư mục làm việc 245 | cũng được cập nhật. Nếu --soft được cung cấp, cả hai đều không 246 | được cập nhật.

247 | 248 |
249 | 250 |

Nếu một "commit" không được chỉ định, "commit" mặc định là HEAD. 251 | Trong trường hợp này, nhánh không được chuyển dịch, nhưng khu chuyển tiếp (và 252 | có thể thư mục làm việc nếu --hard được cung cấp) được thiết lập 253 | lại với nội dung của "commit" mới nhất.

254 | 255 |
256 | 257 |

Nếu tên tệp tin (và/hoặc -p) được cung cấp thì lệnh này hoạt 258 | động tương tự checkout với tên tệp tin, ngoại trừ việc 259 | chỉ có khu chuyển tiếp (và không phải thư mục làm việc) được cập nhật. (Bạn 260 | cũng có thể chỉ rõ lấy các tệp tin từ "commit" cụ thể nào thay vì 261 | HEAD.)

262 | 263 |
264 | 265 |

Merge

266 | 267 |

Lệnh "merge" tạo một "commit" mới sáp nhập những thay đổi từ các "commit" 268 | khác. Trước khi tiến hành "merge", khu chuyển tiếp phải khớp với "commit" hiện 269 | tại. Có một trường hợp đặc biệt khi các "commit" khác là tổ tiên của "commit" 270 | hiện tại thì không xảy ra điều gì. Trường hợp khác đơn giản hơn là nếu 271 | "commit" hiện tại là tổ tiên của "commit" khác, khi đó sẽ tạo ra "fast-forward" 272 | "merge"và đơn giản chỉ dịch chuyển tham chiếu và "commit" mới được "check out".

273 | 274 |
275 | 276 |

Trong các trường hợp khác, "merge thực sự" phải xảy ra. Bạn có thể lựa 277 | chọn các chiến lược khác nhau nhưng mặc định sẽ phải thực hiện "merge đệ quy", 278 | về cơ bản sẽ lấy "commit" hiện tại (ed489), "commit" khác 279 | (33104), và tổ tiên chung (b325c), và sau đó thực hiện 280 | "merge ba-hướng". 281 | Kết quả được lưu trữ vào thư mục làm việc và khu chuyển tiếp, và sau đó thực 282 | hiện thêm một "commit" nữa và "commit" mới này tham chiếu thêm một "commit" 283 | cha (33104.)

284 | 285 |
286 | 287 |

Cherry Pick

288 | 289 |

Lệnh "cherry-pick" sẽ sao chép một "commit", tạo một "commit" mới trên 290 | nhánh hiện tại với nội dung giống hệt và "patch" thành một "commit" khác.

291 | 292 |
293 | 294 |

Rebase

295 | 296 |

Lệnh "rebase" là một lựa chọn khác thay vì "merge" để 297 | kết hợp nhiều nhánh khác nhau. Trong khi "merge" tạo một "commit" mới với hai 298 | cha và tạo ra lịch sử phi tuyến tính (non-linear) thì "rebase" tái tạo lại các 299 | "commit" từ nhánh hiện tại lên một nhánh khác và tạo ra lịch sử tuyến tính 300 | ("linear"). Về bản chất, đây là phương pháp thực hiện tự động các lệnh cherry-pick liên tiếp.

302 | 303 |
304 | 305 |

Lệnh trên lấy tất cả các "commit" tồn tại trong topic nhưng không 306 | có trong main, (các "commit" 169a62c33a), tái 307 | tạo lên main, và sau đó chuyển đầu nhánh tới đỉnh mới. Chú ý 308 | rằng các "commit" cũ sẽ bị xoá bỏ nếu chúng không được tham chiếu nữa.

309 | 310 |

Để giới hạn quay trở lại bao xa, sử dụng thêm --onto. Lệnh sau 311 | tái tạo lên main từ các "commit" mới nhất trên nhánh hiện tại tính 312 | từ 169a6 (không bao gồm), là "commit" 2c33a.

313 | 314 |
315 | 316 |

Cũng có thêm lệnh git rebase --interactive, lệnh này cho phép 317 | bạn thực hiện các thao tác phức tạp hơn thay vì đơn giản tái tạo lại các 318 | "commit", ví dụ như loại bỏ, sắp xếp lại, sửa đổi, và gộp nhóm (squash) các 319 | "commit". Rất khó để biểu diễn các thao tác này bằng hình ảnh; mời bạn xem git-rebase(1) để biết thêm chi tiết.

321 | 322 |

Chú ý kỹ thuật

323 | 324 |

Nội dung của các tệp tin thật ra không được lưu trữ trong chỉ mục (.git/index) 325 | hay trong các đối tượng "commit" mà mỗi tệp tin được lưu trữ trong cơ sở dữ 326 | liệu đối tượng (.git/objects) thành một blob, và được định 327 | danh bởi hàm băm SHA-1 của chính nó. Tệp tin chỉ mục liệt kê các tên tệp tin 328 | cùng với các định danh của "blob" tương ứng cùng với một số dữ liệu khác. Đối 329 | với các "commit", có thêm một kiểu dữ liệu nữa là tree cũng được định 330 | danh bởi hàm băm của nó. Các "tree" tương ứng với các thư mục trong thư mục 331 | làm việc và chứa danh sách các "tree" và "blob" tương ứng với mỗi tệp tin trong 332 | thư mục đó. Mỗi "commit" lưu định danh của "tree" mức đầu, điều đó có nghĩa nó 333 | chứa tất cả các "blob" và các "tree" khác liên quan tới "commit" đó.

334 | 335 |

Nếu bạn tạo một "commit" sử dụng HEAD bị tách rời, "commit" cuối thật ra 336 | được tham chiếu bởi cái được gọi là: "reflog" cho HEAD. Tuy nhiên, nó sẽ không 337 | có hiệu lực sau một khoảng thời gian nhất định, do đó cuối cùng "commit" sẽ bị 338 | xoá bỏ, tương tự như các "commit" bị xoá bỏ với git commit --amend 339 | hoặc git rebase.

340 | 341 |
342 | 343 |

Bản quyền © 2010, 344 | Mark Lodato. 345 | Bản dịch tiếng Việt © 2013, 346 | Hoat Le. 347 |

348 | 349 |

352 | Tài liệu được phát hành dưới giấy phép Creative 354 | Commons Attribution-Noncommercial-Share Alike 3.0 United States 355 | License.

356 | 357 |

Want to translate into another 358 | language?

359 | 360 | 361 | 362 | -------------------------------------------------------------------------------- /index-zh-cn.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 图解Git 6 | 7 | 8 | 10 | 11 | 12 |

图解Git

13 | 14 |
15 | 其他语言: 16 | 32 |
33 | 34 | 35 | 36 | 38 | 39 |

此页图解git中的最常用命令。如果你稍微理解git的工作原理,这篇文章能够让你理解的更透彻。 40 | 如果你想知道这个站点怎样产生,请前往GitHub 41 | repository

42 | 43 | 44 | 45 |

正文

46 |
    47 |
  1. 基本用法
  2. 48 |
  3. 约定
  4. 49 |
  5. 命令详解 50 |
      51 |
    1. Diff
    2. 52 |
    3. Commit
    4. 53 |
    5. Checkout
    6. 54 |
    7. Detached HEAD(匿名分支提交)
    8. 55 |
    9. Reset
    10. 56 |
    11. Merge
    12. 57 |
    13. Cherry Pick
    14. 58 |
    15. Rebase
    16. 59 |
    60 |
  6. 61 |
  7. 技术说明
  8. 62 |
63 | 64 |

基本用法

65 | 66 |
67 | 68 |

上面的四条命令在工作目录、暂存目录(也叫做索引)和仓库之间复制文件。

69 | 70 |
    71 | 72 |
  • git add files 把当前文件放入暂存区域。
  • 73 | 74 |
  • git commit 给暂存区域生成快照并提交。
  • 75 | 76 |
  • git reset -- files 用来撤销最后一次git add files,你也可以用git reset 77 | 撤销所有暂存区域文件。
  • 78 | 79 |
  • git checkout -- files 把文件从暂存区域复制到工作目录,用来丢弃本地修改。
  • 80 | 81 |
82 | 83 |

你可以用 git reset -p, git checkout -p, or 84 | git add -p进入交互模式。

85 | 86 |

也可以跳过暂存区域直接从仓库取出文件或者直接提交代码。

87 | 88 |
89 | 90 |
    91 | 92 |
  • git commit -a 相当于运行 git add 93 | 把所有当前目录下的文件加入暂存区域再运行。git commit.
  • 94 | 95 |
  • git commit files 进行一次包含最后一次提交加上工作目录中文件快照的提交。并且文件被添加到暂存区域。
  • 96 | 97 |
  • git checkout HEAD -- files 回滚到复制最后一次提交。
  • 98 | 99 |
100 | 101 |

约定

102 | 103 |

后文中以下面的形式使用图片。

104 | 105 |
106 | 107 |

绿色的5位字符表示提交的ID,分别指向父节点。分支用橘色显示,分别指向特定的提交。当前分支由附在其上的HEAD标识。 108 | 这张图片里显示最后5次提交,ed489是最新提交。 main分支指向此次提交,另一个stable分支指向祖父提交节点。

109 | 110 |

命令详解

111 | 112 |

Diff

113 | 114 |

有许多种方法查看两次提交之间的变动。下面是一些示例。

115 | 116 |
117 | 118 |

Commit

119 | 120 |

提交时,git用暂存区域的文件创建一个新的提交,并把此时的节点设为父节点。然后把当前分支指向新的提交节点。下图中,当前分支是main。 121 | 在运行命令之前,main指向ed489,提交后,main指向新的节点f0cec并以ed489作为父节点。

122 | 123 |
124 | 125 |

即便当前分支是某次提交的祖父节点,git会同样操作。下图中,在main分支的祖父节点stable分支进行一次提交,生成了1800b。 126 | 这样,stable分支就不再是main分支的祖父节点。此时,合并 (或者 衍合) 是必须的。

127 | 128 |
129 | 130 |

如果想更改一次提交,使用 git commit --amend。git会使用与当前提交相同的父节点进行一次新提交,旧的提交会被取消。

131 | 132 |
133 | 134 |

另一个例子是分离HEAD提交,后文讲。

135 | 136 |

Checkout

137 | 138 |

checkout命令用于从历史提交(或者暂存区域)中拷贝文件到工作目录,也可用于切换分支。

139 | 140 |

当给定某个文件名(或者打开-p选项,或者文件名和-p选项同时打开)时,git会从指定的提交中拷贝文件到暂存区域和工作目录。比如,git checkout HEAD~ foo.c会将提交节点HEAD~(即当前提交节点的父节点)中的foo.c复制到工作目录并且加到暂存区域中。(如果命令中没有指定提交节点,则会从暂存区域中拷贝内容。)注意当前分支不会发生变化。

141 | 142 |
143 | 144 |

当不指定文件名,而是给出一个(本地)分支时,那么HEAD标识会移动到那个分支(也就是说,我们“切换”到那个分支了),然后暂存区域和工作目录中的内容会和HEAD对应的提交节点一致。新提交节点(下图中的a47c3)中的所有文件都会被复制(到暂存区域和工作目录中);只存在于老的提交节点(ed489)中的文件会被删除;不属于上述两者的文件会被忽略,不受影响。

145 | 146 |
147 | 148 |

如果既没有指定文件名,也没有指定分支名,而是一个标签、远程分支、SHA-1值或者是像main~3类似的东西,就得到一个匿名分支,称作detached HEAD(被分离的HEAD标识)。这样可以很方便地在历史版本之间互相切换。比如说你想要编译1.6.6.1版本的git,你可以运行git checkout v1.6.6.1(这是一个标签,而非分支名),编译,安装,然后切换回另一个分支,比如说git checkout main。然而,当提交操作涉及到“分离的HEAD”时,其行为会略有不同,详情见在下面

149 | 150 |
151 | 152 |

HEAD标识处于分离状态时的提交操作

153 | 154 |

HEAD处于分离状态(不依附于任一分支)时,提交操作可以正常进行,但是不会更新任何已命名的分支。(你可以认为这是在更新一个匿名分支。)

155 | 156 |
157 | 158 |

一旦此后你切换到别的分支,比如说main,那么这个提交节点(可能)再也不会被引用到,然后就会被丢弃掉了。注意这个命令之后就不会有东西引用2eecb

159 | 160 |
161 | 162 |

但是,如果你想保存这个状态,可以用命令git checkout -b name来创建一个新的分支。

163 | 164 |
165 | 166 |

Reset

167 | 168 |

reset命令把当前分支指向另一个位置,并且有选择的变动工作目录和索引。也用来在从历史仓库中复制文件到索引,而不动工作目录。

169 | 170 |

如果不给选项,那么当前分支指向到那个提交。如果用--hard选项,那么工作目录也更新,如果用--soft选项,那么都不变。

171 | 172 |
173 | 174 |

如果没有给出提交点的版本号,那么默认用HEAD。这样,分支指向不变,但是索引会回滚到最后一次提交,如果用--hard选项,工作目录也同样。

175 | 176 |
177 | 178 |

如果给了文件名(或者 -p选项), 那么工作效果和带文件名的checkout差不多,除了索引被更新。

179 | 180 |
181 | 182 |

Merge

183 | 184 |

merge 命令把不同分支合并起来。合并前,索引必须和当前提交相同。如果另一个分支是当前提交的祖父节点,那么合并命令将什么也不做。 185 | 另一种情况是如果当前提交是另一个分支的祖父节点,就导致fast-forward合并。指向只是简单的移动,并生成一个新的提交。

186 | 187 |
188 | 189 |

否则就是一次真正的合并。默认把当前提交(ed489 如下所示)和另一个提交(33104)以及他们的共同祖父节点(b325c)进行一次三方合并。结果是先保存当前目录和索引,然后和父节点33104一起做一次新提交。 191 |

192 | 193 |
194 | 195 |

Cherry Pick

196 | 197 |

cherry-pick命令"复制"一个提交节点并在当前分支做一次完全一样的新提交。

198 | 199 |
200 | 201 |

Rebase

202 | 203 |

衍合是合并命令的另一种选择。合并把两个父分支合并进行一次提交,提交历史不是线性的。衍合在当前分支上重演另一个分支的历史,提交历史是线性的。 204 | 本质上,这是线性化的自动的 cherry-pick

205 | 206 |
207 | 208 |

上面的命令都在topic分支中进行,而不是main分支,在main分支上重演,并且把分支指向新的节点。注意旧提交没有被引用,将被回收。

209 | 210 |

要限制回滚范围,使用--onto选项。下面的命令在main分支上重演当前分支从169a6以来的最近几个提交,即2c33a

211 | 212 |
213 | 214 |

同样有git rebase --interactive让你更方便的完成一些复杂操作,比如丢弃、重排、修改、合并提交。没有图片体现这些,细节看这里:git-rebase(1)

216 | 217 |

技术说明

218 | 219 |

文件内容并没有真正存储在索引(.git/index)或者提交对象中,而是以blob的形式分别存储在数据库中(.git/objects),并用SHA-1值来校验。 220 | 索引文件用识别码列出相关的blob文件以及别的数据。对于提交来说,以树(tree)的形式存储,同样用对于的哈希值识别。树对应着工作目录中的文件夹,树中包含的 221 | 树或者blob对象对应着相应的子目录和文件。每次提交都存储下它的上一级树的识别码。

222 | 223 |

如果用detached HEAD提交,那么最后一次提交会被the reflog for HEAD引用。但是过一段时间就失效,最终被回收,与git commit --amend或者git 224 | rebase很像。

225 | 226 |
227 | 228 |

Copyright © 2010, 229 | Mark Lodato. 230 | Chinese translation © 2012, 231 | wych. 232 |

233 | 234 |

本著作系采用创用CC 姓名标示-非商业性-相同方式分享3.0 美国授权条款授权。

235 | 236 | 237 | 238 | -------------------------------------------------------------------------------- /index-zh-tw.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 圖解Git 6 | 7 | 8 | 10 | 11 | 12 |

圖解Git

13 | 14 |
15 | 其他語言: 16 | 32 |
33 | 34 | 35 | 36 | 38 | 39 |

此頁圖解git中的最常用命令。如果你稍微理解git的工作原理,這篇文章能夠讓你理解的更透徹。 40 | 如果你想知道這個網站怎樣產生,請前往GitHub 41 | repository

42 | 43 | 44 | 45 |

正文

46 |
    47 |
  1. 基本使用
  2. 48 |
  3. 規範
  4. 49 |
  5. 命令詳解 50 |
      51 |
    1. Diff
    2. 52 |
    3. Commit
    4. 53 |
    5. Checkout
    6. 54 |
    7. Detached HEAD(匿名分支提交)
    8. 55 |
    9. Reset
    10. 56 |
    11. Merge
    12. 57 |
    13. Cherry Pick
    14. 58 |
    15. Rebase
    16. 59 |
    60 |
  6. 61 |
  7. 技術說明
  8. 62 |
63 | 64 |

基本使用

65 | 66 |
67 | 68 |

上面的四條命令在工作目錄、暫存目錄(也叫做索引)和倉庫之間複製檔案。

69 | 70 |
    71 | 72 |
  • git add files 把指定檔案放入暫存區域。
  • 73 | 74 |
  • git commit 給暫存區域產生快照並提交。
  • 75 | 76 |
  • git reset -- files 用來撤銷最後一次git add files,你也可以用git reset 77 | 撤銷所有暫存區域檔案。
  • 78 | 79 |
  • git checkout -- files 把檔從暫存區域複製到工作目錄,用來放棄本地修改。
  • 80 | 81 |
82 | 83 |

你可以用 git reset -p, git checkout -p, or 84 | git add -p進入互動模式。

85 | 86 |

也可以跳過暫存區域直接從倉庫取出檔案或者直接提交代碼。

87 | 88 |
89 | 90 |
    91 | 92 |
  • git commit -a 相當於執行 git add 93 | 把所有目前的目錄下的檔加入暫存區域再執行。git commit.
  • 94 | 95 |
  • git commit files 進行一次包含最後一次提交加上工作目錄中檔快照的提交。並且檔被添加到暫存區域。
  • 96 | 97 |
  • git checkout HEAD -- files 回滾到複製最後一次提交。
  • 98 | 99 |
100 | 101 |

規範

102 | 103 |

後文中以下面的形式使用圖片。

104 | 105 |
106 | 107 |

綠色的5位元字元表示提交的ID,分別指向父節點。分支用橘色顯示,分別指向特定的提交。目前分支由附在其上的HEAD標識。 108 | 這張圖片裡顯示最後5次提交,ed489是最新提交。 main分支指向此次提交,另一個stable分支指向祖父提交節點。

109 | 110 |

命令詳解

111 | 112 |

Diff

113 | 114 |

有許多種方法查看兩次提交之間的變動。下面是一些範例。

115 | 116 |
117 | 118 |

Commit

119 | 120 |

提交時,git用暫存區域的檔建立一個新的提交,並把此時的節點設為父節點。然後把目前分支指向新的提交節點。下圖中,目前分支是main。 121 | 在執行命令之前,main指向ed489,提交後,main指向新的節點f0cec並以ed489作為父節點。

122 | 123 |
124 | 125 |

即便目前分支是某次提交的祖父節點,git會同樣操作。下圖中,在main分支的祖父節點stable分支進行一次提交,產生了1800b。 126 | 這樣,stable分支就不再是main分支的祖父節點。此時,合併 (或者 衍合) 是必須的。

127 | 128 |
129 | 130 |

如果想更改一次提交,使用 git commit --amend。git會使用與目前提交相同的父節點進行一次新提交,舊的提交會被取消。

131 | 132 |
133 | 134 |

另一個例子是分離HEAD提交,後文講。

135 | 136 |

Checkout

137 | 138 |

checkout命令用於從歷史提交(或者暫存區域)中拷貝檔到工作目錄,也可用於切換分支。

139 | 140 |

當給定某個檔案名(或者打開-p選項,或者檔案名和-p選項同時打開)時,git會從指定的提交中拷貝檔到暫存區域和工作目錄。比如,git checkout HEAD~ foo.c會將提交節點HEAD~(即目前提交節點的父節點)中的foo.c複製到工作目錄並且加到暫存區域中。(如果命令中沒有指定提交節點,則會從暫存區域中拷貝內容。)注意目前分支不會發生變化。

141 | 142 |
143 | 144 |

當不指定檔案名,而是給出一個(本地)分支時,那麼HEAD標識會移動到那個分支(也就是說,我們“切換”到那個分支了),然後暫存區域和工作目錄中的內容會和HEAD對應的提交節點一致。新提交節點(下圖中的a47c3)中的所有檔都會被複製(到暫存區域和工作目錄中);只存在於老的提交節點(ed489)中的文件會被刪除;不屬於上述兩者的檔會被忽略,不受影響。

145 | 146 |
147 | 148 |

如果既沒有指定檔案名,也沒有指定分支名,而是一個標籤、遠端分支、SHA-1值或者是像main~3類似的東西,就得到一個匿名分支,稱作detached HEAD(被分離的HEAD標識)。這樣可以很方便地在歷史版本之間互相切換。比如說你想要編譯1.6.6.1版本的git,你可以執行git checkout v1.6.6.1(這是一個標籤,而非分支名),編譯,安裝,然後切換回另一個分支,比如說git checkout main。然而,當提交操作涉及到“分離的HEAD”時,其行為會略有不同,詳情見在下面

149 | 150 |
151 | 152 |

HEAD標識處於分離狀態時的提交操作

153 | 154 |

HEAD處於分離狀態(不依附于任一分支)時,提交操作可以正常進行,但是不會更新任何已命名的分支。(你可以認為這是在更新一個匿名分支。)

155 | 156 |
157 | 158 |

一旦此後你切換到別的分支,比如說main,那麼這個提交節點(可能)再也不會被引用到,然後就會被放棄掉了。注意這個命令之後就不會有東西引用2eecb

159 | 160 |
161 | 162 |

但是,如果你想保存這個狀態,可以用命令git checkout -b name來建立一個新的分支。

163 | 164 |
165 | 166 |

Reset

167 | 168 |

reset命令把目前分支指向另一個位置,並且有選擇的變動工作目錄和索引。也用來在從歷史倉庫中複製檔到索引,而不動工作目錄。

169 | 170 |

如果不給選項,那麼目前分支指向到那個提交。如果用--hard選項,那麼工作目錄也更新,如果用--soft選項,那麼都不變。

171 | 172 |
173 | 174 |

如果沒有給出提交點的版本號,那麼預設用HEAD。這樣,分支指向不變,但是索引會回溯到最後一次提交,如果用--hard選項,工作目錄也同樣。

175 | 176 |
177 | 178 |

如果給了檔案名(或者 -p選項), 那麼工作效果和帶檔案名的checkout差不多,除了索引被更新。

179 | 180 |
181 | 182 |

Merge

183 | 184 |

merge 命令把不同分支合併起來。合併前,索引必須和目前提交相同。如果另一個分支是目前提交的祖父節點,那麼合併命令將什麼也不做。 185 | 另一種情況是如果目前提交是另一個分支的祖父節點,就會導致fast-forward合併。指向只是簡單的移動,並產生一個新的提交。

186 | 187 |
188 | 189 |

否則就是一次真正的合併。預設把目前提交(ed489 如下所示)和另一個提交(33104)以及他們的共同祖父節點(b325c)進行一次三方合併。結果是先保存目前的目錄和索引,然後和父節點33104一起做一次新提交。 191 |

192 | 193 |
194 | 195 |

Cherry Pick

196 | 197 |

cherry-pick命令"複製"一個提交節點並在目前的分支做一次完全一樣的新提交。

198 | 199 |
200 | 201 |

Rebase

202 | 203 |

衍合是合併命令的另一種選擇。合併把兩個父分支合併進行一次提交,提交歷史不是線性的。衍合在目前分支上重演另一個分支的歷史,提交歷史是線性的。 204 | 本質上,這是線性化的自動的 cherry-pick

205 | 206 |
207 | 208 |

上面的命令都在topic分支中進行,而不是main分支,在main分支上重演,並且把分支指向新的節點。注意舊提交沒有被引用,將被回收。

209 | 210 |

要限制回滾範圍,使用--onto選項。下面的命令在main分支上重演目前分支從169a6以來的最近幾個提交,即2c33a

211 | 212 |
213 | 214 |

同樣有git rebase --interactive讓你更方便的完成一些複雜操作,比如放棄、重排、修改、合併提交。沒有圖片體現這些,細節看這裡:git-rebase(1)

216 | 217 |

技術說明

218 | 219 |

檔案內容並沒有真正存儲在索引(.git/index)或者提交物件中,而是以blob的形式分別存儲在資料庫中(.git/objects),並用SHA-1值來校驗。 220 | 索引檔用識別碼列出相關的blob檔以及別的資料。對於提交來說,以樹(tree)的形式存儲,同樣用對於的雜湊值識別。樹對應著工作目錄中的資料夾,樹中包含的 221 | 樹或者blob物件對應著相應的子目錄和檔案。每次提交都存儲下它的上一級樹的識別碼。

222 | 223 |

如果用detached HEAD提交,那麼最後一次提交會被the reflog for HEAD引用。但是過一段時間就失效,最終被回收,與git commit --amend或者git 224 | rebase很像。

225 | 226 |
227 | 228 |

Copyright © 2010, 229 | Mark Lodato. 230 | Traditional Chinese translation © 2015, 231 | Peter Dave Hello. 232 |

233 | 234 |

本著作系採用創用CC 姓名標示-非商業性-相同方式分享3.0 美國授權條款授權。

235 | 236 | 237 | 238 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | A Visual Git Reference 6 | 7 | 8 | 9 |

Available languages:

10 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /merge-ff.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \refbelow [branch] "main" : main -> E; 7 | \oldbranch stable -> A; 8 | \branch stable -> E; 9 | \oldHEAD -> old stable; 10 | \HEAD -> stable; 11 | 12 | \node [cmd] at (0, 3.75) {git merge main}; 13 | 14 | \path [line] 15 | (E) edge [bend right=5] (index.north east) 16 | (E) edge [bend right=15] (work.north east) 17 | (old HEAD) edge [dashed, bend left=10] (HEAD) 18 | ; 19 | 20 | \end{tikzpicture} 21 | \end{document} 22 | -------------------------------------------------------------------------------- /merge.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \normalcommits 6 | \indexnode[2,-3] 7 | \worknode[-2,-3] 8 | \commit 2eecb (2) -> B; 9 | \commit 33104 (3) -> 2; 10 | \branch other -> 3; 11 | 12 | % draw the old branch manually with a long line 13 | \node [old branch, above=1 of E] (old main) {main}; 14 | \path [old branch line] (old main) edge (E); 15 | \node [cancel ref, above=.2\g of E, anchor=center] {}; 16 | \oldHEAD -> old main; 17 | 18 | \newcommit f8bc5 (F) -> E; 19 | \branch main -> F; 20 | \HEAD -> main; 21 | \path [background line, bend right=15] (F) edge[-] (3); 22 | \path [commit line, bend right=15] (F) edge (3); 23 | 24 | \node [cmd] at (0, 3.75) {git merge other}; 25 | 26 | \node [inner sep=8\gLine] (merge) at (0,-1) {3-way merge}; 27 | 28 | \path [background line] 29 | (3) edge [-, bend right=15] (merge) 30 | ; 31 | \path [line] 32 | (3) edge [bend right=15] (merge) 33 | (B) edge [bend right=37] (merge) 34 | (E) edge [bend left=20] (merge) 35 | (merge) edge [bend right=10] (index) 36 | (merge) edge [bend left=10] (work) 37 | (index) edge [bend right=35] node [near start] {(if no conflicts)} (F) 38 | (old HEAD label) edge [dashed, bend left=35] (HEAD) 39 | ; 40 | 41 | \end{tikzpicture} 42 | \end{document} 43 | -------------------------------------------------------------------------------- /rebase-onto.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \indexnode 6 | \worknode 7 | \commitTerminal cT at (-6,.75); 8 | \commit a47c3 (A) -> cT; 9 | \commit b325c (B) -> A; 10 | \commit c10b9 (C) -> B; 11 | \commit da985 (D) -> C; 12 | \newcommit e918c (E) -> D; 13 | \commit 169a6 (1) -> A; 14 | \commit 2c33a (2) -> 1; 15 | 16 | \oldbranch topic -> 2; 17 | \oldHEAD -> old topic; 18 | \branch main -> D; 19 | \branch topic -> E; 20 | \HEAD -> topic; 21 | 22 | \node [cmd,right] at (1, 3.75) {git rebase --onto main 169a6}; 23 | 24 | \path [line] 25 | (E) edge [bend left=20] (index) 26 | (E) edge [bend left=30] (work) 27 | (old HEAD label) edge [dashed, bend left=10] (HEAD label) 28 | (2) edge [loosely dashed, bend right=40] (E) 29 | ; 30 | 31 | \end{tikzpicture} 32 | \end{document} 33 | -------------------------------------------------------------------------------- /rebase.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \indexnode 6 | \worknode 7 | \commitTerminal cT at (-6,.75); 8 | \commit a47c3 (A) -> cT; 9 | \commit b325c (B) -> A; 10 | \commit c10b9 (C) -> B; 11 | \commit da985 (D) -> C; 12 | \newcommit e57cf (E) -> D; 13 | \newcommit f7e63 (F) -> E; 14 | \commit 169a6 (1) -> A; 15 | \commit 2c33a (2) -> 1; 16 | 17 | \oldbranch topic -> 2; 18 | \oldHEAD -> old topic; 19 | \branch main -> D; 20 | \branch topic -> F; 21 | \HEAD -> topic; 22 | 23 | \node [cmd,right] at (1, 3.75) {git rebase main}; 24 | 25 | \path [line] 26 | (F) edge [bend left=20] (index) 27 | (F) edge [bend left=30] (work) 28 | (old HEAD label) edge [dashed, bend left=10] (HEAD label) 29 | (1) edge [loosely dashed, bend right=35] (E) 30 | (2) edge [loosely dashed, bend left=30] (F) 31 | ; 32 | 33 | \end{tikzpicture} 34 | \end{document} 35 | -------------------------------------------------------------------------------- /reset-commit.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \branch stable -> A; 7 | \oldbranch main -> E; 8 | \branch main -> B; 9 | \oldHEAD -> old main; 10 | \HEAD -> main; 11 | 12 | \node [cmd] at (0, 3.75) {git reset HEAD\~{}3}; 13 | 14 | \path [line, auto=left] 15 | (B) edge [bend right=20] node [near end] 16 | {(if not \texttt{--soft})} (index) 17 | (B) edge [bend right=40] node [swap] {(if \texttt{--hard})} (work) 18 | (old HEAD) edge [dashed, bend right=15] (HEAD) 19 | ; 20 | 21 | \end{tikzpicture} 22 | \end{document} 23 | -------------------------------------------------------------------------------- /reset-files.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \branch main -> E; 7 | \branch stable -> A; 8 | \HEAD -> main; 9 | 10 | \node [cmd] (cmd1) at (0, 3.75) {git reset -- \emph{files}}; 11 | 12 | \path [line] 13 | (E) edge [bend left=20] (index) 14 | ; 15 | 16 | \end{tikzpicture} 17 | \end{document} 18 | -------------------------------------------------------------------------------- /reset.tex: -------------------------------------------------------------------------------- 1 | \input{common.tex} 2 | \begin{document} 3 | \begin{tikzpicture}[main] 4 | \boundingbox 5 | \usualsetup 6 | \branch main -> E; 7 | \branch stable -> A; 8 | \HEAD -> main; 9 | 10 | \node [cmd] (cmd1) at (0, 3.75) {git reset}; 11 | 12 | \path [line, auto=left] 13 | (E) edge [bend left=20] (index) 14 | (E) edge [bend left=30] node {(if \texttt{--hard})} (work) 15 | ; 16 | 17 | \end{tikzpicture} 18 | \end{document} 19 | -------------------------------------------------------------------------------- /translate-en.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Translating "A Visual Git Reference" 6 | 7 | 9 | 10 | 11 |

Translating A Visual Git Reference

12 | 13 |

Thanks to kindness of others, A Visual Git 14 | Reference has been translated from English into several other 15 | languages. If you would like to translate it into your native language, I 16 | would be happy to receive your patch! Please follow the below guide to get 17 | you started.

18 | 19 |
    20 |
  1. Fork MarkLodato/visual-git-guide 21 | on Github.
  2. 22 |
  3. Clone your fork.
  4. 23 |
  5. Translate the work, following the same scheme as the other languages. 24 | Be sure to remember to add your name to the copyright notice in README.md 25 | and index-en.html. There are more steps, but if you don't follow them, 26 | don't worry—I'll take care of the rest.
  6. 27 |
  7. Commit and push your changes back to Github repository.
  8. 28 |
  9. Submit a pull request via the Github website.
  10. 29 |
30 | 31 |

The nitty-gritty

32 | 33 |

I'll take care of these details if you don't want to worry about them, 34 | but here they are in case you are interested:

35 | 36 |
    37 |
  1. Add your name to the bottom of the copyright notice in README.md and 38 | index-en.html.
  2. 39 |
  3. Add a link from index.html to index-LANG.html, where 40 |
  4. Add index-LANG.html to the HTML Makefile 41 | variable.
  5. 42 |
  6. Copy index-en.html to index-LANG.html. 43 |
  7. Translate the new file. Remember to update the html lang 44 | tag on line 2, remove the copyright notices for all the other languages, 45 | and (if possible) link to the appropriate language Creative Commons 46 | translation.
  8. 47 |
  9. Add a link to your page on index-*.html. Again, please keep this 48 | sorted by filename. Remember to create links on the other languages and 49 | create a non-link for your language on your own page.
  10. 50 |
51 | 52 |

Images

53 | 54 |

Unfortunately, the current setup makes it difficult to translate the 55 | images. If there is sufficient interest, I can rearrange things so that 56 | each language could have its own images. For now, they're all in English! 57 | 58 |


59 | 60 |

Copyright © 2010, 61 | Mark Lodato. 62 |

63 | 64 |

67 | This work is licensed under a Creative 69 | Commons Attribution-Noncommercial-Share Alike 3.0 United States 70 | License.

71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /visual-git-guide.css: -------------------------------------------------------------------------------- 1 | html{ 2 | background: #FAFAFA; 3 | } 4 | 5 | body{ 6 | font-family: sans-serif; 7 | margin: 0 auto; 8 | width: 70%; 9 | padding: 20px 0px; 10 | background: white; 11 | box-shadow: 0 1px 5px rgba(0, 0, 0, 0.25); 12 | color: rgba(0,0,0,0.7); 13 | } 14 | 15 | @media handheld, screen and (max-width: 995px){ 16 | body{ 17 | width: 100%; 18 | } 19 | } 20 | 21 | h1, h2, h3{ 22 | color: rgba(0,0,0,0.8); 23 | margin-left: 20px; 24 | margin-right: 20px; 25 | } 26 | 27 | h1{font-size: 4rem;} 28 | h2{font-size: 2rem;} 29 | h3{font-size: 1.2rem;} 30 | 31 | a, a:visited{ 32 | text-decoration: none; 33 | color: #f05033; 34 | font-size: 1rem; 35 | } 36 | 37 | 38 | p, div, ol, ul, pre, strong{ 39 | margin-left: 20px; 40 | margin-right: 20px; 41 | } 42 | 43 | hr{ 44 | color: #212121; 45 | height: 1px; 46 | background: #BDBDBD; 47 | } 48 | 49 | 50 | .center { 51 | text-align: center; 52 | } 53 | #link-to-png, #link-to-svg { 54 | font-style: italic; display: none; 55 | } 56 | ol ol { 57 | list-style-type: lower-alpha; 58 | } 59 | #language-box { 60 | position: absolute; 61 | top: 2px; 62 | font-family: sans-serif; 63 | list-style: none; 64 | margin: 0; 65 | padding: 0; 66 | text-align: center; 67 | } 68 | #language-box ul { 69 | display: inline; 70 | list-style: none; 71 | margin: 0 0 0 -0.5em; 72 | padding: 0.5em; 73 | width: 100%; 74 | } 75 | #language-box ul li { 76 | padding: .2ex 0; 77 | display: inline; 78 | } 79 | #language-box ul li.selected { 80 | display: none; 81 | } 82 | @media print { 83 | #language-box { 84 | display: none; 85 | } 86 | body{ 87 | width: 100%; 88 | } 89 | } 90 | pre { 91 | margin-left: 2em; 92 | } 93 | -------------------------------------------------------------------------------- /visual-git-guide.js: -------------------------------------------------------------------------------- 1 | // Webkit browsers can't zoom properly with object tags. 2 | if (navigator.userAgent.indexOf("AppleWebKit") > -1) { 3 | replacePNG = function(img, src) { 4 | var h = img.height, w = img.width; 5 | img.src = src; 6 | img.height = h; 7 | img.width = w; 8 | return 0; 9 | } 10 | } else { 11 | replacePNG = function(img, src) { 12 | var p = img.parentNode; 13 | var obj = document.createElement('object'); 14 | obj.type = 'image/svg+xml'; 15 | obj.data = src; 16 | obj.width = img.width; 17 | obj.height = img.height; 18 | p.appendChild(obj); 19 | p.removeChild(img); 20 | return -1; 21 | } 22 | } 23 | var svg_disabled = window.location.search.indexOf("no-svg") > 0; 24 | // Replace all the PNGs with SVGs on browsers that support them. 25 | function replace_all_PNGs() { 26 | var hasSVG = document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"); 27 | if (hasSVG) { 28 | if (svg_disabled) { 29 | document.getElementById('link-to-svg').style.display = 'block'; 30 | return; 31 | } 32 | var images = document.getElementsByTagName('img'); 33 | for (var i = 0; i < images.length; i++) { 34 | var img = images[i]; 35 | var src = img.src.match(/^(.*\.svg)\.png$/) 36 | if (src) 37 | i += replacePNG(img, src[1]); 38 | } 39 | document.getElementById('link-to-png').style.display = 'block'; 40 | } 41 | } 42 | 43 | // enable Google Analytics 44 | var _gaq = _gaq || []; 45 | _gaq.push(['_setAccount', 'UA-13167645-1']); 46 | _gaq.push(['_trackPageview']); 47 | (function() { 48 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; 49 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 50 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); 51 | })(); 52 | --------------------------------------------------------------------------------