commonmarker 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of commonmarker might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +3 -2
- data/README.md +67 -42
- data/Rakefile +22 -2
- data/commonmarker.gemspec +13 -9
- data/ext/commonmarker/cmark/api_test/main.c +35 -0
- data/ext/commonmarker/cmark/build/CMakeFiles/CMakeError.log +12 -12
- data/ext/commonmarker/cmark/build/CMakeFiles/CMakeOutput.log +141 -141
- data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/main.c.o +0 -0
- data/ext/commonmarker/cmark/build/api_test/api_test +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/houdini_html_u.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/iterator.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/houdini_html_u.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/iterator.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_u.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/iterator.c.o +0 -0
- data/ext/commonmarker/cmark/build/src/cmark +0 -0
- data/ext/commonmarker/cmark/build/src/libcmark.0.19.0.dylib +0 -0
- data/ext/commonmarker/cmark/build/src/libcmark.a +0 -0
- data/ext/commonmarker/cmark/build/src/libcmark.dylib +0 -0
- data/ext/commonmarker/cmark/src/houdini_html_u.c +26 -13
- data/ext/commonmarker/cmark/src/iterator.c +2 -2
- data/ext/commonmarker/cmark/test/__pycache__/cmark.cpython-34.pyc +0 -0
- data/ext/commonmarker/cmark/test/__pycache__/normalize.cpython-34.pyc +0 -0
- data/ext/commonmarker/cmark/test/cmark.pyc +0 -0
- data/ext/commonmarker/cmark/test/normalize.pyc +0 -0
- data/ext/commonmarker/commonmarker.c +276 -3
- data/ext/commonmarker/extconf.rb +3 -1
- data/lib/commonmarker.rb +70 -360
- data/lib/commonmarker/config.rb +1 -1
- data/lib/commonmarker/renderer.rb +91 -0
- data/lib/commonmarker/renderer/html_renderer.rb +149 -0
- data/lib/commonmarker/version.rb +1 -1
- data/test/benchinput.md +148414 -0
- data/test/benchmark.rb +13 -9
- data/test/progit/Gemfile +5 -0
- data/test/progit/README.md +9 -0
- data/test/progit/README.original.md +70 -0
- data/test/progit/Rakefile +285 -0
- data/test/progit/ar/01-introduction/01-chapter1.markdown +264 -0
- data/test/progit/ar/02-git-basics/01-chapter2.markdown +1124 -0
- data/test/progit/ar/NOTES +18 -0
- data/test/progit/ar/README +14 -0
- data/test/progit/az/01-introduction/01-chapter1.markdown +257 -0
- data/test/progit/az/02-git-basics/01-chapter2.markdown +1127 -0
- data/test/progit/az/03-git-branching/01-chapter3.markdown +598 -0
- data/test/progit/az/04-git-server/01-chapter4.markdown +861 -0
- data/test/progit/az/05-distributed-git/01-chapter5.markdown +897 -0
- data/test/progit/az/06-git-tools/01-chapter6.markdown +1126 -0
- data/test/progit/az/07-customizing-git/01-chapter7.markdown +937 -0
- data/test/progit/az/08-git-and-other-scms/01-chapter8.markdown +690 -0
- data/test/progit/az/09-git-internals/01-chapter9.markdown +977 -0
- data/test/progit/be/01-introduction/01-chapter1.markdown +257 -0
- data/test/progit/be/02-git-basics/01-chapter2.markdown +1126 -0
- data/test/progit/ca/01-introduction/01-chapter1.markdown +257 -0
- data/test/progit/ca/README.txt +1 -0
- data/test/progit/couchapp/Makefile +41 -0
- data/test/progit/couchapp/Readme.md +17 -0
- data/test/progit/couchapp/_id +1 -0
- data/test/progit/couchapp/shows/chapter.js +14 -0
- data/test/progit/couchapp/templates/foot.html +7 -0
- data/test/progit/couchapp/templates/head.html +51 -0
- data/test/progit/couchapp/vendor/markdown/showdown.js +420 -0
- data/test/progit/couchapp/vendor/mustache.js/mustache.js +302 -0
- data/test/progit/cs/01-introduction/01-chapter1.markdown +259 -0
- data/test/progit/cs/02-git-basics/01-chapter2.markdown +1225 -0
- data/test/progit/cs/03-git-branching/01-chapter3.markdown +606 -0
- data/test/progit/cs/04-git-server/01-chapter4.markdown +871 -0
- data/test/progit/cs/05-distributed-git/01-chapter5.markdown +914 -0
- data/test/progit/cs/06-git-tools/01-chapter6.markdown +1167 -0
- data/test/progit/cs/07-customizing-git/01-chapter7.markdown +940 -0
- data/test/progit/cs/08-git-and-other-scms/01-chapter8.markdown +700 -0
- data/test/progit/cs/09-git-internals/01-chapter9.markdown +1014 -0
- data/test/progit/de/01-introduction/01-chapter1.markdown +445 -0
- data/test/progit/de/02-git-basics/01-chapter2.markdown +1589 -0
- data/test/progit/de/03-git-branching/01-chapter3.markdown +964 -0
- data/test/progit/de/04-git-server/01-chapter4.markdown +1337 -0
- data/test/progit/de/05-distributed-git/01-chapter5.markdown +1329 -0
- data/test/progit/de/06-git-tools/01-chapter6.markdown +1502 -0
- data/test/progit/de/07-customizing-git/01-chapter7.markdown +1361 -0
- data/test/progit/de/08-git-and-other-scms/01-chapter8.markdown +919 -0
- data/test/progit/de/09-git-internals/01-chapter9.markdown +1361 -0
- data/test/progit/de/README.md +626 -0
- data/test/progit/ebooks/cover.png +0 -0
- data/test/progit/en/01-introduction/01-chapter1.markdown +263 -0
- data/test/progit/en/02-git-basics/01-chapter2.markdown +1228 -0
- data/test/progit/en/03-git-branching/01-chapter3.markdown +606 -0
- data/test/progit/en/04-git-server/01-chapter4.markdown +871 -0
- data/test/progit/en/05-distributed-git/01-chapter5.markdown +914 -0
- data/test/progit/en/06-git-tools/01-chapter6.markdown +1150 -0
- data/test/progit/en/07-customizing-git/01-chapter7.markdown +940 -0
- data/test/progit/en/08-git-and-other-scms/01-chapter8.markdown +700 -0
- data/test/progit/en/09-git-internals/01-chapter9.markdown +983 -0
- data/test/progit/eo/01-introduction/01-chapter1.markdown +257 -0
- data/test/progit/eo/02-git-basics/01-chapter2.markdown +1171 -0
- data/test/progit/epub/ProGit.css +28 -0
- data/test/progit/epub/title.png +0 -0
- data/test/progit/es-ni/01-introduction/01-chapter1.markdown +257 -0
- data/test/progit/es-ni/02-git-basics/01-chapter2.markdown +1127 -0
- data/test/progit/es/01-introduction/01-chapter1.markdown +262 -0
- data/test/progit/es/02-git-basics/01-chapter2.markdown +1165 -0
- data/test/progit/es/03-git-branching/01-chapter3.markdown +598 -0
- data/test/progit/es/04-git-server/01-chapter4.markdown +707 -0
- data/test/progit/es/05-distributed-git/01-chapter5.markdown +890 -0
- data/test/progit/es/06-git-tools/01-chapter6.markdown +1113 -0
- data/test/progit/es/07-customizing-git/01-chapter7.markdown +875 -0
- data/test/progit/es/08-git-and-other-scms/01-chapter8.markdown +686 -0
- data/test/progit/es/09-git-internals/01-chapter9.markdown +976 -0
- data/test/progit/es/NOTES +29 -0
- data/test/progit/es/README +3 -0
- data/test/progit/es/glosario-Benzirpi.txt +27 -0
- data/test/progit/es/omegat-Benzirpi.tmx +29075 -0
- data/test/progit/fa/01-introduction/01-chapter1.markdown +262 -0
- data/test/progit/fa/03-git-branching/01-chapter3.markdown +608 -0
- data/test/progit/fa/04-git-server/01-chapter4.markdown +872 -0
- data/test/progit/fa/NOTES.en-fa.md +143 -0
- data/test/progit/fa/README.md +7 -0
- data/test/progit/fi/01-introduction/01-chapter1.markdown +259 -0
- data/test/progit/fi/02-git-basics/01-chapter2.markdown +1171 -0
- data/test/progit/fi/NOTES +5 -0
- data/test/progit/figures-dia/fig0101.dia +617 -0
- data/test/progit/figures-dia/fig0102.dia +921 -0
- data/test/progit/figures-dia/fig0103.dia +1468 -0
- data/test/progit/figures-dia/fig0104.dia +1432 -0
- data/test/progit/figures-dia/fig0105.dia +1924 -0
- data/test/progit/figures-dia/fig0106.dia +562 -0
- data/test/progit/figures-dia/fig0201.dia +774 -0
- data/test/progit/figures-dia/fig0301.dia +2006 -0
- data/test/progit/figures-dia/fig0302.dia +2148 -0
- data/test/progit/figures-dia/fig0303.dia +719 -0
- data/test/progit/figures-dia/fig0304.dia +525 -0
- data/test/progit/figures-dia/fig0305.dia +622 -0
- data/test/progit/figures-dia/fig0306.dia +622 -0
- data/test/progit/figures-dia/fig0307.dia +719 -0
- data/test/progit/figures-dia/fig0308.dia +734 -0
- data/test/progit/figures-dia/fig0309.dia +831 -0
- data/test/progit/figures-dia/fig0310.dia +412 -0
- data/test/progit/figures-dia/fig0311.dia +493 -0
- data/test/progit/figures-dia/fig0312.dia +596 -0
- data/test/progit/figures-dia/fig0313.dia +774 -0
- data/test/progit/figures-dia/fig0314.dia +846 -0
- data/test/progit/figures-dia/fig0315.dia +787 -0
- data/test/progit/figures-dia/fig0316.dia +1078 -0
- data/test/progit/figures-dia/fig0317.dia +881 -0
- data/test/progit/figures-dia/fig0318.dia +968 -0
- data/test/progit/figures-dia/fig0319.dia +957 -0
- data/test/progit/figures-dia/fig0320.dia +1637 -0
- data/test/progit/figures-dia/fig0321.dia +1494 -0
- data/test/progit/figures-dia/fig0322.dia +1142 -0
- data/test/progit/figures-dia/fig0323.dia +1377 -0
- data/test/progit/figures-dia/fig0324.dia +1603 -0
- data/test/progit/figures-dia/fig0325.dia +2003 -0
- data/test/progit/figures-dia/fig0326.dia +2013 -0
- data/test/progit/figures-dia/fig0327.dia +687 -0
- data/test/progit/figures-dia/fig0328.dia +814 -0
- data/test/progit/figures-dia/fig0329.dia +793 -0
- data/test/progit/figures-dia/fig0330.dia +693 -0
- data/test/progit/figures-dia/fig0331.dia +1159 -0
- data/test/progit/figures-dia/fig0332.dia +1362 -0
- data/test/progit/figures-dia/fig0333.dia +1165 -0
- data/test/progit/figures-dia/fig0334.dia +1450 -0
- data/test/progit/figures-dia/fig0335.dia +994 -0
- data/test/progit/figures-dia/fig0336.dia +786 -0
- data/test/progit/figures-dia/fig0337.dia +1546 -0
- data/test/progit/figures-dia/fig0338.dia +1755 -0
- data/test/progit/figures-dia/fig0339.dia +1882 -0
- data/test/progit/figures-dia/fig0501.dia +456 -0
- data/test/progit/figures-dia/fig0502.dia +956 -0
- data/test/progit/figures-dia/fig0503.dia +915 -0
- data/test/progit/figures-dia/fig0504.dia +620 -0
- data/test/progit/figures-dia/fig0505.dia +744 -0
- data/test/progit/figures-dia/fig0506.dia +747 -0
- data/test/progit/figures-dia/fig0507.dia +895 -0
- data/test/progit/figures-dia/fig0508.dia +1122 -0
- data/test/progit/figures-dia/fig0509.dia +1243 -0
- data/test/progit/figures-dia/fig0510.dia +1240 -0
- data/test/progit/figures-dia/fig0511.dia +1201 -0
- data/test/progit/figures-dia/fig0512.dia +801 -0
- data/test/progit/figures-dia/fig0513.dia +1387 -0
- data/test/progit/figures-dia/fig0514.dia +1568 -0
- data/test/progit/figures-dia/fig0515.dia +1721 -0
- data/test/progit/figures-dia/fig0516.dia +997 -0
- data/test/progit/figures-dia/fig0517.dia +994 -0
- data/test/progit/figures-dia/fig0518.dia +1145 -0
- data/test/progit/figures-dia/fig0519.dia +992 -0
- data/test/progit/figures-dia/fig0520.dia +1240 -0
- data/test/progit/figures-dia/fig0521.dia +801 -0
- data/test/progit/figures-dia/fig0522.dia +922 -0
- data/test/progit/figures-dia/fig0523.dia +922 -0
- data/test/progit/figures-dia/fig0524.dia +1828 -0
- data/test/progit/figures-dia/fig0525.dia +2685 -0
- data/test/progit/figures-dia/fig0526.dia +717 -0
- data/test/progit/figures-dia/fig0527.dia +856 -0
- data/test/progit/figures-dia/fig0601.dia +790 -0
- data/test/progit/figures-dia/fig0702.dia +795 -0
- data/test/progit/figures-dia/fig0703.dia +795 -0
- data/test/progit/figures-dia/fig0901.dia +669 -0
- data/test/progit/figures-dia/fig0902.dia +834 -0
- data/test/progit/figures-dia/fig0903.dia +1483 -0
- data/test/progit/figures-dia/fig0904.dia +1728 -0
- data/test/progit/figures-dia/makeimages +25 -0
- data/test/progit/figures-source/progit.graffle +123108 -0
- data/test/progit/figures/18333fig0101-tn.png +0 -0
- data/test/progit/figures/18333fig0102-tn.png +0 -0
- data/test/progit/figures/18333fig0103-tn.png +0 -0
- data/test/progit/figures/18333fig0104-tn.png +0 -0
- data/test/progit/figures/18333fig0105-tn.png +0 -0
- data/test/progit/figures/18333fig0106-tn.png +0 -0
- data/test/progit/figures/18333fig0107-tn.png +0 -0
- data/test/progit/figures/18333fig0201-tn.png +0 -0
- data/test/progit/figures/18333fig0202-tn.png +0 -0
- data/test/progit/figures/18333fig0301-tn.png +0 -0
- data/test/progit/figures/18333fig0302-tn.png +0 -0
- data/test/progit/figures/18333fig0303-tn.png +0 -0
- data/test/progit/figures/18333fig0304-tn.png +0 -0
- data/test/progit/figures/18333fig0305-tn.png +0 -0
- data/test/progit/figures/18333fig0306-tn.png +0 -0
- data/test/progit/figures/18333fig0307-tn.png +0 -0
- data/test/progit/figures/18333fig0308-tn.png +0 -0
- data/test/progit/figures/18333fig0309-tn.png +0 -0
- data/test/progit/figures/18333fig0310-tn.png +0 -0
- data/test/progit/figures/18333fig0311-tn.png +0 -0
- data/test/progit/figures/18333fig0312-tn.png +0 -0
- data/test/progit/figures/18333fig0313-tn.png +0 -0
- data/test/progit/figures/18333fig0314-tn.png +0 -0
- data/test/progit/figures/18333fig0315-tn.png +0 -0
- data/test/progit/figures/18333fig0316-tn.png +0 -0
- data/test/progit/figures/18333fig0317-tn.png +0 -0
- data/test/progit/figures/18333fig0318-tn.png +0 -0
- data/test/progit/figures/18333fig0319-tn.png +0 -0
- data/test/progit/figures/18333fig0320-tn.png +0 -0
- data/test/progit/figures/18333fig0321-tn.png +0 -0
- data/test/progit/figures/18333fig0322-tn.png +0 -0
- data/test/progit/figures/18333fig0323-tn.png +0 -0
- data/test/progit/figures/18333fig0324-tn.png +0 -0
- data/test/progit/figures/18333fig0325-tn.png +0 -0
- data/test/progit/figures/18333fig0326-tn.png +0 -0
- data/test/progit/figures/18333fig0327-tn.png +0 -0
- data/test/progit/figures/18333fig0328-tn.png +0 -0
- data/test/progit/figures/18333fig0329-tn.png +0 -0
- data/test/progit/figures/18333fig0330-tn.png +0 -0
- data/test/progit/figures/18333fig0331-tn.png +0 -0
- data/test/progit/figures/18333fig0332-tn.png +0 -0
- data/test/progit/figures/18333fig0333-tn.png +0 -0
- data/test/progit/figures/18333fig0334-tn.png +0 -0
- data/test/progit/figures/18333fig0335-tn.png +0 -0
- data/test/progit/figures/18333fig0336-tn.png +0 -0
- data/test/progit/figures/18333fig0337-tn.png +0 -0
- data/test/progit/figures/18333fig0338-tn.png +0 -0
- data/test/progit/figures/18333fig0339-tn.png +0 -0
- data/test/progit/figures/18333fig0401-tn.png +0 -0
- data/test/progit/figures/18333fig0402-tn.png +0 -0
- data/test/progit/figures/18333fig0403-tn.png +0 -0
- data/test/progit/figures/18333fig0404-tn.png +0 -0
- data/test/progit/figures/18333fig0405-tn.png +0 -0
- data/test/progit/figures/18333fig0406-tn.png +0 -0
- data/test/progit/figures/18333fig0407-tn.png +0 -0
- data/test/progit/figures/18333fig0408-tn.png +0 -0
- data/test/progit/figures/18333fig0409-tn.png +0 -0
- data/test/progit/figures/18333fig0410-tn.png +0 -0
- data/test/progit/figures/18333fig0411-tn.png +0 -0
- data/test/progit/figures/18333fig0412-tn.png +0 -0
- data/test/progit/figures/18333fig0413-tn.png +0 -0
- data/test/progit/figures/18333fig0414-tn.png +0 -0
- data/test/progit/figures/18333fig0415-tn.png +0 -0
- data/test/progit/figures/18333fig0501-tn.png +0 -0
- data/test/progit/figures/18333fig0502-tn.png +0 -0
- data/test/progit/figures/18333fig0503-tn.png +0 -0
- data/test/progit/figures/18333fig0504-tn.png +0 -0
- data/test/progit/figures/18333fig0505-tn.png +0 -0
- data/test/progit/figures/18333fig0506-tn.png +0 -0
- data/test/progit/figures/18333fig0507-tn.png +0 -0
- data/test/progit/figures/18333fig0508-tn.png +0 -0
- data/test/progit/figures/18333fig0509-tn.png +0 -0
- data/test/progit/figures/18333fig0510-tn.png +0 -0
- data/test/progit/figures/18333fig0511-tn.png +0 -0
- data/test/progit/figures/18333fig0512-tn.png +0 -0
- data/test/progit/figures/18333fig0513-tn.png +0 -0
- data/test/progit/figures/18333fig0514-tn.png +0 -0
- data/test/progit/figures/18333fig0515-tn.png +0 -0
- data/test/progit/figures/18333fig0516-tn.png +0 -0
- data/test/progit/figures/18333fig0517-tn.png +0 -0
- data/test/progit/figures/18333fig0518-tn.png +0 -0
- data/test/progit/figures/18333fig0519-tn.png +0 -0
- data/test/progit/figures/18333fig0520-tn.png +0 -0
- data/test/progit/figures/18333fig0521-tn.png +0 -0
- data/test/progit/figures/18333fig0522-tn.png +0 -0
- data/test/progit/figures/18333fig0523-tn.png +0 -0
- data/test/progit/figures/18333fig0524-tn.png +0 -0
- data/test/progit/figures/18333fig0525-tn.png +0 -0
- data/test/progit/figures/18333fig0526-tn.png +0 -0
- data/test/progit/figures/18333fig0527-tn.png +0 -0
- data/test/progit/figures/18333fig0601-tn.png +0 -0
- data/test/progit/figures/18333fig0701-tn.png +0 -0
- data/test/progit/figures/18333fig0702-tn.png +0 -0
- data/test/progit/figures/18333fig0703-tn.png +0 -0
- data/test/progit/figures/18333fig0901-tn.png +0 -0
- data/test/progit/figures/18333fig0902-tn.png +0 -0
- data/test/progit/figures/18333fig0903-tn.png +0 -0
- data/test/progit/figures/18333fig0904-tn.png +0 -0
- data/test/progit/fr/01-introduction/01-chapter1.markdown +371 -0
- data/test/progit/fr/02-git-basics/01-chapter2.markdown +1378 -0
- data/test/progit/fr/03-git-branching/01-chapter3.markdown +781 -0
- data/test/progit/fr/04-git-server/01-chapter4.markdown +1141 -0
- data/test/progit/fr/05-distributed-git/01-chapter5.markdown +1163 -0
- data/test/progit/fr/06-git-tools/01-chapter6.markdown +1356 -0
- data/test/progit/fr/07-customizing-git/01-chapter7.markdown +1200 -0
- data/test/progit/fr/08-git-and-other-scms/01-chapter8.markdown +832 -0
- data/test/progit/fr/09-git-internals/01-chapter9.markdown +1228 -0
- data/test/progit/fr/NOTES.fr-fr.markdown +1 -0
- data/test/progit/fr/NOTES.fr-fr.md +127 -0
- data/test/progit/fr/README.md +43 -0
- data/test/progit/fr/glossaire-git.adoc +108 -0
- data/test/progit/hi/01-introduction/01-chapter1.markdown +7 -0
- data/test/progit/hu/01-introduction/01-chapter1.markdown +257 -0
- data/test/progit/id/01-introduction/01-chapter1.markdown +257 -0
- data/test/progit/id/02-git-basics/01-chapter2.markdown +1127 -0
- data/test/progit/id/03-git-branching/01-chapter3.markdown +598 -0
- data/test/progit/it/01-introduction/01-chapter1.markdown +263 -0
- data/test/progit/it/02-git-basics/01-chapter2.markdown +1227 -0
- data/test/progit/it/03-git-branching/01-chapter3.markdown +598 -0
- data/test/progit/it/04-git-server/01-chapter4.markdown +864 -0
- data/test/progit/it/05-distributed-git/01-chapter5.markdown +897 -0
- data/test/progit/it/06-git-tools/01-chapter6.markdown +1144 -0
- data/test/progit/it/07-customizing-git/01-chapter7.markdown +606 -0
- data/test/progit/it/08-git-and-other-scms/01-chapter8.markdown +707 -0
- data/test/progit/it/09-git-internals/01-chapter9.markdown +1000 -0
- data/test/progit/ja/01-introduction/01-chapter1.markdown +260 -0
- data/test/progit/ja/02-git-basics/01-chapter2.markdown +1221 -0
- data/test/progit/ja/03-git-branching/01-chapter3.markdown +604 -0
- data/test/progit/ja/04-git-server/01-chapter4.markdown +863 -0
- data/test/progit/ja/05-distributed-git/01-chapter5.markdown +908 -0
- data/test/progit/ja/06-git-tools/01-chapter6.markdown +1133 -0
- data/test/progit/ja/07-customizing-git/01-chapter7.markdown +936 -0
- data/test/progit/ja/08-git-and-other-scms/01-chapter8.markdown +690 -0
- data/test/progit/ja/09-git-internals/01-chapter9.markdown +984 -0
- data/test/progit/ja/README.md +58 -0
- data/test/progit/ja/translation glossaries.txt +33 -0
- data/test/progit/ko/01-introduction/01-chapter1.markdown +258 -0
- data/test/progit/ko/02-git-basics/01-chapter2.markdown +1181 -0
- data/test/progit/ko/03-git-branching/01-chapter3.markdown +612 -0
- data/test/progit/ko/04-git-server/01-chapter4.markdown +867 -0
- data/test/progit/ko/05-distributed-git/01-chapter5.markdown +913 -0
- data/test/progit/ko/06-git-tools/01-chapter6.markdown +1142 -0
- data/test/progit/ko/07-customizing-git/01-chapter7.markdown +935 -0
- data/test/progit/ko/08-git-and-other-scms/01-chapter8.markdown +688 -0
- data/test/progit/ko/09-git-internals/01-chapter9.markdown +976 -0
- data/test/progit/ko/README.md +75 -0
- data/test/progit/ko/translation_guide.txt +65 -0
- data/test/progit/latex/README +27 -0
- data/test/progit/latex/config.yml +144 -0
- data/test/progit/latex/makepdf +207 -0
- data/test/progit/latex/template.tex +155 -0
- data/test/progit/makeebooks +125 -0
- data/test/progit/makepdfs +47 -0
- data/test/progit/mk/01-introduction/01-chapter1.markdown +258 -0
- data/test/progit/mk/02-git-basics/01-chapter2.markdown +1125 -0
- data/test/progit/mk/03-git-branching/01-chapter3.markdown +598 -0
- data/test/progit/mk/05-distributed-git/01-chapter5.markdown +897 -0
- data/test/progit/nl/01-introduction/01-chapter1.markdown +296 -0
- data/test/progit/nl/02-git-basics/01-chapter2.markdown +1253 -0
- data/test/progit/nl/03-git-branching/01-chapter3.markdown +642 -0
- data/test/progit/nl/04-git-server/01-chapter4.markdown +902 -0
- data/test/progit/nl/05-distributed-git/01-chapter5.markdown +953 -0
- data/test/progit/nl/06-git-tools/01-chapter6.markdown +1177 -0
- data/test/progit/nl/07-customizing-git/01-chapter7.markdown +974 -0
- data/test/progit/nl/08-git-and-other-scms/01-chapter8.markdown +725 -0
- data/test/progit/nl/09-git-internals/01-chapter9.markdown +1013 -0
- data/test/progit/no-nb/01-introduction/01-chapter1.markdown +261 -0
- data/test/progit/no-nb/02-git-basics/01-chapter2.markdown +1225 -0
- data/test/progit/no-nb/03-git-branching/01-chapter3.markdown +606 -0
- data/test/progit/no-nb/04-git-server/01-chapter4.markdown +867 -0
- data/test/progit/no-nb/05-distributed-git/01-chapter5.markdown +914 -0
- data/test/progit/no-nb/06-git-tools/01-chapter6.markdown +1144 -0
- data/test/progit/no-nb/07-customizing-git/01-chapter7.markdown +936 -0
- data/test/progit/no-nb/08-git-and-other-scms/01-chapter8.markdown +689 -0
- data/test/progit/no-nb/09-git-internals/01-chapter9.markdown +977 -0
- data/test/progit/no-nb/README +2 -0
- data/test/progit/pl/01-introduction/01-chapter1.markdown +257 -0
- data/test/progit/pl/02-git-basics/02-chapter2.markdown +1128 -0
- data/test/progit/pl/03-git-branching/01-chapter3.markdown +598 -0
- data/test/progit/pl/04-git-server/01-chapter4.markdown +897 -0
- data/test/progit/pl/05-distributed-git/01-chapter5.markdown +1278 -0
- data/test/progit/pl/06-git-tools/01-chapter6.markdown +1550 -0
- data/test/progit/pl/07-customizing-git/01-chapter7.markdown +1058 -0
- data/test/progit/pl/08-git-and-other-scms/01-chapter8.markdown +948 -0
- data/test/progit/pl/09-git-internals/01-chapter9.markdown +1382 -0
- data/test/progit/pl/translation-guidelines.txt +70 -0
- data/test/progit/pt-br/01-introduction/01-chapter1.markdown +256 -0
- data/test/progit/pt-br/02-git-basics/01-chapter2.markdown +1127 -0
- data/test/progit/pt-br/03-git-branching/01-chapter3.markdown +596 -0
- data/test/progit/pt-br/04-git-server/01-chapter4.markdown +888 -0
- data/test/progit/pt-br/05-distributed-git/01-chapter5.markdown +896 -0
- data/test/progit/pt-br/06-git-tools/01-chapter6.markdown +1122 -0
- data/test/progit/pt-br/07-customizing-git/01-chapter7.markdown +932 -0
- data/test/progit/pt-br/08-git-and-other-scms/01-chapter8.markdown +691 -0
- data/test/progit/pt-br/09-git-internals/01-chapter9.markdown +978 -0
- data/test/progit/pt-br/figures-dia/fig0101.dia +617 -0
- data/test/progit/pt-br/figures-dia/fig0102.dia +921 -0
- data/test/progit/pt-br/figures-dia/fig0103.dia +1468 -0
- data/test/progit/pt-br/figures-dia/fig0104.dia +1432 -0
- data/test/progit/pt-br/figures-dia/fig0105.dia +1924 -0
- data/test/progit/pt-br/figures-dia/fig0106.dia +562 -0
- data/test/progit/pt-br/figures-dia/fig0201.dia +776 -0
- data/test/progit/pt-br/figures-dia/fig0301.dia +2006 -0
- data/test/progit/pt-br/figures-dia/fig0302.dia +2148 -0
- data/test/progit/pt-br/figures-dia/fig0316.dia +1079 -0
- data/test/progit/pt-br/figures-dia/fig0322.dia +1142 -0
- data/test/progit/pt-br/figures-dia/fig0323.dia +1407 -0
- data/test/progit/pt-br/figures-dia/fig0324.dia +1603 -0
- data/test/progit/pt-br/figures-dia/fig0325.dia +2003 -0
- data/test/progit/pt-br/figures-dia/fig0326.dia +2013 -0
- data/test/progit/pt-br/figures-dia/fig0336.dia +786 -0
- data/test/progit/pt-br/figures-dia/fig0337.dia +1546 -0
- data/test/progit/pt-br/figures-dia/fig0338.dia +1755 -0
- data/test/progit/pt-br/figures-dia/fig0339.dia +1882 -0
- data/test/progit/pt-br/figures-dia/fig0501.dia +456 -0
- data/test/progit/pt-br/figures-dia/fig0502.dia +965 -0
- data/test/progit/pt-br/figures-dia/fig0503.dia +914 -0
- data/test/progit/pt-br/figures-dia/fig0511.dia +1201 -0
- data/test/progit/pt-br/figures-dia/fig0515.dia +1721 -0
- data/test/progit/pt-br/figures-dia/fig0702.dia +795 -0
- data/test/progit/pt-br/figures-dia/fig0703.dia +795 -0
- data/test/progit/pt-br/figures-dia/fig0901.dia +669 -0
- data/test/progit/pt-br/figures-dia/fig0902.dia +834 -0
- data/test/progit/pt-br/figures-dia/fig0903.dia +1483 -0
- data/test/progit/pt-br/figures-dia/fig0904.dia +1728 -0
- data/test/progit/ro/01-introduction/01-chapter1.markdown +257 -0
- data/test/progit/ru/01-introduction/01-chapter1.markdown +259 -0
- data/test/progit/ru/02-git-basics/01-chapter2.markdown +1155 -0
- data/test/progit/ru/03-git-branching/01-chapter3.markdown +598 -0
- data/test/progit/ru/04-git-server/01-chapter4.markdown +854 -0
- data/test/progit/ru/05-distributed-git/01-chapter5.markdown +897 -0
- data/test/progit/ru/06-git-tools/01-chapter6.markdown +1126 -0
- data/test/progit/ru/07-customizing-git/01-chapter7.markdown +938 -0
- data/test/progit/ru/08-git-and-other-scms/01-chapter8.markdown +691 -0
- data/test/progit/ru/09-git-internals/01-chapter9.markdown +977 -0
- data/test/progit/ru/Glossary +38 -0
- data/test/progit/ru/README +12 -0
- data/test/progit/ru/figures-dia/fig0101.dia +647 -0
- data/test/progit/ru/figures-dia/fig0102.dia +1009 -0
- data/test/progit/ru/figures-dia/fig0103.dia +1468 -0
- data/test/progit/ru/figures-dia/fig0104.dia +1432 -0
- data/test/progit/ru/figures-dia/fig0105.dia +1924 -0
- data/test/progit/ru/figures-dia/fig0106.dia +561 -0
- data/test/progit/ru/figures-dia/fig0201.dia +774 -0
- data/test/progit/ru/figures-dia/fig0322.dia +1182 -0
- data/test/progit/ru/figures-dia/fig0323.dia +1457 -0
- data/test/progit/ru/figures-dia/fig0324.dia +1698 -0
- data/test/progit/ru/figures-dia/fig0325.dia +2101 -0
- data/test/progit/ru/figures-dia/fig0326.dia +2111 -0
- data/test/progit/ru/figures-dia/fig0336.dia +786 -0
- data/test/progit/ru/figures-dia/fig0337.dia +1546 -0
- data/test/progit/ru/figures-dia/fig0338.dia +1755 -0
- data/test/progit/ru/figures-dia/fig0339.dia +1882 -0
- data/test/progit/ru/figures-dia/fig0501.dia +477 -0
- data/test/progit/ru/figures-dia/fig0502.dia +1063 -0
- data/test/progit/ru/figures-dia/fig0503.dia +915 -0
- data/test/progit/ru/figures-dia/fig0511.dia +1201 -0
- data/test/progit/ru/figures-dia/fig0515.dia +1741 -0
- data/test/progit/ru/figures-dia/fig0702.dia +851 -0
- data/test/progit/ru/figures-dia/fig0703.dia +851 -0
- data/test/progit/sr/01-introduction/01-chapter1.markdown +257 -0
- data/test/progit/summary.rb +29 -0
- data/test/progit/th/01-introduction/01-chapter1.markdown +257 -0
- data/test/progit/th/02-git-basics/01-chapter2.markdown +1126 -0
- data/test/progit/th/README.md +47 -0
- data/test/progit/tr/01-introduction/01-chapter1.markdown +258 -0
- data/test/progit/tr/02-git-basics/01-chapter2.markdown +1129 -0
- data/test/progit/tr/03-git-branching/01-chapter3.markdown +598 -0
- data/test/progit/tr/04-git-server/01-chapter4.markdown +73 -0
- data/test/progit/tr/05-distributed-git/01-chapter5.markdown +215 -0
- data/test/progit/uk/01-introduction/01-chapter1.markdown +522 -0
- data/test/progit/vi/01-introduction/01-chapter1.markdown +259 -0
- data/test/progit/vi/02-git-basics/01-chapter2.markdown +1172 -0
- data/test/progit/vi/03-git-branching/01-chapter3.markdown +598 -0
- data/test/progit/zh-tw/01-introduction/01-chapter1.markdown +259 -0
- data/test/progit/zh-tw/02-git-basics/01-chapter2.markdown +1183 -0
- data/test/progit/zh-tw/03-git-branching/01-chapter3.markdown +604 -0
- data/test/progit/zh-tw/04-git-server/01-chapter4.markdown +866 -0
- data/test/progit/zh-tw/05-distributed-git/01-chapter5.markdown +912 -0
- data/test/progit/zh-tw/06-git-tools/01-chapter6.markdown +1139 -0
- data/test/progit/zh-tw/07-customizing-git/01-chapter7.markdown +932 -0
- data/test/progit/zh-tw/08-git-and-other-scms/01-chapter8.markdown +689 -0
- data/test/progit/zh-tw/09-git-internals/01-chapter9.markdown +977 -0
- data/test/progit/zh/01-introduction/01-chapter1.markdown +259 -0
- data/test/progit/zh/02-git-basics/01-chapter2.markdown +1177 -0
- data/test/progit/zh/03-git-branching/01-chapter3.markdown +604 -0
- data/test/progit/zh/04-git-server/01-chapter4.markdown +866 -0
- data/test/progit/zh/05-distributed-git/01-chapter5.markdown +912 -0
- data/test/progit/zh/06-git-tools/01-chapter6.markdown +1125 -0
- data/test/progit/zh/07-customizing-git/01-chapter7.markdown +935 -0
- data/test/progit/zh/08-git-and-other-scms/01-chapter8.markdown +689 -0
- data/test/progit/zh/09-git-internals/01-chapter9.markdown +976 -0
- data/test/spec_tests.json +4382 -4070
- data/test/test_basics.rb +1 -1
- data/test/test_helper.rb +1 -0
- data/test/test_maliciousness.rb +4 -2
- data/test/test_pathological_inputs.rb +31 -30
- data/test/test_spec.rb +5 -4
- metadata +972 -4
@@ -0,0 +1,262 @@
|
|
1
|
+
# سرآغاز #
|
2
|
+
|
3
|
+
در این فصل در رابطه با شروع کار با Git صحبت خواهد شد. این فصل با توضیحاتی در رابطه با تاریخچه ابزارهای کنترل نسخه شروع میشود، سپس چگونگی راه اندازی Git برروی یک سیستم خاص آموزش داده خواهد شد و در انتها انجام تنظیمات موردنیاز برروی این نرم افزار جهت شروع به کار با آن مورد بررسی قرار میگیرد. در انتهای این فصل خواننده باید دلیل وجود و استفاده از Git را بداند و همچنین باید محیط کار را برای استفاده از آن فراهم کرده باشد.
|
4
|
+
|
5
|
+
## کنترل نسخه ##
|
6
|
+
|
7
|
+
کنترل نسخه چیست و چه اهمیتی دارد؟ کنترل نسخه سیستمی است که تغییرات مربوط به یک یا چندین فایل را در طول زمان ذخیره میکند، تا کاربر بتواند به نسخههای قبلی مراجعت داشته باشد. در مثالهای استفاده شده در این کتاب از فایل های سورس نرم افزار جهت نمایش کنترل نسخه استفاده میشود، ولی با این وجود میتوان هر نوع فایلی را تحت کنترل نسخه قرار داد.
|
8
|
+
|
9
|
+
اگر شما یک گرافیست یا طراح وب باشید و تصمیم به نگهداری تمامی نسخههای یک عکس یا ساختار را داشته باشید (که قطعًا به همین منوال است)، استفاده از یک سیستم کنترل نسخه (VCS) راهبردی عاقلانه است. یک VCS این امکان را به شما میدهد تا: فایلها یا پروژهای را به یک وضعیت قبل برگردانید، تغییرات انجام گرفته در مرور زمان را مشاهده کنید، باعث و بانی تغییری را که منجر به ایجاد خطا یا مشکلی در سیستم شده است بیابید، چه کسی و چه زمانی موردی خاص را مطرح کرده است و بسیاری موارد دیگر. استفاده از یک VCS حتی این امکان را به شما میدهد که اگر احیاناً خطایی مرتکب شدید یا فایلی را اشتباهاً حذف یا از دست دادید، به راحتی آن را اصلاح و بازیابی کنید.
|
10
|
+
|
11
|
+
### سیستمهای کنترل نسخه محلی ###
|
12
|
+
|
13
|
+
روشی که اکثر کاربران جهت کنترل نسخه انتخاب میکنند شامل کپی کردن فایلها در پوشههای دیگر است (البته اگر هوشمندی نشان دهند، پوشه موردنظر را با تاریخ و زمان مشخصی نامگذاری میکنند). چنین روشی به جهت سادگی بین کاربران بسیار رایج است، ولی خطاپذیری بالایی نیز دارد. در این روش امکان دارد فرد به آسانی پوشهای که در آن قرار دارد را فراموش کرده و به اشتباه دست به تغییر فایلهایی بزند که مدنظر او نیست.
|
14
|
+
|
15
|
+
برای مقابله با این موذل، برنامه نویسان از زمانهای بسیار قبل اقدام به توسعه VCSها زدهاند که در بردارنده پایگاه داده سادهای هستند به گونه ای که تمامی تغییرات انجام شده برروی فایلهای هدف را در قالب کنترل نسخه نگهداری میکنند (تصویر 1-1)
|
16
|
+
|
17
|
+
Insert 18333fig0101.png
|
18
|
+
تصویر 1-1. دیاگرام کنترل نسخه محلی.
|
19
|
+
|
20
|
+
یکی از رایجترین ابزارهای VCS سیستمی با نام rcs بوده است، که هم اکنون نیز به همراه تعداد زیادی از کامپیوترهای امروزی نیز توزیع میشود. حتی سیستم عامل رایج Mac OS X نیز با نصب ابزارهای توسعه توسط کاربر برروی آن، دستور خط فرمان rcs را در اختیار فرد قرار میدهد. این ابزار به زبانی ساده با حفظ مجموعهای از وصلهها (که تغییرات بین فایلها میباشند) از یک نسخه به نسخهای دیگر در قالب فرمتی خاص برروی دیسک عمل میکند؛ این ابزار با اجرای چنین سیستمی قادر است با متصل کردن وصلهها به یکدیگر توانایی بازسازی هر فایلی را در هر لحظهای از زمان داشته باشد.
|
21
|
+
|
22
|
+
### سیستمهای کنترل نسخه مرکزی ###
|
23
|
+
|
24
|
+
مسئله مهم دیگری که کاربران با آن مواجه میشوند، نیاز آنها به همکاری با دیگر توسعهدهندگان برروی سیستمهای دیگر است. برای حل این مسئله، سیستمهای کنترل نسخه مرکزی (CVCSs) توسعه یافتند. چنین سیستمهایی مانند CVS، Subversion و Perforce در بردارنده سروری مرکزی هستند که تمامی نسخههای فایلها و حتی کاربرانی که این فایلها را از این مکان مرکزی checkout کردهاند در خود نگهداری میکند. برای سالهای زیادی، چنین روشی، روشی استاندارد برای کنترل نسخه بوده است (تصویر 1-2).
|
25
|
+
|
26
|
+
Insert 18333fig0102.png
|
27
|
+
تصویر 1-2. دیاگرام کنترل نسخه مرکزی.
|
28
|
+
|
29
|
+
این ساختار مزایای بسیاری مخصوصاً نسبت به سیستمهای کنترل نسخه محلی دارد. به عنوان مثال، هر فرد در حد و اندازه مشخصی خواهد توانست بداند که دیگر افراد تا چه اندازه در پروژه شریک هستند. مدیران از این نظر که هرکس از نظر سطح دسترسی قادر به انجام چه کاری است، کنترل مناسبی دارند؛ همچنین مدیریت یک CVCS به مراتب آسانتر از تعامل با پایگاههای داده محلی موجود برروی سیستمهای کاربران است.
|
30
|
+
|
31
|
+
با این وجود، چنین ساختاری معایبی نیز دارد. واضحترین موضوع بروز کوچکترین ایراد در سرورهای مرکزی است. اگر برای مدت یک ساعت این سرور متوقف و از کار بیفتد، در طی این بازه یک ساعته هیچکس نخواهد توانست تعاملی با سرور داشته باشد یا حتی تغییرات نسخه را برروی چیزی که در حال کارکردن با آن است ذخیره کند. اگر هارد دیسکی که پایگاه داده مرکزی برروی آن قرار دارد خراب شود، و پشتیبان مناسبی از آن گرفته نشده باشد، کاربر به طور کامل تاریخچه پروژه را از دست خواهد داد به جز تصاویر لحظهای که هر کاربر احتمالاً برروی ماشین محلی خود خواهد داشت. سیستمهای VCS محلی نیز این عیب را به ارث میبرند-اگر کاربر تمامی تاریخچه پروژه را در یک مکان ذخیره کند، ریسک از دادن همه چیز به قوت خود باقی خواهد ماند.
|
32
|
+
|
33
|
+
### سیستمهای کنترل نسخه پخشی ###
|
34
|
+
|
35
|
+
اینجا است که سیستمهای کنترل نسخه پخشی (DVCSs) نمود پیدا میکنند. در یک DVCS (مانند Git، Mercurial، Bazaar یا Darcs) کابران به checkout کردن آخرین تصویر لحظهای فایلها اکتفا نمیکنند: آنها مخزن را نیز بهصورت کامل کپی میکنند. بنابراین اگر هر سروری که سیستمها به واسطه آن در حال تعامل با یکدیگر هستند متوقف و از کار بیافتد، با کپی مخرن هر کدام از کاربران برروی سرور، عمل بازیابی انجام میگیرد. در واقع هر checkoutای، پشتیبان کاملی از تمامی دادهها است.
|
36
|
+
|
37
|
+
Insert 18333fig0103.png
|
38
|
+
تصویر 1-3. دیاگرام کنترل نسخه پخشی.
|
39
|
+
|
40
|
+
علاوه بر آن اکثر این سیستمها تعامل خوبی با داشتن مخازن خارجی متعدد جهت کار کردن با آنها دارند، در نتیجه شخص خواهد توانست با گروههای مختلفی در قالب پروژهای یکسان بهصورت همزمان تعامل داشته باشد. این قابلیت این امکان را به کاربر خواهد داد که جریانهای کاری متنوعی همانند مدلهای سلسه مراتبی را پیاده سازی کند که انجام آن در سیستمهای متمرکز امکان پذیر نیست.
|
41
|
+
|
42
|
+
## تاریخچه کوتاهی از Git ##
|
43
|
+
|
44
|
+
همانند اکثر حوادث بزرگ در در زندگی، Git نیز با خلاقیتی مخرب و جنجالی آتشین شروع شد. هسته لینوکس پروژه نرمافزاری متن باز با وسعت نسبتاً زیادی است. جهت نگهداری هسته لینوکس برای مدت زمان زیادی (1991 - 2002) تغییرات نرمافزاری به واسطه وصلهها و فایلهای بایگانی شده انتقال پیدا میکرد. در سال 2002، پروژه هسته لینوکس شروع به استفاده از سیستم DVCS خصوصی با نام BitKeeper کرد.
|
45
|
+
|
46
|
+
در سال 2005، ارتباط بین مجموعه تیم توسعه دهنده هسته لینوکس و شرکت تجاری توسعه دهنده BitKeeper گسسته شد و وضعیت ابزاری که قبل از آن به صورت رایگان عرضه میگشت تغییر پیدا کرد. این اتفاق زنگ هشداری برای مجموعه تیم توسعه دهنده لینوکس (به خصوص مؤسس لینوکس، لینوس تورلوادز) بود که بر اساس تجربههای کسب شده در استفاده از BitKeeper، خود اقدام به تولید نرم افزاری در این زمینه بزنند. مواردی از اهداف سیستم جدید عبارت بودند از:
|
47
|
+
|
48
|
+
* سرعت
|
49
|
+
* طراحی ساده
|
50
|
+
* پشتیبانی قوی از توسعه غیر خطی (هزاران انشعاب موازی)
|
51
|
+
* کاملاً پخشی
|
52
|
+
* قابلیت کنترل بهینه پروژههای بزرگ همانند هسته لینوکس (از نظر سرعت و اندازه داده)
|
53
|
+
|
54
|
+
از زمان تولد Git در سال 2005، این نرم افزار از نظر استفاده آسان و حفظ اهداف اولیه ذکر شده به تکامل و بلوغ رسیده است. Git نرم افزاری سریع، بسیار بهینه در مواجه با پروژههای بزرگ و حاوی سیستم انشعابی باورنکردنی برای توسعه غیر خطی است (فصل 3).
|
55
|
+
|
56
|
+
## مقدمات Git ##
|
57
|
+
|
58
|
+
خوب، Git چیست؟ این بخش از نظر یادگیری، بخشی مهم قلمداد می شود، زیرا اگر فرد از پایه و اساس عملکرد Git اطلاع پیدا کند، آنگاه خواهد توانست آسانتر در استفاده مؤثر از آن بهره جوید. در حین یادگیری Git، بهتر است فرد ذهن خود را از مواردی که احیاناً در رابطه با دیگر VCSها همانند Subversion و Perforce میداند تخلیه کند؛ بدین سبب از بروز اشتباهات موردی در استفاده از این ابزار پیشگیری میشود. با وجود آنکه رابط کاربری Git نسبتاً مشابه با دیگر سیستمها است، ولی در ذخیره سازی و نگاه به اطلاعات، دید بسیار متفاوتی در مقایسه با دیگر سیستمها دارد؛ دانستن این تفاوتها میتواند به فرد در جلوگیری از بروز اشتباهات بعدی در استفاده از این ابزار یاری دهد.
|
59
|
+
|
60
|
+
### تصاویر لحظهای، نه تفاوتها ###
|
61
|
+
|
62
|
+
اصلیترین تفاوت بین Git و دیگر VCSها (که شامل Subversion و هم خانواده های آن نیز میشود) دیدگاهی است که Git نسبت به دادههای خود دارد. از نظر مفهومی، اکثریت دیگر سیستمها اطلاعات را به مثابه لیستی از تغییرات بر مبنای فایل، ذخیره میکنند. این سیستمها (CVS، Subversion، Perfoce، Bazaar و غیره) همانطور که در تصویر 1-4 نشان داده شده است، به اطلاعاتی که نگهداری میکنند به شکل مجموعهای از فایلها و تغییراتی که برروی هر فایل در مرور زمان انجام گرفته است، مینگرند.
|
63
|
+
|
64
|
+
|
65
|
+
Insert 18333fig0104.png
|
66
|
+
تصویر 1-4. دیگر سیستمها دادهها به شکل تغییرات در نسخه پایه هر فایل ذخیره میکنند.
|
67
|
+
|
68
|
+
سGit از چنین تفکر یا روش ذخیره سازی دادهای پیروی نمیکند. در عوض دیدگاه Git نسبت به دادههای خود به شکل تصاویر لحظهای از یک سیستم فایلی کوچک است. هر زمانی که شخص commitای انجام میدهد یا وضعیت پروژه خود را در Git ذخیره میکند، در اصل تصویری از وضعیت تمامی فایلها در لحظه موردنظر تهیه و ارجاعی به تصویر لحظهای ایجاد شده ذخیره می شود. برای آنکه این عمل به صورت بهینه انجام پذیرد، اگر در فایلی تغییری ایجاد نشده باشد، Git اقدام به ذخیره سازی مجدد فایل نمیکند - تنها پیوندی به نسخه مشابه آن فایل که قبلاً ذخیره شده است را ذخیره می کند. طریقه نگرش Git به داده در تصویر 1-5 نمایش داده شده است.
|
69
|
+
|
70
|
+
Insert 18333fig0105.png
|
71
|
+
تصویر 1-5. Git دادهها را به شکل تصاویر لحظهای از پروژه در مرور زمان نگهداری میکند.
|
72
|
+
|
73
|
+
این شکل نگرش مهمترین اصل تمایز Git با دیگر VCSها است. این امر موجب میشود تا Git تجدیدنظری نسبت به تمامی ابعاد کنترل نسخه داشته باشد، که اکثریت دیگر سیستمها از نسلهای قبل از خود به ارث بردهاند. این موضوع باعث شده است تا Git از یک VCS ساده، به سیستم فایلی کوچکی بدل شود که در بالادست آن ابزار قدرتمند باورنکردنی بنا شده است. در فصل 3 بعضی از مزایای چنین دیدگاهی نسبت به داده، پوشش داده میشود.
|
74
|
+
|
75
|
+
### تقریباً تمام عملیات به صورت محلی انجام میپذیرد ###
|
76
|
+
|
77
|
+
اکثر عملیاتی که در Git انجام میپذیرد جهت اجرا تنها نیازمند فایلها و منابع محلی هستند - بهطور کلی نیازمند هیچگونه اطلاعاتی از کامپیوتری دیگر در شبکه نیست. اگر شما فردی هستید که به CVCSای عادت کردهاید که در آن اکثر فعالیتها دارای افزونگی رکود شبکهای داشتهاند، شاید این مزیت Git این فکر را برای شما تداعی کند که خدایان سرعت Git را با قدرتی وصف ناشدنی مورد لطف و رحمت قرار دادهاند. از آن جهت که تمامی تاریخچه پروژه برروی دیسک محلی قرار دارد، به نظر میرسد که اکثر عملیات به صورت لحظهای و بلادرنگ انجام میپذیرند.
|
78
|
+
|
79
|
+
به عنوان مثال، Git برای نمایش تاریخچه پروژه نیازی جهت مراجعه به سرور برای اخذ تاریخچه و نمایش آن ندارد - Git این عمل را با خواندن مستقیم پایگاه داده محلی انجام میدهد. این بدان معناست که شخص میتواند تاریخچه پروژه را تقریباً بلادرنگ مشاهده کند. اگر نیاز به مشاهده تغییرات بین نسخه فعلی یک فایل با نسخه یک ماه قبل از آن باشد، Git میتواند بهجای آنکه از سرور درخواست این عمل را داشته باشد و یا آنکه نسخه قبلی را از سرور خارجی فراخوانی و سپس مقایسه محلی را انجام دهد، این عمل را با نگاهی به نسخه یک ماه قبل فایل و انجام محاسبات محلی تغییرات رخ داده، انجام میدهد.
|
80
|
+
|
81
|
+
همچنین بدین معناست که در صورت آفلاین بودن و یا وصل نبودن به VPN دامنه عملکرد شخص زیاد محدود نمیشود. اگر سوار بر هواپیما یا قطار شده باشید و تصمیم به انجام کاری داشته باشید، میتوانید به راحتی commit را انجام داده و زمانی که دسترسی به شبکه پیدا کردید آپلود را انجام دهید. اگر به خانه رفته باشید و قادر به فعال سازی VPN خود نشده باشید، باز هم وقفهای در کار شما حاصل نمیشود. در اکثریت دیگر سیستمها انجام این موارد غیرممکن یا به سختی انجام میپذیرد. به عنوان مثال در Perforce، در صورتی که به شبکه متصل نباشید در واقع توانایی انجام کاری نخواهید داشت؛ در Subversion و CVS، امکان دستکاری فایلها برای شما وجود دارد، ولی برای commit تغییرات روی پایگاه داده محدودیت دارید (زیرا اتصال شما به پایگاه داده بر قرار نیست). شاید این موضوع مسئله مهمی به نظر نیاید، ولی شاید با مشاهده تفاوتهای بزرگی که میتواند به موجب آن ایجاد شود، شگفت زده شوید.
|
82
|
+
|
83
|
+
### Git صداقت دارد ###
|
84
|
+
|
85
|
+
هرچیزی که بخواهد در Git ذخیره شود، ابتدا checksum آن محاسبه میشود و سپس بهوسیله همین checksum ارجاع داده میشود. چنین عملی موجب میشود که در صورت ایجاد کوچکترین تغییری در محتویات فایل یا پوشهای، Git از آن آگاهی پیدا کند. این دستورالعمل در Git در پایینترین سطح پیادهسازی شده است و تأییدی بر صحت فلسفه Git دارد. بدین دلیل است که اگر دادهای در حین انتقال از دست برود و یا فایلی مخدوش شود، Git به سرعت از آن اطلاع پیدا میکند.
|
86
|
+
|
87
|
+
مکانیزمی که Git برای تولید checksum استفاده میکند، هش SHA-1 است. این هش یک رشته 40 کاراکتری از کاراکترهای مبنای شانزده است (0 - 9 و a - f) که از روی محتویات فایل و یا ساختار پوشه موردنظر در Git محاسبه میگردد. در ادامه یک نمونه از هش SHA-1 آورده شده است:
|
88
|
+
|
89
|
+
|
90
|
+
24b9da6552252987aa493b52f8696cd6d3b00373
|
91
|
+
|
92
|
+
به علت استفاده زیاد Git از این هش، به کرات در جای جای Git مشاهدهگر این هشها خواهید بود. در واقع، Git از نام فایل برای ذخیرهسازی آن استفاده نمیکند بلکه Git از هش تولید شده از محتویات فایل مربوطه برای آدرس دهی آن در پایگاه داده خود بهره میگیرد.
|
93
|
+
|
94
|
+
### عموماً Git فقط داده اضافه میکند ###
|
95
|
+
|
96
|
+
هرگاه عملی در Git انجام میپذیرد، تقریباً در تمامی موارد Git دادهای به دادههای خود در پایگاه داده اضافه میکند. انجام دادن عملی در این سیستم که برگشتپذیر نباشد یا باعث حذف داده ای از سیستم شود، بسیار سخت است. مشابه اکثر VCSها، فرد میتواند تا قبل از commit هرگونه تغییراتی را انجام دهد؛ ولی به محض commit یک تصویر لحظهای در Git، امکان حذف آن بسیار سخت است، مخصوصاً اگر فرد عادتاً پایگاه داده خود را به مخزن دیگری push کند.
|
97
|
+
|
98
|
+
این قابلیت باعث میشود که استفاده از Git، به عملی فرح بخش تبدیل شود زیرا فرد خواهد توانست بدون در خطر انداختن چیزی دست به هرگونه آزمایشی بزند. برای آشنایی بیشتر با چگونگی ذخیرهسازی و بازیابی دادهها در Git که به نظر از دست رفته میباشند، میتوانید به فصل 9 مراجعه کنید.
|
99
|
+
|
100
|
+
### سه وضعیت ###
|
101
|
+
|
102
|
+
توجه، توجه. اگر میخواهید پروسه یادگیری Git را بدون دردسر ادامه دهید، این بخش را به دقت مطالعه کنید. فایلها در Git میتوانند در سه وضعیت اصلی قرار داشته باشند: committed، modified و staged. committed بدین معناست که فایل موردنظر در پایگاه داده محلی ذخیره شده است. modified یعنی تغییری در فایل ایجاد شده است ولی هنوز commitای از این فایل روی پایگاه داده انجام نگرفته است. فایلی که در وضعیت staged قرار گرفته است، فایلی تغییر یافته است که نسخه فعلی آن در تصویر لحظهای بعدی جهت commit نشانهگذاری شده است.
|
103
|
+
|
104
|
+
حال میتوان سه بخش اصلی پروژه Git را معرفی کرد: پوشه Git، پوشه در حال کار (working directory) و staging area.
|
105
|
+
|
106
|
+
Insert 18333fig0106.png
|
107
|
+
تصویر 1-6. پوشه در حال کار، staging area و پوشه Git
|
108
|
+
|
109
|
+
در Git، metadata و پایگاه داده پروژه در پوشه Git ذخیره میشوند. این قسمت مهمترین بخش Git است، در واقع هنگامی که از مخزن کامپیوتری cloneای گرفته میشود، کپی از این پوشه ایجاد میگردد.
|
110
|
+
|
111
|
+
پوشه در حال کار، checkout منفردی از نسخهای از پروژه است. فایلهای این بخش، فایلهایی میباشند که از پایگاه داده فشرده واقع در پوشه Git بیرون کشیده شده و جهت استفاده و ایجاد تغییر بر روی دیسک قرار داده شدهاند.
|
112
|
+
|
113
|
+
staging area عموماً از یک فایل ساده تشکیل شده است که محتوی اطلاعاتی است که مشخص میکند که چه چیزهایی در commit بعدی قرار میگیرند. معمولاً این فایل را index مینامند ولی عبارت staging area نیز در حال تبدیل شدن به نامی استاندارد برای چنین فایلی است.
|
114
|
+
|
115
|
+
روند کاری Git عموماً به صورت ذیل است:
|
116
|
+
|
117
|
+
1. ایجاد تغییرات روی فایلهای واقع در پوشه در حال کار.
|
118
|
+
2. stage کردن فایلها و اضافه کردن تصاویر لحظهای فایلها به staging area.
|
119
|
+
3. commit کردن، که به موجب آن وضعیت فعلی فایلها در staging area تحت یک تصویر لحظهای به صورت دائمی در پوشه Git ذخیره میگردد.
|
120
|
+
|
121
|
+
اگر نسخهای از یک فایل در پوشه git قرار داشته باشد، commit شده فرض میشود. اگر تغییری در فایل ایجاد شده باشد و به staging area اضافه شده باشد، گوییم staged شده است. و اگر در فایل از آخرین مرتبهای که checkout شده است تغییری ایجاد شده باشد ولی staged نشده باشد، گوییم modified شده است. در فصل 2، با این وضعیتها بیشتر آشنا خواهید شد و یاد خواهید گرفت که چگونه میتوان از آنها به نحو احسنت استفاده کرد و یا حتی به صورت کامل از روی مرحله stage پرش کرد.
|
122
|
+
|
123
|
+
## نصب Git ##
|
124
|
+
|
125
|
+
حال وقت آن است که کار با Git را شروع کنیم. اول از هر چیز میبایست Git را نصب کرد. روشهای مختلفی برای این کار وجود دارد؛ دو مورد از رایجترین این روشها نصب از طریق سورس یا نصب به واسطه بستههای موجودی است که برای پلتفرم موردنظر شما تهیه شده است.
|
126
|
+
|
127
|
+
### نصب از طریق سورس ###
|
128
|
+
|
129
|
+
اگر امکان نصب از طریق سورس برای شما وجود دارد، این روش مناسبترین روش جهت نصب میباشد، زیرا شما بعد از نصب آخرین نسخه نرمافزار را در اختیار خواهید داشت. در هر نسخه از Git سعی شده است که تا در رابط کاربری بهبودهایی حاصل شود، بنابراین در اختیار داشتن آخرین نسخه بهترین گزینه است البته اگر با کامپایل سورس نرمافزار مشکلی نداشته باشید. همچنین معمولاً مخازن نرم افزاری اکثر توزیعهای لینوکس دربردارنده بستههایی با نسخههای قدیمی هستند؛ بنابراین در صورتی که شما توسعه دهندهای به روز هستید یا از backportها استفاده میکنید، نصب از طریق سورس بهترین انتخاب برای شما است.
|
130
|
+
|
131
|
+
برای نصب Git نیاز به کتابخانه های curl، zlib، openssl، expat و libiconv است که Git نیازمند آنهاست. به عنوان مثال، اگر روی سیستمی کار میکنید که yum (مانند Fedora) یا apt-get (مانند سیستم های مبتنی بر Debian) دارد، میتوانید برای نصب این بستههای نیازمندی از دستورهای ذیل استفاده کنید:
|
132
|
+
|
133
|
+
$ yum install curl-devel expat-devel gettext-devel \
|
134
|
+
openssl-devel zlib-devel
|
135
|
+
|
136
|
+
$ apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \
|
137
|
+
libz-dev libssl-dev
|
138
|
+
|
139
|
+
حال که تمامی نیازمندیها نصب گردید، میتوان آخرین نسخه Git را از وب سایت آن دانلود کرد:
|
140
|
+
|
141
|
+
http://git-scm.com/download
|
142
|
+
|
143
|
+
و آن را کامپایل و نصب نمود:
|
144
|
+
|
145
|
+
$ tar -zxf git-1.7.2.2.tar.gz
|
146
|
+
$ cd git-1.7.2.2
|
147
|
+
$ make prefix=/usr/local all
|
148
|
+
$ sudo make prefix=/usr/local install
|
149
|
+
|
150
|
+
بعد از کامل شدن این مراحل میتوان از خود Git برای دریافت آپدیتهای Git استفاده کرد:
|
151
|
+
|
152
|
+
$ git clone git://git.kernel.org/pub/scm/git/git.git
|
153
|
+
|
154
|
+
### نصب بر روی لینوکس ###
|
155
|
+
|
156
|
+
اگر قصد نصب Git بر روی لینوکس به واسطه یک نصاب باینری را دارید، میتوانید این کار را از طریق ابزار مدیریت بسته های نرمافزاری که همراه توزیع موردنظر شما ارائه میشود انجام دهید. اگر توزیع شما Fedora است، میتوانید از yum استفاده کنید:
|
157
|
+
|
158
|
+
$ yum install git-core
|
159
|
+
|
160
|
+
یا اگر توزیعی مبتنی بر Debian مانند Ubuntu دارید، میتوانید از apt-get استفاده کنید:
|
161
|
+
|
162
|
+
$ apt-get install git
|
163
|
+
|
164
|
+
### نصب برروی Mac ###
|
165
|
+
|
166
|
+
برای نصب برروی Mac دو روش آسان وجود دارد. آسانترین روش استفاده از نصاب گرافیکی Git است، که امکان دانلود آن از صفحه Google Code وجود دارد (تصویر 1-7):
|
167
|
+
|
168
|
+
http://code.google.com/p/git-osx-installer
|
169
|
+
|
170
|
+
Insert 18333fig0107.png
|
171
|
+
تصویر 1-7. نصاب Git OS X
|
172
|
+
|
173
|
+
روش دیگر نصب از طریق MacPortها (`http://www.macports.org`) است. اگر MacPortها را نصب شده روی سیستم خود دارید، میتوانید Git را با دستور ذیل نصب کنید
|
174
|
+
|
175
|
+
$ sudo port install git-core +svn +doc +bash_completion +gitweb
|
176
|
+
|
177
|
+
نیازی به افزودن تمامی اضافات نیست، ولی شاید برای استفاده از Git به همراه مخازن Subversion، احتمالاً افزودن +svn گزینه مناسبی است.
|
178
|
+
|
179
|
+
### نصب بر روی ویندوز ###
|
180
|
+
|
181
|
+
نصب Git روی ویندوز بسیار آسان است. پروژه msysGit یکی از آسانترین مراحل نصب را دارد. تنها نیاز است که فایل نصاب exe را از صفحه GitHub دانلود، و آن را اجرا کرد:
|
182
|
+
|
183
|
+
http://msysgit.github.com/
|
184
|
+
|
185
|
+
بعد از اتمام نصب، هم نسخه خط فرمان (شامل SSH client که در ادامه مشاهده خواهد شد که ابزاری کارآمد است) و هم رابط گرافیکی استاندارد را در اختیار خواهید داشت.
|
186
|
+
|
187
|
+
نکته برای کابران ویندوز: کاربر باید جهت کار با Git از پوسته ارائه شده به همراه msysGit (به سبک Unix) استفاده کند، تا بتواند دستورات چند خطی پیچیدهای که در این کتاب آورده شده را اجرا کند. اگر به هر دلیلی، نیاز به استفاده از پوسته خود ویندوز/کنسول خط فرمان، شدید باید در عوض تک کوت (simple quote) از دابل کوت (برای پارامترهایی که در بر دارنده فاصله هستند) استفاده کنید و باید پارامترهای موجود در آخرین خط که با circumflex accent (^) به پایان میرسند را داخل کوت قرار دهید، زیرا این علامت، نشانگر ادامه دار بودن خط در ویندوز است.
|
188
|
+
|
189
|
+
## تنظیمات شروع به کار Git ##
|
190
|
+
|
191
|
+
حال که Git روی سیستم نصب شده است، نیاز به شخصیسازی بعضی از منابع Git است. انجام این تنظیمات فقط برای یک مرتبه انجام میپذیرد؛ و بعد از آن با هر بار ارتقاء بدون تغییر باقی میمانند. همچنین امکان تغییر آنها در هر زمانی که نیاز باشد به کمک خط فرمان وجود دارد.
|
192
|
+
|
193
|
+
به همراه Git ابزاری ارائه شده است با نام git config که امکان خواندن و اعمال متغیرهای تنظیماتی که تمامی ابعاد ظاهری و عملیاتی Git را کنترل میکند فراهم میسازد.
|
194
|
+
|
195
|
+
* فایل `/etc/gitconfig`: حاوی مقادیر تمامی کاربران سیستم و مخازن آنها است. اگر به همراه `git config` از گزینه `--system` استفاده شود، خواندن و نوشتن به صورت اختصاصی از این فایل انجام میپذیرد.
|
196
|
+
* فایل `~/.gitconfig`: مختص کاربر مشخصی است. با استفاده از گزینه `--global` خواندن و نوشتن Git به صورت اختصاصی از این فایل انجام میپذیرد.
|
197
|
+
* فایل config موجود در پوشه git (`.git/config`) یا هر مخزنی که در حال استفاده از آن میباشید: مختص یک مخزن خاص است. مقادیر هر سطح باعث لغو مقادیر سطح قبلی خود میشود. بنابراین مقادیر `.git/config` موجب لغو مقادیر `/etc/gitconfig` خواهد شد.
|
198
|
+
|
199
|
+
در سیستمهای ویندوزی، Git در پوشه `$HOME` (متغیر محیطی `%USERPROFILE%` در ویندوز) که برای اکثر کاربران با توجه به نسخه سیستم در مسیرهای `C:\Documents and Settings\$USER یا `C:\Users\$USER` (`$USER در ویندوز متغیر محیطی `%USERNAME%`) قرار دارد، فایل `.gitconfig` را جستجو میکند. همچنین نسبت به مسیر ریشه MSys که همان مسیر نصب انتخاب شده در هنگام اجرای نصاب Git در ویندوز میباشد، به دنبال فایلی با نام /etc/gitconfig میگردد.
|
200
|
+
|
201
|
+
### شناسه کاربر ###
|
202
|
+
|
203
|
+
اولین عملی که بعد از نصب Git باید انجام شود، مقداردهی دو متغیر نام کاربری (user name) و آدرس پست الکترونیکی (e-mail address) است. این عمل از آن جهت اهمیت دارد که در هر commit این اطلاعات بهصورتی تغییر ناپذیر روی commit انجام شده حک میشوند.
|
204
|
+
|
205
|
+
$ git config --global user.name "John Doe"
|
206
|
+
$ git config --global user.email johndoe@example.com
|
207
|
+
|
208
|
+
مجدداً یادآوری میشود که انجام این عمل در صورت استفاده از گزینه `--global` فقط یک مرتبه انجام میپذیرد، زیرا Git برای هر عملی که در سیستم انجام میپذیرد از این اطلاعات استفاده میکند. حال اگر فرد نیاز به استفاده از نام و آدرس پست الکترونیکی متفاوتی برای پروژههای خاصی دارد، میتواند با اجرای همان دستورات البته بدون استفاده از گزینه `--global` هنگامی که در مسیر پروژه مذکور قرار دارد به مقصود خود دست یابد.
|
209
|
+
|
210
|
+
### ویرایشگر کاربر ###
|
211
|
+
|
212
|
+
حال که شناسه تنظیم شد، میتوان ویرایشگر متن پیش فرضی را معرفی کرد تا هنگامی که نیاز به درج پیغامی در Git است فراخوانی شود. به صورت پیش فرض Git از ویرایشگر پیش فرض سیستم برای این امر استفاده می کند، که معمولاً Vi یا Vim است. اگر نظر شخص به استفاده از ویرایشگر متنی متفاوتی مانند Emacs باشد، میتوان به صورت ذیل عمل کرد:
|
213
|
+
|
214
|
+
$ git config --global core.editor emacs
|
215
|
+
|
216
|
+
### ابزار Diff ###
|
217
|
+
|
218
|
+
ابزار مفید دیگری که شاید نیاز به تنظیم داشته باشد، ابزار diff پیش فرضی است که برای رفع مغایرت ایجاد شده در هنگام اجرای دستور merge استفاده میگردد. به عنوان مثال اگر هدف استفاده از vimdiff باشد خواهیم داشت:
|
219
|
+
|
220
|
+
$ git config --global merge.tool vimdiff
|
221
|
+
|
222
|
+
سGit از ابزارهای kdiff3، tkdiff، meld، xxdiff، emerge، vimdiff، gvimdiff، ecmerge و opendiff جهت merge پشتیبانی میکند. با این وجود امکان تعریف ابزاری شخصی نیز وجود دارد؛ برای اطلاعات بیشتر جهت انجام این مورد میتوانید به فصل 7 مراجعه کنید.
|
223
|
+
|
224
|
+
### بررسی تنظیمات ###
|
225
|
+
|
226
|
+
برای مشاهده و بررسی تنظیمات، میتوان از دستور `git config --list` استفاده کرد که در نتیجه آن Git تمامی تنظیمات موجود تا آن لحظه را در قالب لیستی نمایش میدهد:
|
227
|
+
|
228
|
+
$ git config --list
|
229
|
+
user.name=Scott Chacon
|
230
|
+
user.email=schacon@gmail.com
|
231
|
+
color.status=auto
|
232
|
+
color.branch=auto
|
233
|
+
color.interactive=auto
|
234
|
+
color.diff=auto
|
235
|
+
...
|
236
|
+
|
237
|
+
احتمال دارد در این لیست کلیدهایی بیش از یک بار مشاهده شوند، دلیل این امر آن است که Git کلید مشابهی را از فایلهای مختلفی (مانند `/etc/giconfig` و `~/.gitconfig`) خوانده است. در اینگونه موارد، Git آخرین مقدار کلید منحصر به فردی که مشاهده میکند را جهت استفاده بهکار میگیرد.
|
238
|
+
|
239
|
+
همچنین برای مشاهده مقدار مورد استفاده یک کلید خاص توسط Git، میتوان از دستور `git config {key}` استفاده کرد:
|
240
|
+
|
241
|
+
$ git config user.name
|
242
|
+
Scott Chacon
|
243
|
+
|
244
|
+
## دریافت راهنمایی ##
|
245
|
+
|
246
|
+
هرگاه در استفاده از Git نیازمند راهنمایی بودید، سه روش برای مشاهده صفحه راهنما هرگونه دستوری در Git وجود دارد:
|
247
|
+
|
248
|
+
$ git help <verb>
|
249
|
+
$ git <verb> --help
|
250
|
+
$ man git-<verb>
|
251
|
+
|
252
|
+
برای مثال، برای مشاهده صفحه راهنما دستور config داریم
|
253
|
+
|
254
|
+
$ git help config
|
255
|
+
|
256
|
+
این دستورات از آن جهت که میتوان از هر مکانی، حتی در حالت آفلاین، به آنها دسترسی پیدا کرد ابزاری کاربردی میباشند.
|
257
|
+
اگر صفحات راهنما و این کتاب جوابگوی نیاز شما نبودند و نیاز به راهنمایی فردی پیدا کردید، میتوانید به کانالهای `#git` یا `#github` در سرور Freenode IRC (irc.freenode.net) مراجعه کنید.
|
258
|
+
معمولاً این کانالها مملؤ از افرادی با سطح دانش بالا در زمینه Git هستند که آماده راهنمایی رساندن به شما میباشند.
|
259
|
+
|
260
|
+
## خلاصه ##
|
261
|
+
|
262
|
+
با مطالعه این فصل شما باید درک اولیهای از این که Git چیست و چه تفاوتی با دیگر CVCSهایی که احتمالاً از آن استفاده میکردید دارد پیدا کرده باشد. همچنین شما باید نسخه آماده به کاری از Git را روی سیستم خود داشته باشید که شناسه شخصی شما برروی آن تنظیم شده است. حال زمان یادگیری اصول اولیه Git است.
|
@@ -0,0 +1,608 @@
|
|
1
|
+
# Git Branching #
|
2
|
+
|
3
|
+
تقریبا تمام انواع VCS نوعی از انشعاب را پشتیبانی میکنند.
|
4
|
+
|
5
|
+
Nearly every VCS has some form of branching support. Branching means you diverge from the main line of development and continue to do work without messing with that main line. In many VCS tools, this is a somewhat expensive process, often requiring you to create a new copy of your source code directory, which can take a long time for large projects.
|
6
|
+
|
7
|
+
Some people refer to the branching model in Git as its “killer feature” , and it certainly sets Git apart in the VCS community. Why is it so special? The way Git branches is incredibly lightweight, making branching operations nearly instantaneous and switching back and forth between branches generally just as fast. Unlike many other VCSs, Git encourages a workflow that branches and merges often, even multiple times in a day. Understanding and mastering this feature gives you a powerful and unique tool and can literally change the way that you develop.
|
8
|
+
|
9
|
+
## What a Branch Is ##
|
10
|
+
|
11
|
+
To really understand the way Git does branching, we need to take a step back and examine how Git stores its data. As you may remember from Chapter 1, Git doesn’t store data as a series of changesets or deltas, but instead as a series of snapshots.
|
12
|
+
|
13
|
+
When you commit in Git, Git stores a commit object that contains a pointer to the snapshot of the content you staged, the author and message metadata, and zero or more pointers to the commit or commits that were the direct parents of this commit: zero parents for the first commit, one parent for a normal commit, and multiple parents for a commit that results from a merge of two or more branches.
|
14
|
+
|
15
|
+
To visualize this, let’s assume that you have a directory containing three files, and you stage them all and commit. Staging the files checksums each one (the SHA-1 hash we mentioned in Chapter 1), stores that version of the file in the Git repository (Git refers to them as blobs), and adds that checksum to the staging area:
|
16
|
+
|
17
|
+
$ git add README test.rb LICENSE
|
18
|
+
$ git commit -m 'initial commit of my project'
|
19
|
+
|
20
|
+
Running `git commit` checksums all project directories and stores them as `tree` objects in the Git repository. Git then creates a `commit` object that has the metadata and a pointer to the root project `tree` object so it can re-create that snapshot when needed.
|
21
|
+
|
22
|
+
Your Git repository now contains five objects: one blob for the contents of each of your three files, one tree that lists the contents of the directory and specifies which file names are stored as which blobs, and one commit with the pointer to that root tree and all the commit metadata. Conceptually, the data in your Git repository looks something like Figure 3-1.
|
23
|
+
|
24
|
+
Insert 18333fig0301.png
|
25
|
+
Figure 3-1. Single commit repository data.
|
26
|
+
|
27
|
+
If you make some changes and commit again, the next commit stores a pointer to the commit that came immediately before it. After two more commits, your history might look something like Figure 3-2.
|
28
|
+
|
29
|
+
Insert 18333fig0302.png
|
30
|
+
Figure 3-2. Git object data for multiple commits.
|
31
|
+
|
32
|
+
A branch in Git is simply a lightweight movable pointer to one of these commits. The default branch name in Git is master. As you initially make commits, you’re given a `master` branch that points to the last commit you made. Every time you commit, it moves forward automatically.
|
33
|
+
|
34
|
+
Insert 18333fig0303.png
|
35
|
+
Figure 3-3. Branch pointing into the commit data’s history.
|
36
|
+
|
37
|
+
What happens if you create a new branch? Well, doing so creates a new pointer for you to move around. Let’s say you create a new branch called testing. You do this with the `git branch` command:
|
38
|
+
|
39
|
+
$ git branch testing
|
40
|
+
|
41
|
+
This creates a new pointer at the same commit you’re currently on (see Figure 3-4).
|
42
|
+
|
43
|
+
Insert 18333fig0304.png
|
44
|
+
Figure 3-4. Multiple branches pointing into the commit’s data history.
|
45
|
+
|
46
|
+
How does Git know what branch you’re currently on? It keeps a special pointer called HEAD. Note that this is a lot different than the concept of HEAD in other VCSs you may be used to, such as Subversion or CVS. In Git, this is a pointer to the local branch you’re currently on. In this case, you’re still on master. The `git branch` command only created a new branch — it didn’t switch to that branch (see Figure 3-5).
|
47
|
+
|
48
|
+
Insert 18333fig0305.png
|
49
|
+
Figure 3-5. HEAD file pointing to the branch you’re on.
|
50
|
+
|
51
|
+
To switch to an existing branch, you run the `git checkout` command. Let’s switch to the new testing branch:
|
52
|
+
|
53
|
+
$ git checkout testing
|
54
|
+
|
55
|
+
This moves HEAD to point to the testing branch (see Figure 3-6).
|
56
|
+
|
57
|
+
Insert 18333fig0306.png
|
58
|
+
Figure 3-6. HEAD points to another branch when you switch branches.
|
59
|
+
|
60
|
+
What is the significance of that? Well, let’s do another commit:
|
61
|
+
|
62
|
+
$ vim test.rb
|
63
|
+
$ git commit -a -m 'made a change'
|
64
|
+
|
65
|
+
Figure 3-7 illustrates the result.
|
66
|
+
|
67
|
+
Insert 18333fig0307.png
|
68
|
+
Figure 3-7. The branch that HEAD points to moves forward with each commit.
|
69
|
+
|
70
|
+
This is interesting, because now your testing branch has moved forward, but your `master` branch still points to the commit you were on when you ran `git checkout` to switch branches. Let’s switch back to the `master` branch:
|
71
|
+
|
72
|
+
$ git checkout master
|
73
|
+
|
74
|
+
Figure 3-8 shows the result.
|
75
|
+
|
76
|
+
Insert 18333fig0308.png
|
77
|
+
Figure 3-8. HEAD moves to another branch on a checkout.
|
78
|
+
|
79
|
+
That command did two things. It moved the HEAD pointer back to point to the `master` branch, and it reverted the files in your working directory back to the snapshot that `master` points to. This also means the changes you make from this point forward will diverge from an older version of the project. It essentially rewinds the work you’ve done in your testing branch temporarily so you can go in a different direction.
|
80
|
+
|
81
|
+
Let’s make a few changes and commit again:
|
82
|
+
|
83
|
+
$ vim test.rb
|
84
|
+
$ git commit -a -m 'made other changes'
|
85
|
+
|
86
|
+
Now your project history has diverged (see Figure 3-9). You created and switched to a branch, did some work on it, and then switched back to your main branch and did other work. Both of those changes are isolated in separate branches: you can switch back and forth between the branches and merge them together when you’re ready. And you did all that with simple `branch` and `checkout` commands.
|
87
|
+
|
88
|
+
Insert 18333fig0309.png
|
89
|
+
Figure 3-9. The branch histories have diverged.
|
90
|
+
|
91
|
+
Because a branch in Git is in actuality a simple file that contains the 40 character SHA-1 checksum of the commit it points to, branches are cheap to create and destroy. Creating a new branch is as quick and simple as writing 41 bytes to a file (40 characters and a newline).
|
92
|
+
|
93
|
+
This is in sharp contrast to the way most VCS tools branch, which involves copying all of the project’s files into a second directory. This can take several seconds or even minutes, depending on the size of the project, whereas in Git the process is always instantaneous. Also, because we’re recording the parents when we commit, finding a proper merge base for merging is automatically done for us and is generally very easy to do. These features help encourage developers to create and use branches often.
|
94
|
+
|
95
|
+
Let’s see why you should do so.
|
96
|
+
|
97
|
+
## Basic Branching and Merging ##
|
98
|
+
|
99
|
+
Let’s go through a simple example of branching and merging with a workflow that you might use in the real world. You’ll follow these steps:
|
100
|
+
|
101
|
+
1. Do work on a web site.
|
102
|
+
2. Create a branch for a new story you’re working on.
|
103
|
+
3. Do some work in that branch.
|
104
|
+
|
105
|
+
At this stage, you’ll receive a call that another issue is critical and you need a hotfix. You’ll do the following:
|
106
|
+
|
107
|
+
1. Switch back to your production branch.
|
108
|
+
2. Create a branch to add the hotfix.
|
109
|
+
3. After it’s tested, merge the hotfix branch, and push to production.
|
110
|
+
4. Switch back to your original story and continue working.
|
111
|
+
|
112
|
+
### Basic Branching ###
|
113
|
+
|
114
|
+
First, let’s say you’re working on your project and have a couple of commits already (see Figure 3-10).
|
115
|
+
|
116
|
+
Insert 18333fig0310.png
|
117
|
+
Figure 3-10. A short and simple commit history.
|
118
|
+
|
119
|
+
You’ve decided that you’re going to work on issue #53 in whatever issue-tracking system your company uses. To be clear, Git isn’t tied into any particular issue-tracking system; but because issue #53 is a focused topic that you want to work on, you’ll create a new branch in which to work. To create a branch and switch to it at the same time, you can run the `git checkout` command with the `-b` switch:
|
120
|
+
|
121
|
+
$ git checkout -b iss53
|
122
|
+
Switched to a new branch 'iss53'
|
123
|
+
|
124
|
+
This is shorthand for:
|
125
|
+
|
126
|
+
$ git branch iss53
|
127
|
+
$ git checkout iss53
|
128
|
+
|
129
|
+
Figure 3-11 illustrates the result.
|
130
|
+
|
131
|
+
Insert 18333fig0311.png
|
132
|
+
Figure 3-11. Creating a new branch pointer.
|
133
|
+
|
134
|
+
You work on your web site and do some commits. Doing so moves the `iss53` branch forward, because you have it checked out (that is, your HEAD is pointing to it; see Figure 3-12):
|
135
|
+
|
136
|
+
$ vim index.html
|
137
|
+
$ git commit -a -m 'added a new footer [issue 53]'
|
138
|
+
|
139
|
+
Insert 18333fig0312.png
|
140
|
+
Figure 3-12. The iss53 branch has moved forward with your work.
|
141
|
+
|
142
|
+
Now you get the call that there is an issue with the web site, and you need to fix it immediately. With Git, you don’t have to deploy your fix along with the `iss53` changes you’ve made, and you don’t have to put a lot of effort into reverting those changes before you can work on applying your fix to what is in production. All you have to do is switch back to your master branch.
|
143
|
+
|
144
|
+
However, before you do that, note that if your working directory or staging area has uncommitted changes that conflict with the branch you’re checking out, Git won’t let you switch branches. It’s best to have a clean working state when you switch branches. There are ways to get around this (namely, stashing and commit amending) that we’ll cover later. For now, you’ve committed all your changes, so you can switch back to your master branch:
|
145
|
+
|
146
|
+
$ git checkout master
|
147
|
+
Switched to branch 'master'
|
148
|
+
|
149
|
+
At this point, your project working directory is exactly the way it was before you started working on issue #53, and you can concentrate on your hotfix. This is an important point to remember: Git resets your working directory to look like the snapshot of the commit that the branch you check out points to. It adds, removes, and modifies files automatically to make sure your working copy is what the branch looked like on your last commit to it.
|
150
|
+
|
151
|
+
Next, you have a hotfix to make. Let’s create a hotfix branch on which to work until it’s completed (see Figure 3-13):
|
152
|
+
|
153
|
+
$ git checkout -b hotfix
|
154
|
+
Switched to a new branch 'hotfix'
|
155
|
+
$ vim index.html
|
156
|
+
$ git commit -a -m 'fixed the broken email address'
|
157
|
+
[hotfix 3a0874c] fixed the broken email address
|
158
|
+
1 files changed, 1 deletion(-)
|
159
|
+
|
160
|
+
Insert 18333fig0313.png
|
161
|
+
Figure 3-13. hotfix branch based back at your master branch point.
|
162
|
+
|
163
|
+
You can run your tests, make sure the hotfix is what you want, and merge it back into your master branch to deploy to production. You do this with the `git merge` command:
|
164
|
+
|
165
|
+
$ git checkout master
|
166
|
+
$ git merge hotfix
|
167
|
+
Updating f42c576..3a0874c
|
168
|
+
Fast-forward
|
169
|
+
README | 1 -
|
170
|
+
1 file changed, 1 deletion(-)
|
171
|
+
|
172
|
+
You’ll notice the phrase "Fast-forward" in that merge. Because the commit pointed to by the branch you merged in was directly upstream of the commit you’re on, Git moves the pointer forward. To phrase that another way, when you try to merge one commit with a commit that can be reached by following the first commit’s history, Git simplifies things by moving the pointer forward because there is no divergent work to merge together — this is called a "fast forward".
|
173
|
+
|
174
|
+
Your change is now in the snapshot of the commit pointed to by the `master` branch, and you can deploy your change (see Figure 3-14).
|
175
|
+
|
176
|
+
Insert 18333fig0314.png
|
177
|
+
Figure 3-14. Your master branch points to the same place as your hotfix branch after the merge.
|
178
|
+
|
179
|
+
After your super-important fix is deployed, you’re ready to switch back to the work you were doing before you were interrupted. However, first you’ll delete the `hotfix` branch, because you no longer need it — the `master` branch points at the same place. You can delete it with the `-d` option to `git branch`:
|
180
|
+
|
181
|
+
$ git branch -d hotfix
|
182
|
+
Deleted branch hotfix (was 3a0874c).
|
183
|
+
|
184
|
+
Now you can switch back to your work-in-progress branch on issue #53 and continue working on it (see Figure 3-15):
|
185
|
+
|
186
|
+
$ git checkout iss53
|
187
|
+
Switched to branch 'iss53'
|
188
|
+
$ vim index.html
|
189
|
+
$ git commit -a -m 'finished the new footer [issue 53]'
|
190
|
+
[iss53 ad82d7a] finished the new footer [issue 53]
|
191
|
+
1 file changed, 1 insertion(+)
|
192
|
+
|
193
|
+
Insert 18333fig0315.png
|
194
|
+
Figure 3-15. Your iss53 branch can move forward independently.
|
195
|
+
|
196
|
+
It’s worth noting here that the work you did in your `hotfix` branch is not contained in the files in your `iss53` branch. If you need to pull it in, you can merge your `master` branch into your `iss53` branch by running `git merge master`, or you can wait to integrate those changes until you decide to pull the `iss53` branch back into `master` later.
|
197
|
+
|
198
|
+
### Basic Merging ###
|
199
|
+
|
200
|
+
Suppose you’ve decided that your issue #53 work is complete and ready to be merged into your `master` branch. In order to do that, you’ll merge in your `iss53` branch, much like you merged in your `hotfix` branch earlier. All you have to do is check out the branch you wish to merge into and then run the `git merge` command:
|
201
|
+
|
202
|
+
$ git checkout master
|
203
|
+
$ git merge iss53
|
204
|
+
Auto-merging README
|
205
|
+
Merge made by the 'recursive' strategy.
|
206
|
+
README | 1 +
|
207
|
+
1 file changed, 1 insertion(+)
|
208
|
+
|
209
|
+
This looks a bit different than the `hotfix` merge you did earlier. In this case, your development history has diverged from some older point. Because the commit on the branch you’re on isn’t a direct ancestor of the branch you’re merging in, Git has to do some work. In this case, Git does a simple three-way merge, using the two snapshots pointed to by the branch tips and the common ancestor of the two. Figure 3-16 highlights the three snapshots that Git uses to do its merge in this case.
|
210
|
+
|
211
|
+
Insert 18333fig0316.png
|
212
|
+
Figure 3-16. Git automatically identifies the best common-ancestor merge base for branch merging.
|
213
|
+
|
214
|
+
Instead of just moving the branch pointer forward, Git creates a new snapshot that results from this three-way merge and automatically creates a new commit that points to it (see Figure 3-17). This is referred to as a merge commit and is special in that it has more than one parent.
|
215
|
+
|
216
|
+
It’s worth pointing out that Git determines the best common ancestor to use for its merge base; this is different than CVS or Subversion (before version 1.5), where the developer doing the merge has to figure out the best merge base for themselves. This makes merging a heck of a lot easier in Git than in these other systems.
|
217
|
+
|
218
|
+
Insert 18333fig0317.png
|
219
|
+
Figure 3-17. Git automatically creates a new commit object that contains the merged work.
|
220
|
+
|
221
|
+
Now that your work is merged in, you have no further need for the `iss53` branch. You can delete it and then manually close the ticket in your ticket-tracking system:
|
222
|
+
|
223
|
+
$ git branch -d iss53
|
224
|
+
|
225
|
+
### Basic Merge Conflicts ###
|
226
|
+
|
227
|
+
Occasionally, this process doesn’t go smoothly. If you changed the same part of the same file differently in the two branches you’re merging together, Git won’t be able to merge them cleanly. If your fix for issue #53 modified the same part of a file as the `hotfix`, you’ll get a merge conflict that looks something like this:
|
228
|
+
|
229
|
+
$ git merge iss53
|
230
|
+
Auto-merging index.html
|
231
|
+
CONFLICT (content): Merge conflict in index.html
|
232
|
+
Automatic merge failed; fix conflicts and then commit the result.
|
233
|
+
|
234
|
+
Git hasn’t automatically created a new merge commit. It has paused the process while you resolve the conflict. If you want to see which files are unmerged at any point after a merge conflict, you can run `git status`:
|
235
|
+
|
236
|
+
$ git status
|
237
|
+
On branch master
|
238
|
+
You have unmerged paths.
|
239
|
+
(fix conflicts and run "git commit")
|
240
|
+
|
241
|
+
Unmerged paths:
|
242
|
+
(use "git add <file>..." to mark resolution)
|
243
|
+
|
244
|
+
both modified: index.html
|
245
|
+
|
246
|
+
no changes added to commit (use "git add" and/or "git commit -a")
|
247
|
+
|
248
|
+
Anything that has merge conflicts and hasn’t been resolved is listed as unmerged. Git adds standard conflict-resolution markers to the files that have conflicts, so you can open them manually and resolve those conflicts. Your file contains a section that looks something like this:
|
249
|
+
|
250
|
+
<<<<<<< HEAD
|
251
|
+
<div id="footer">contact : email.support@github.com</div>
|
252
|
+
=======
|
253
|
+
<div id="footer">
|
254
|
+
please contact us at support@github.com
|
255
|
+
</div>
|
256
|
+
>>>>>>> iss53
|
257
|
+
|
258
|
+
This means the version in HEAD (your master branch, because that was what you had checked out when you ran your merge command) is the top part of that block (everything above the `=======`), while the version in your `iss53` branch looks like everything in the bottom part. In order to resolve the conflict, you have to either choose one side or the other or merge the contents yourself. For instance, you might resolve this conflict by replacing the entire block with this:
|
259
|
+
|
260
|
+
<div id="footer">
|
261
|
+
please contact us at email.support@github.com
|
262
|
+
</div>
|
263
|
+
|
264
|
+
This resolution has a little of each section, and I’ve fully removed the `<<<<<<<`, `=======`, and `>>>>>>>` lines. After you’ve resolved each of these sections in each conflicted file, run `git add` on each file to mark it as resolved. Staging the file marks it as resolved in Git.
|
265
|
+
If you want to use a graphical tool to resolve these issues, you can run `git mergetool`, which fires up an appropriate visual merge tool and walks you through the conflicts:
|
266
|
+
|
267
|
+
$ git mergetool
|
268
|
+
|
269
|
+
This message is displayed because 'merge.tool' is not configured.
|
270
|
+
See 'git mergetool --tool-help' or 'git help config' for more details.
|
271
|
+
'git mergetool' will now attempt to use one of the following tools:
|
272
|
+
opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge
|
273
|
+
Merging:
|
274
|
+
index.html
|
275
|
+
|
276
|
+
Normal merge conflict for 'index.html':
|
277
|
+
{local}: modified file
|
278
|
+
{remote}: modified file
|
279
|
+
Hit return to start merge resolution tool (opendiff):
|
280
|
+
|
281
|
+
If you want to use a merge tool other than the default (Git chose `opendiff` for me in this case because I ran the command on a Mac), you can see all the supported tools listed at the top after “... one of the following tools:”. Type the name of the tool you’d rather use. In Chapter 7, we’ll discuss how you can change this default value for your environment.
|
282
|
+
|
283
|
+
After you exit the merge tool, Git asks you if the merge was successful. If you tell the script that it was, it stages the file to mark it as resolved for you.
|
284
|
+
|
285
|
+
You can run `git status` again to verify that all conflicts have been resolved:
|
286
|
+
|
287
|
+
$ git status
|
288
|
+
On branch master
|
289
|
+
Changes to be committed:
|
290
|
+
(use "git reset HEAD <file>..." to unstage)
|
291
|
+
|
292
|
+
modified: index.html
|
293
|
+
|
294
|
+
|
295
|
+
If you’re happy with that, and you verify that everything that had conflicts has been staged, you can type `git commit` to finalize the merge commit. The commit message by default looks something like this:
|
296
|
+
|
297
|
+
Merge branch 'iss53'
|
298
|
+
|
299
|
+
Conflicts:
|
300
|
+
index.html
|
301
|
+
#
|
302
|
+
# It looks like you may be committing a merge.
|
303
|
+
# If this is not correct, please remove the file
|
304
|
+
# .git/MERGE_HEAD
|
305
|
+
# and try again.
|
306
|
+
#
|
307
|
+
|
308
|
+
You can modify that message with details about how you resolved the merge if you think it would be helpful to others looking at this merge in the future — why you did what you did, if it’s not obvious.
|
309
|
+
|
310
|
+
## Branch Management ##
|
311
|
+
|
312
|
+
Now that you’ve created, merged, and deleted some branches, let’s look at some branch-management tools that will come in handy when you begin using branches all the time.
|
313
|
+
|
314
|
+
The `git branch` command does more than just create and delete branches. If you run it with no arguments, you get a simple listing of your current branches:
|
315
|
+
|
316
|
+
$ git branch
|
317
|
+
iss53
|
318
|
+
* master
|
319
|
+
testing
|
320
|
+
|
321
|
+
Notice the `*` character that prefixes the `master` branch: it indicates the branch that you currently have checked out. This means that if you commit at this point, the `master` branch will be moved forward with your new work. To see the last commit on each branch, you can run `git branch -v`:
|
322
|
+
|
323
|
+
$ git branch -v
|
324
|
+
iss53 93b412c fix javascript issue
|
325
|
+
* master 7a98805 Merge branch 'iss53'
|
326
|
+
testing 782fd34 add scott to the author list in the readmes
|
327
|
+
|
328
|
+
Another useful option to figure out what state your branches are in is to filter this list to branches that you have or have not yet merged into the branch you’re currently on. There are useful `--merged` and `--no-merged` options available in Git for this purpose. To see which branches are already merged into the branch you’re on, you can run `git branch --merged`:
|
329
|
+
|
330
|
+
$ git branch --merged
|
331
|
+
iss53
|
332
|
+
* master
|
333
|
+
|
334
|
+
Because you already merged in `iss53` earlier, you see it in your list. Branches on this list without the `*` in front of them are generally fine to delete with `git branch -d`; you’ve already incorporated their work into another branch, so you’re not going to lose anything.
|
335
|
+
|
336
|
+
To see all the branches that contain work you haven’t yet merged in, you can run `git branch --no-merged`:
|
337
|
+
|
338
|
+
$ git branch --no-merged
|
339
|
+
testing
|
340
|
+
|
341
|
+
This shows your other branch. Because it contains work that isn’t merged in yet, trying to delete it with `git branch -d` will fail:
|
342
|
+
|
343
|
+
$ git branch -d testing
|
344
|
+
error: The branch 'testing' is not fully merged.
|
345
|
+
If you are sure you want to delete it, run 'git branch -D testing'.
|
346
|
+
|
347
|
+
If you really do want to delete the branch and lose that work, you can force it with `-D`, as the helpful message points out.
|
348
|
+
|
349
|
+
## Branching Workflows ##
|
350
|
+
|
351
|
+
Now that you have the basics of branching and merging down, what can or should you do with them? In this section, we’ll cover some common workflows that this lightweight branching makes possible, so you can decide if you would like to incorporate it into your own development cycle.
|
352
|
+
|
353
|
+
### Long-Running Branches ###
|
354
|
+
|
355
|
+
Because Git uses a simple three-way merge, merging from one branch into another multiple times over a long period is generally easy to do. This means you can have several branches that are always open and that you use for different stages of your development cycle; you can merge regularly from some of them into others.
|
356
|
+
|
357
|
+
Many Git developers have a workflow that embraces this approach, such as having only code that is entirely stable in their `master` branch — possibly only code that has been or will be released. They have another parallel branch named develop or next that they work from or use to test stability — it isn’t necessarily always stable, but whenever it gets to a stable state, it can be merged into `master`. It’s used to pull in topic branches (short-lived branches, like your earlier `iss53` branch) when they’re ready, to make sure they pass all the tests and don’t introduce bugs.
|
358
|
+
|
359
|
+
In reality, we’re talking about pointers moving up the line of commits you’re making. The stable branches are farther down the line in your commit history, and the bleeding-edge branches are farther up the history (see Figure 3-18).
|
360
|
+
|
361
|
+
Insert 18333fig0318.png
|
362
|
+
Figure 3-18. More stable branches are generally farther down the commit history.
|
363
|
+
|
364
|
+
It’s generally easier to think about them as work silos, where sets of commits graduate to a more stable silo when they’re fully tested (see Figure 3-19).
|
365
|
+
|
366
|
+
Insert 18333fig0319.png
|
367
|
+
Figure 3-19. It may be helpful to think of your branches as silos.
|
368
|
+
|
369
|
+
You can keep doing this for several levels of stability. Some larger projects also have a `proposed` or `pu` (proposed updates) branch that has integrated branches that may not be ready to go into the `next` or `master` branch. The idea is that your branches are at various levels of stability; when they reach a more stable level, they’re merged into the branch above them.
|
370
|
+
Again, having multiple long-running branches isn’t necessary, but it’s often helpful, especially when you’re dealing with very large or complex projects.
|
371
|
+
|
372
|
+
### Topic Branches ###
|
373
|
+
|
374
|
+
Topic branches, however, are useful in projects of any size. A topic branch is a short-lived branch that you create and use for a single particular feature or related work. This is something you’ve likely never done with a VCS before because it’s generally too expensive to create and merge branches. But in Git it’s common to create, work on, merge, and delete branches several times a day.
|
375
|
+
|
376
|
+
You saw this in the last section with the `iss53` and `hotfix` branches you created. You did a few commits on them and deleted them directly after merging them into your main branch. This technique allows you to context-switch quickly and completely — because your work is separated into silos where all the changes in that branch have to do with that topic, it’s easier to see what has happened during code review and such. You can keep the changes there for minutes, days, or months, and merge them in when they’re ready, regardless of the order in which they were created or worked on.
|
377
|
+
|
378
|
+
Consider an example of doing some work (on `master`), branching off for an issue (`iss91`), working on it for a bit, branching off the second branch to try another way of handling the same thing (`iss91v2`), going back to your master branch and working there for a while, and then branching off there to do some work that you’re not sure is a good idea (`dumbidea` branch). Your commit history will look something like Figure 3-20.
|
379
|
+
|
380
|
+
Insert 18333fig0320.png
|
381
|
+
Figure 3-20. Your commit history with multiple topic branches.
|
382
|
+
|
383
|
+
Now, let’s say you decide you like the second solution to your issue best (`iss91v2`); and you showed the `dumbidea` branch to your coworkers, and it turns out to be genius. You can throw away the original `iss91` branch (losing commits C5 and C6) and merge in the other two. Your history then looks like Figure 3-21.
|
384
|
+
|
385
|
+
Insert 18333fig0321.png
|
386
|
+
Figure 3-21. Your history after merging in dumbidea and iss91v2.
|
387
|
+
|
388
|
+
It’s important to remember when you’re doing all this that these branches are completely local. When you’re branching and merging, everything is being done only in your Git repository — no server communication is happening.
|
389
|
+
|
390
|
+
## Remote Branches ##
|
391
|
+
|
392
|
+
Remote branches are references to the state of branches on your remote repositories. They’re local branches that you can’t move; they’re moved automatically whenever you do any network communication. Remote branches act as bookmarks to remind you where the branches on your remote repositories were the last time you connected to them.
|
393
|
+
|
394
|
+
They take the form `(remote)/(branch)`. For instance, if you wanted to see what the `master` branch on your `origin` remote looked like as of the last time you communicated with it, you would check the `origin/master` branch. If you were working on an issue with a partner and they pushed up an `iss53` branch, you might have your own local `iss53` branch; but the branch on the server would point to the commit at `origin/iss53`.
|
395
|
+
|
396
|
+
This may be a bit confusing, so let’s look at an example. Let’s say you have a Git server on your network at `git.ourcompany.com`. If you clone from this, Git automatically names it `origin` for you, pulls down all its data, creates a pointer to where its `master` branch is, and names it `origin/master` locally; and you can’t move it. Git also gives you your own `master` branch starting at the same place as origin’s `master` branch, so you have something to work from (see Figure 3-22).
|
397
|
+
|
398
|
+
Insert 18333fig0322.png
|
399
|
+
Figure 3-22. A Git clone gives you your own master branch and origin/master pointing to origin’s master branch.
|
400
|
+
|
401
|
+
If you do some work on your local master branch, and, in the meantime, someone else pushes to `git.ourcompany.com` and updates its master branch, then your histories move forward differently. Also, as long as you stay out of contact with your origin server, your `origin/master` pointer doesn’t move (see Figure 3-23).
|
402
|
+
|
403
|
+
Insert 18333fig0323.png
|
404
|
+
Figure 3-23. Working locally and having someone push to your remote server makes each history move forward differently.
|
405
|
+
|
406
|
+
To synchronize your work, you run a `git fetch origin` command. This command looks up which server origin is (in this case, it’s `git.ourcompany.com`), fetches any data from it that you don’t yet have, and updates your local database, moving your `origin/master` pointer to its new, more up-to-date position (see Figure 3-24).
|
407
|
+
|
408
|
+
Insert 18333fig0324.png
|
409
|
+
Figure 3-24. The `git fetch` command updates your remote references.
|
410
|
+
|
411
|
+
To demonstrate having multiple remote servers and what remote branches for those remote projects look like, let’s assume you have another internal Git server that is used only for development by one of your sprint teams. This server is at `git.team1.ourcompany.com`. You can add it as a new remote reference to the project you’re currently working on by running the `git remote add` command as we covered in Chapter 2. Name this remote `teamone`, which will be your shortname for that whole URL (see Figure 3-25).
|
412
|
+
|
413
|
+
Insert 18333fig0325.png
|
414
|
+
Figure 3-25. Adding another server as a remote.
|
415
|
+
|
416
|
+
Now, you can run `git fetch teamone` to fetch everything the remote `teamone` server has that you don’t have yet. Because that server has a subset of the data your `origin` server has right now, Git fetches no data but sets a remote branch called `teamone/master` to point to the commit that `teamone` has as its `master` branch (see Figure 3-26).
|
417
|
+
|
418
|
+
Insert 18333fig0326.png
|
419
|
+
Figure 3-26. You get a reference to teamone’s master branch position locally.
|
420
|
+
|
421
|
+
### Pushing ###
|
422
|
+
|
423
|
+
When you want to share a branch with the world, you need to push it up to a remote that you have write access to. Your local branches aren’t automatically synchronized to the remotes you write to — you have to explicitly push the branches you want to share. That way, you can use private branches for work you don’t want to share, and push up only the topic branches you want to collaborate on.
|
424
|
+
|
425
|
+
If you have a branch named `serverfix` that you want to work on with others, you can push it up the same way you pushed your first branch. Run `git push (remote) (branch)`:
|
426
|
+
|
427
|
+
$ git push origin serverfix
|
428
|
+
Counting objects: 20, done.
|
429
|
+
Compressing objects: 100% (14/14), done.
|
430
|
+
Writing objects: 100% (15/15), 1.74 KiB, done.
|
431
|
+
Total 15 (delta 5), reused 0 (delta 0)
|
432
|
+
To git@github.com:schacon/simplegit.git
|
433
|
+
* [new branch] serverfix -> serverfix
|
434
|
+
|
435
|
+
This is a bit of a shortcut. Git automatically expands the `serverfix` branchname out to `refs/heads/serverfix:refs/heads/serverfix`, which means, “Take my serverfix local branch and push it to update the remote’s serverfix branch.” We’ll go over the `refs/heads/` part in detail in Chapter 9, but you can generally leave it off. You can also do `git push origin serverfix:serverfix`, which does the same thing — it says, “Take my serverfix and make it the remote’s serverfix.” You can use this format to push a local branch into a remote branch that is named differently. If you didn’t want it to be called `serverfix` on the remote, you could instead run `git push origin serverfix:awesomebranch` to push your local `serverfix` branch to the `awesomebranch` branch on the remote project.
|
436
|
+
|
437
|
+
The next time one of your collaborators fetches from the server, they will get a reference to where the server’s version of `serverfix` is under the remote branch `origin/serverfix`:
|
438
|
+
|
439
|
+
$ git fetch origin
|
440
|
+
remote: Counting objects: 20, done.
|
441
|
+
remote: Compressing objects: 100% (14/14), done.
|
442
|
+
remote: Total 15 (delta 5), reused 0 (delta 0)
|
443
|
+
Unpacking objects: 100% (15/15), done.
|
444
|
+
From git@github.com:schacon/simplegit
|
445
|
+
* [new branch] serverfix -> origin/serverfix
|
446
|
+
|
447
|
+
It’s important to note that when you do a fetch that brings down new remote branches, you don’t automatically have local, editable copies of them. In other words, in this case, you don’t have a new `serverfix` branch — you only have an `origin/serverfix` pointer that you can’t modify.
|
448
|
+
|
449
|
+
To merge this work into your current working branch, you can run `git merge origin/serverfix`. If you want your own `serverfix` branch that you can work on, you can base it off your remote branch:
|
450
|
+
|
451
|
+
$ git checkout -b serverfix origin/serverfix
|
452
|
+
Branch serverfix set up to track remote branch serverfix from origin.
|
453
|
+
Switched to a new branch 'serverfix'
|
454
|
+
|
455
|
+
This gives you a local branch that you can work on that starts where `origin/serverfix` is.
|
456
|
+
|
457
|
+
### Tracking Branches ###
|
458
|
+
|
459
|
+
Checking out a local branch from a remote branch automatically creates what is called a _tracking branch_. Tracking branches are local branches that have a direct relationship to a remote branch. If you’re on a tracking branch and type `git push`, Git automatically knows which server and branch to push to. Also, running `git pull` while on one of these branches fetches all the remote references and then automatically merges in the corresponding remote branch.
|
460
|
+
|
461
|
+
When you clone a repository, it generally automatically creates a `master` branch that tracks `origin/master`. That’s why `git push` and `git pull` work out of the box with no other arguments. However, you can set up other tracking branches if you wish — ones that don’t track branches on `origin` and don’t track the `master` branch. The simple case is the example you just saw, running `git checkout -b [branch] [remotename]/[branch]`. If you have Git version 1.6.2 or later, you can also use the `--track` shorthand:
|
462
|
+
|
463
|
+
$ git checkout --track origin/serverfix
|
464
|
+
Branch serverfix set up to track remote branch serverfix from origin.
|
465
|
+
Switched to a new branch 'serverfix'
|
466
|
+
|
467
|
+
To set up a local branch with a different name than the remote branch, you can easily use the first version with a different local branch name:
|
468
|
+
|
469
|
+
$ git checkout -b sf origin/serverfix
|
470
|
+
Branch sf set up to track remote branch serverfix from origin.
|
471
|
+
Switched to a new branch 'sf'
|
472
|
+
|
473
|
+
Now, your local branch `sf` will automatically push to and pull from `origin/serverfix`.
|
474
|
+
|
475
|
+
### Deleting Remote Branches ###
|
476
|
+
|
477
|
+
Suppose you’re done with a remote branch — say, you and your collaborators are finished with a feature and have merged it into your remote’s `master` branch (or whatever branch your stable codeline is in). You can delete a remote branch using the rather obtuse syntax `git push [remotename] :[branch]`. If you want to delete your `serverfix` branch from the server, you run the following:
|
478
|
+
|
479
|
+
$ git push origin :serverfix
|
480
|
+
To git@github.com:schacon/simplegit.git
|
481
|
+
- [deleted] serverfix
|
482
|
+
|
483
|
+
Boom. No more branch on your server. You may want to dog-ear this page, because you’ll need that command, and you’ll likely forget the syntax. A way to remember this command is by recalling the `git push [remotename] [localbranch]:[remotebranch]` syntax that we went over a bit earlier. If you leave off the `[localbranch]` portion, then you’re basically saying, “Take nothing on my side and make it be `[remotebranch]`.”
|
484
|
+
|
485
|
+
## Rebasing ##
|
486
|
+
|
487
|
+
In Git, there are two main ways to integrate changes from one branch into another: the `merge` and the `rebase`. In this section you’ll learn what rebasing is, how to do it, why it’s a pretty amazing tool, and in what cases you won’t want to use it.
|
488
|
+
|
489
|
+
### The Basic Rebase ###
|
490
|
+
|
491
|
+
If you go back to an earlier example from the Merge section (see Figure 3-27), you can see that you diverged your work and made commits on two different branches.
|
492
|
+
|
493
|
+
Insert 18333fig0327.png
|
494
|
+
Figure 3-27. Your initial diverged commit history.
|
495
|
+
|
496
|
+
The easiest way to integrate the branches, as we’ve already covered, is the `merge` command. It performs a three-way merge between the two latest branch snapshots (C3 and C4) and the most recent common ancestor of the two (C2), creating a new snapshot (and commit), as shown in Figure 3-28.
|
497
|
+
|
498
|
+
Insert 18333fig0328.png
|
499
|
+
Figure 3-28. Merging a branch to integrate the diverged work history.
|
500
|
+
|
501
|
+
However, there is another way: you can take the patch of the change that was introduced in C3 and reapply it on top of C4. In Git, this is called _rebasing_. With the `rebase` command, you can take all the changes that were committed on one branch and replay them on another one.
|
502
|
+
|
503
|
+
In this example, you’d run the following:
|
504
|
+
|
505
|
+
$ git checkout experiment
|
506
|
+
$ git rebase master
|
507
|
+
First, rewinding head to replay your work on top of it...
|
508
|
+
Applying: added staged command
|
509
|
+
|
510
|
+
It works by going to the common ancestor of the two branches (the one you’re on and the one you’re rebasing onto), getting the diff introduced by each commit of the branch you’re on, saving those diffs to temporary files, resetting the current branch to the same commit as the branch you are rebasing onto, and finally applying each change in turn. Figure 3-29 illustrates this process.
|
511
|
+
|
512
|
+
Insert 18333fig0329.png
|
513
|
+
Figure 3-29. Rebasing the change introduced in C3 onto C4.
|
514
|
+
|
515
|
+
At this point, you can go back to the master branch and do a fast-forward merge (see Figure 3-30).
|
516
|
+
|
517
|
+
Insert 18333fig0330.png
|
518
|
+
Figure 3-30. Fast-forwarding the master branch.
|
519
|
+
|
520
|
+
Now, the snapshot pointed to by C3' is exactly the same as the one that was pointed to by C5 in the merge example. There is no difference in the end product of the integration, but rebasing makes for a cleaner history. If you examine the log of a rebased branch, it looks like a linear history: it appears that all the work happened in series, even when it originally happened in parallel.
|
521
|
+
|
522
|
+
Often, you’ll do this to make sure your commits apply cleanly on a remote branch — perhaps in a project to which you’re trying to contribute but that you don’t maintain. In this case, you’d do your work in a branch and then rebase your work onto `origin/master` when you were ready to submit your patches to the main project. That way, the maintainer doesn’t have to do any integration work — just a fast-forward or a clean apply.
|
523
|
+
|
524
|
+
Note that the snapshot pointed to by the final commit you end up with, whether it’s the last of the rebased commits for a rebase or the final merge commit after a merge, is the same snapshot — it’s only the history that is different. Rebasing replays changes from one line of work onto another in the order they were introduced, whereas merging takes the endpoints and merges them together.
|
525
|
+
|
526
|
+
### More Interesting Rebases ###
|
527
|
+
|
528
|
+
You can also have your rebase replay on something other than the rebase branch. Take a history like Figure 3-31, for example. You branched a topic branch (`server`) to add some server-side functionality to your project, and made a commit. Then, you branched off that to make the client-side changes (`client`) and committed a few times. Finally, you went back to your server branch and did a few more commits.
|
529
|
+
|
530
|
+
Insert 18333fig0331.png
|
531
|
+
Figure 3-31. A history with a topic branch off another topic branch.
|
532
|
+
|
533
|
+
Suppose you decide that you want to merge your client-side changes into your mainline for a release, but you want to hold off on the server-side changes until it’s tested further. You can take the changes on client that aren’t on server (C8 and C9) and replay them on your master branch by using the `--onto` option of `git rebase`:
|
534
|
+
|
535
|
+
$ git rebase --onto master server client
|
536
|
+
|
537
|
+
This basically says, “Check out the client branch, figure out the patches from the common ancestor of the `client` and `server` branches, and then replay them onto `master`.” It’s a bit complex; but the result, shown in Figure 3-32, is pretty cool.
|
538
|
+
|
539
|
+
Insert 18333fig0332.png
|
540
|
+
Figure 3-32. Rebasing a topic branch off another topic branch.
|
541
|
+
|
542
|
+
Now you can fast-forward your master branch (see Figure 3-33):
|
543
|
+
|
544
|
+
$ git checkout master
|
545
|
+
$ git merge client
|
546
|
+
|
547
|
+
Insert 18333fig0333.png
|
548
|
+
Figure 3-33. Fast-forwarding your master branch to include the client branch changes.
|
549
|
+
|
550
|
+
Let’s say you decide to pull in your server branch as well. You can rebase the server branch onto the master branch without having to check it out first by running `git rebase [basebranch] [topicbranch]` — which checks out the topic branch (in this case, `server`) for you and replays it onto the base branch (`master`):
|
551
|
+
|
552
|
+
$ git rebase master server
|
553
|
+
|
554
|
+
This replays your `server` work on top of your `master` work, as shown in Figure 3-34.
|
555
|
+
|
556
|
+
Insert 18333fig0334.png
|
557
|
+
Figure 3-34. Rebasing your server branch on top of your master branch.
|
558
|
+
|
559
|
+
Then, you can fast-forward the base branch (`master`):
|
560
|
+
|
561
|
+
$ git checkout master
|
562
|
+
$ git merge server
|
563
|
+
|
564
|
+
You can remove the `client` and `server` branches because all the work is integrated and you don’t need them anymore, leaving your history for this entire process looking like Figure 3-35:
|
565
|
+
|
566
|
+
$ git branch -d client
|
567
|
+
$ git branch -d server
|
568
|
+
|
569
|
+
Insert 18333fig0335.png
|
570
|
+
Figure 3-35. Final commit history.
|
571
|
+
|
572
|
+
### The Perils of Rebasing ###
|
573
|
+
|
574
|
+
Ahh, but the bliss of rebasing isn’t without its drawbacks, which can be summed up in a single line:
|
575
|
+
|
576
|
+
**Do not rebase commits that you have pushed to a public repository.**
|
577
|
+
|
578
|
+
If you follow that guideline, you’ll be fine. If you don’t, people will hate you, and you’ll be scorned by friends and family.
|
579
|
+
|
580
|
+
When you rebase stuff, you’re abandoning existing commits and creating new ones that are similar but different. If you push commits somewhere and others pull them down and base work on them, and then you rewrite those commits with `git rebase` and push them up again, your collaborators will have to re-merge their work and things will get messy when you try to pull their work back into yours.
|
581
|
+
|
582
|
+
Let’s look at an example of how rebasing work that you’ve made public can cause problems. Suppose you clone from a central server and then do some work off that. Your commit history looks like Figure 3-36.
|
583
|
+
|
584
|
+
Insert 18333fig0336.png
|
585
|
+
Figure 3-36. Clone a repository, and base some work on it.
|
586
|
+
|
587
|
+
Now, someone else does more work that includes a merge, and pushes that work to the central server. You fetch them and merge the new remote branch into your work, making your history look something like Figure 3-37.
|
588
|
+
|
589
|
+
Insert 18333fig0337.png
|
590
|
+
Figure 3-37. Fetch more commits, and merge them into your work.
|
591
|
+
|
592
|
+
Next, the person who pushed the merged work decides to go back and rebase their work instead; they do a `git push --force` to overwrite the history on the server. You then fetch from that server, bringing down the new commits.
|
593
|
+
|
594
|
+
Insert 18333fig0338.png
|
595
|
+
Figure 3-38. Someone pushes rebased commits, abandoning commits you’ve based your work on.
|
596
|
+
|
597
|
+
At this point, you have to merge this work in again, even though you’ve already done so. Rebasing changes the SHA-1 hashes of these commits so to Git they look like new commits, when in fact you already have the C4 work in your history (see Figure 3-39).
|
598
|
+
|
599
|
+
Insert 18333fig0339.png
|
600
|
+
Figure 3-39. You merge in the same work again into a new merge commit.
|
601
|
+
|
602
|
+
You have to merge that work in at some point so you can keep up with the other developer in the future. After you do that, your commit history will contain both the C4 and C4' commits, which have different SHA-1 hashes but introduce the same work and have the same commit message. If you run a `git log` when your history looks like this, you’ll see two commits that have the same author date and message, which will be confusing. Furthermore, if you push this history back up to the server, you’ll reintroduce all those rebased commits to the central server, which can further confuse people.
|
603
|
+
|
604
|
+
If you treat rebasing as a way to clean up and work with commits before you push them, and if you only rebase commits that have never been available publicly, then you’ll be fine. If you rebase commits that have already been pushed publicly, and people may have based work on those commits, then you may be in for some frustrating trouble.
|
605
|
+
|
606
|
+
## Summary ##
|
607
|
+
|
608
|
+
We’ve covered basic branching and merging in Git. You should feel comfortable creating and switching to new branches, switching between branches and merging local branches together. You should also be able to share your branches by pushing them to a shared server, working with others on shared branches and rebasing your branches before they are shared.
|