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,1144 @@
|
|
1
|
+
# Strumenti di Git #
|
2
|
+
|
3
|
+
Finora hai imparato la maggior parte dei comandi d’uso quotidiani e i flussi di lavoro che devi conoscere per gestire o mantenere un repository Git per i tuoi sorgenti. Hai eseguito le attività di base per tracciare e committare i file, hai sfruttato il potere dell' *area di assemblamento* e le diramazioni (*branch*) e le unioni (*merge*) leggere.
|
4
|
+
|
5
|
+
Ora vedremo una serie di cose molto potenti di Git che potresti non usare quotidianamente, ma di cui a un certo punto potresti averne bisogno.
|
6
|
+
|
7
|
+
## Selezione della revisione ##
|
8
|
+
|
9
|
+
Git ti permette di specificare una o più *commit* in diversi modi. Non sono sempre ovvi, ma è utile conoscerli.
|
10
|
+
|
11
|
+
### Singole versioni ###
|
12
|
+
|
13
|
+
Puoi fare riferimento a una singola commit usando l’hash SHA-1 attribuito, ma ci sono altri metodi più amichevoli per fare riferimento a una *commit*. Questa sezione delinea i modi con cui ci si può riferire a una singolo commit.
|
14
|
+
|
15
|
+
### SHA breve ###
|
16
|
+
|
17
|
+
Git è abbastanza intelligente da capire a quale *commit* ti riferisci se scrivi i primi caratteri purché il codice SHA-1 sia di almeno quattro caratteri e sia univoco: ovvero che uno solo degli oggetti nel *repository* inizi con quel SHA-1.
|
18
|
+
|
19
|
+
Per vedere per esempio una specifica *commit*, immagina di eseguire 'git log' e trovi la *commit* dove sono state aggiunte determinate funzionalità:
|
20
|
+
|
21
|
+
$ git log
|
22
|
+
commit 734713bc047d87bf7eac9674765ae793478c50d3
|
23
|
+
Author: Scott Chacon <schacon@gmail.com>
|
24
|
+
Date: Fri Jan 2 18:32:33 2009 -0800
|
25
|
+
|
26
|
+
fixed refs handling, added gc auto, updated tests
|
27
|
+
|
28
|
+
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
|
29
|
+
Merge: 1c002dd... 35cfb2b...
|
30
|
+
Author: Scott Chacon <schacon@gmail.com>
|
31
|
+
Date: Thu Dec 11 15:08:43 2008 -0800
|
32
|
+
|
33
|
+
Merge commit 'phedders/rdocs'
|
34
|
+
|
35
|
+
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
|
36
|
+
Author: Scott Chacon <schacon@gmail.com>
|
37
|
+
Date: Thu Dec 11 14:58:32 2008 -0800
|
38
|
+
|
39
|
+
added some blame and merge stuff
|
40
|
+
|
41
|
+
In questo caso scegli '1c002dd....'. Se vuoi eseguire 'git show' su quella *commit*, i seguenti comandi sono equivalenti (assumendo che le versioni più brevi siano univoche):
|
42
|
+
|
43
|
+
$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
|
44
|
+
$ git show 1c002dd4b536e7479f
|
45
|
+
$ git show 1c002d
|
46
|
+
|
47
|
+
Git riesce a capire un valore SHA-1 intero da uno corto, abbreviato. Se usi l’opzione '--abbrev-commit' col comando 'git-log', l'*output* userà valori più corti ma garantirà che siano unici: di default usa sette caratteri ma ne userà di più se sarà necessario per mantenere l’univocità del valore SHA-1:
|
48
|
+
|
49
|
+
$ git log --abbrev-commit --pretty=oneline
|
50
|
+
ca82a6d changed the version number
|
51
|
+
085bb3b removed unnecessary test code
|
52
|
+
a11bef0 first commit
|
53
|
+
|
54
|
+
Da otto a dieci caratteri sono, generalmente, più che sufficienti per essere univoci all'interno di un progetto. Uno dei progetti Git più grandi, il kernel di Linux, inizia a necessitare 12 caratteri, dei 40 possibili, per essere univoco.
|
55
|
+
|
56
|
+
### Una breve nota su SHA-1 ###
|
57
|
+
|
58
|
+
Molte persone si preoccupa che a un certo punto, in modo del tutto casuale, ci possano essere due oggetti nel tuo *repository* che abbiano lo stesso SHA-1. Cosa succederebbe?
|
59
|
+
|
60
|
+
Se dovessi committare un oggetto che abbia lo stesso hash SHA-1 di un altro oggetto che sia già nel tuo repository, Git troverà l'altro oggetto già nel database di Git e lo considererà già scritto. Se in seguito vorrai scaricare quest'ultimo ogetto, otterrai sempre le informazioni del più vecchio.
|
61
|
+
|
62
|
+
Dovresti comunque essere consapevole che questo sia uno scenario molto improbabile. Il codice SHA-1 è di 20 bytes o 160 bits. Il numero di oggetti casuali necessari perché ci sia la probabilità del 50% di una singola collisione è di circa 2^80 (la formula per determinare la probabilità di collisione è `p = (n(n-1)/2) * (1/2^160)`). 2^80 è 1.2 x 10^24 ovvero 1 milione di miliardi di miliardi. È 1.200 volte il numero di granelli di sabbia sulla terra.
|
63
|
+
|
64
|
+
Ecco un esempio per dare un'idea di cosa ci vorrebbe per ottenere una collisione SHA-1. Se tutti i 6.5 miliardi di esseri umani sulla Terra programmassero e, ogni secondo, ognuno scrivesse codice che sia equivalente all'intera cronologia del kernel Linux (1 milione di oggetti Git) e ne facesse la push su un enorme *repository* Git, ci vorrebbero 5 anni per contenere abbastanza oggetti in quel *repository* per avere il 50% di possibilità di una singola collisione di oggetti SHA-1. Esiste una probabilità più alta che ogni membro del tuo gruppo di sviluppo, in incidenti non correlati venga attaccato e ucciso da dei lupi nella stessa notte.
|
65
|
+
|
66
|
+
### Riferimenti alle diramazioni ###
|
67
|
+
|
68
|
+
Il modo più diretto per specificare una *commit* è avere una diramazione (*branch* in inglese) che vi faccia riferimento, che ti permetterebbe di usare il nome della diramazione in qualsiasi comando Git che richieda un oggetto *commit* o un valore SHA-1. Se per esempio vuoi vedere l'ultima *commit* di una diramazione, i comandi seguenti sono equivalenti (supponendo che la diramazione 'topic1' punti a 'ca82a6d'):
|
69
|
+
|
70
|
+
$ git show ca82a6dff817ec66f44342007202690a93763949
|
71
|
+
$ git show topic1
|
72
|
+
|
73
|
+
Se vuoi vedere a quale SHA specifico punti una diramazione, o se vuoi vedere a quali SHA puntino questi esempi, puoi usare il comando 'rev-parse' di Git, che fa parte dei comandi sottotraccia (*plumbing* in inglese) . Nel Capitolo 9 trovi maggiori informazioni sui comandi sottotraccia ma, brevemente, 'rev-parse' esiste per operazioni di basso livello e non è concepito per essere usato nelle operazioni quotidiane. Può comunque essere d'aiuto quando hai bisogno di vedere cosa sta succedendo davvero. Qui puoi quindi eseguire 'rev-parse' sulla tua diramazione.
|
74
|
+
|
75
|
+
$ git rev-parse topic1
|
76
|
+
ca82a6dff817ec66f44342007202690a93763949
|
77
|
+
|
78
|
+
### Nomi brevi dei riferimenti ###
|
79
|
+
|
80
|
+
Una delle cose che Git fa dietro le quinte è aggiornare il registro dei riferimenti (*reflog* in inglese), che registra la posizione dei tuoi riferimenti HEAD e delle diramazione su cui hai lavorato negli ulti mesi.
|
81
|
+
|
82
|
+
Puoi consultare il registro con il comando 'git reflog':
|
83
|
+
|
84
|
+
$ git reflog
|
85
|
+
734713b HEAD@{0}: commit: fixed refs handling, added gc auto, updated
|
86
|
+
d921970 HEAD@{1}: merge phedders/rdocs: Merge made by recursive.
|
87
|
+
1c002dd HEAD@{2}: commit: added some blame and merge stuff
|
88
|
+
1c36188 HEAD@{3}: rebase -i (squash): updating HEAD
|
89
|
+
95df984 HEAD@{4}: commit: # This is a combination of two commits.
|
90
|
+
1c36188 HEAD@{5}: rebase -i (squash): updating HEAD
|
91
|
+
7e05da5 HEAD@{6}: rebase -i (pick): updating HEAD
|
92
|
+
|
93
|
+
Ogni volta che una diramazione viene aggiornata per qualsiasi ragione, Git memorizza questa informazione in questa cronologia temporanea. E puoi anche specificare *commit* più vecchie. Se vuoi vedere la cronologia a partire dalla quintultima commit a partire dalla *HEAD* del tuo *repository*, puoi usare il riferimento '@{n}' che vedi nel *output* del registro:
|
94
|
+
|
95
|
+
$ git show HEAD@{5}
|
96
|
+
|
97
|
+
Puoi anche usare questa sintassi per vedere dov'era una diramazione a una certa data. Se vuoi vedere, per esempio, dov'era ieri la diramazione 'master' puoi scrivere:
|
98
|
+
|
99
|
+
$ git show master@{yesterday}
|
100
|
+
|
101
|
+
Che mostra dov'era ieri la diramazione. Questa tecnica funziona solo per i dati che sono ancora nel registri e non puoi quindi usarla per vedere *commit* più vecchie di qualche mese.
|
102
|
+
|
103
|
+
Per vedere le informazioni del registro formattate come l’output di `git log`, puoi eseguire il comando `git log -g`:
|
104
|
+
|
105
|
+
$ git log -g master
|
106
|
+
commit 734713bc047d87bf7eac9674765ae793478c50d3
|
107
|
+
Reflog: master@{0} (Scott Chacon <schacon@gmail.com>)
|
108
|
+
Reflog message: commit: fixed refs handling, added gc auto, updated
|
109
|
+
Author: Scott Chacon <schacon@gmail.com>
|
110
|
+
Date: Fri Jan 2 18:32:33 2009 -0800
|
111
|
+
|
112
|
+
fixed refs handling, added gc auto, updated tests
|
113
|
+
|
114
|
+
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
|
115
|
+
Reflog: master@{1} (Scott Chacon <schacon@gmail.com>)
|
116
|
+
Reflog message: merge phedders/rdocs: Merge made by recursive.
|
117
|
+
Author: Scott Chacon <schacon@gmail.com>
|
118
|
+
Date: Thu Dec 11 15:08:43 2008 -0800
|
119
|
+
|
120
|
+
Merge commit 'phedders/rdocs'
|
121
|
+
|
122
|
+
E' importante notare che l'informazione del registro è solamente locale: è un registro di ciò che hai fatto nel tuo *repository*. I riferimenti non saranno uguali sui cloni degli altri. Appena dopo aver clonato un *repository* il tuo registro sarà vuoto perché non è successo ancora nulla nel tuo *repository*. Potrai eseguire 'git show HEAD@{2.months.ago}' solo se hai clonato il progetto almeno due mesi fa: se è stato clonato cinque minuti fa non otterrai nessun risultato.
|
123
|
+
|
124
|
+
### Riferimenti ancestrali ###
|
125
|
+
|
126
|
+
L'altro modo principale per specificare una *commit* è attraverso i suoi ascendenti. Se metti un `^` alla fine di un riferimento, Git lo risolve interpretandolo come il padre padre di quella determinata *commit*.
|
127
|
+
Immagina di vedere la cronologia del tuo progetto:
|
128
|
+
|
129
|
+
$ git log --pretty=format:'%h %s' --graph
|
130
|
+
* 734713b fixed refs handling, added gc auto, updated tests
|
131
|
+
* d921970 Merge commit 'phedders/rdocs'
|
132
|
+
|\
|
133
|
+
| * 35cfb2b Some rdoc changes
|
134
|
+
* | 1c002dd added some blame and merge stuff
|
135
|
+
|/
|
136
|
+
* 1c36188 ignore *.gem
|
137
|
+
* 9b29157 add open3_detach to gemspec file list
|
138
|
+
|
139
|
+
Puoi quindi vedere la *commit* precedente specificando `HEAD^`, che significa "l'ascendente di HEAD":
|
140
|
+
|
141
|
+
$ git show HEAD^
|
142
|
+
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
|
143
|
+
Merge: 1c002dd... 35cfb2b...
|
144
|
+
Author: Scott Chacon <schacon@gmail.com>
|
145
|
+
Date: Thu Dec 11 15:08:43 2008 -0800
|
146
|
+
|
147
|
+
Merge commit 'phedders/rdocs'
|
148
|
+
|
149
|
+
Puoi specificare anche un numero dopo la `^`: per esempio `d921970^2` significa "il secondo ascendente di d921870." Questa sintassi è utile solo per incorporare delle *commit* che hanno più di un ascendente. Il primo ascendente è la diramazione dove ti trovi al momento dell'incorporamento, e il secondo è la *commit* sulla diramazione da cui hai fatto l'incorporamento:
|
150
|
+
|
151
|
+
$ git show d921970^
|
152
|
+
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
|
153
|
+
Author: Scott Chacon <schacon@gmail.com>
|
154
|
+
Date: Thu Dec 11 14:58:32 2008 -0800
|
155
|
+
|
156
|
+
added some blame and merge stuff
|
157
|
+
|
158
|
+
$ git show d921970^2
|
159
|
+
commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548
|
160
|
+
Author: Paul Hedderly <paul+git@mjr.org>
|
161
|
+
Date: Wed Dec 10 22:22:03 2008 +0000
|
162
|
+
|
163
|
+
Some rdoc changes
|
164
|
+
|
165
|
+
Un altro modo di specificare un riferimento ancestrale è la `~`. Questo si riferisce anche al primo ascendente, quindi `HEAD~` e `HEAD^` sono equivalenti. La differenza diventa evidente quando specifichi un numero. `HEAD~2` significa "il primo ascendente del primo ascendente", o "il nonno”: attraversa i primi ascendenti il numero di volte specificato. Per esempio, nella cronologia precedente, `HEAD~3` sarebbe
|
166
|
+
|
167
|
+
$ git show HEAD~3
|
168
|
+
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
|
169
|
+
Author: Tom Preston-Werner <tom@mojombo.com>
|
170
|
+
Date: Fri Nov 7 13:47:59 2008 -0500
|
171
|
+
|
172
|
+
ignore *.gem
|
173
|
+
|
174
|
+
Che può essere scritto anche come `HEAD^^^` che, di nuovo, è sempre il primo genitore del primo genitore del primo genitore:
|
175
|
+
|
176
|
+
$ git show HEAD^^^
|
177
|
+
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
|
178
|
+
Author: Tom Preston-Werner <tom@mojombo.com>
|
179
|
+
Date: Fri Nov 7 13:47:59 2008 -0500
|
180
|
+
|
181
|
+
ignore *.gem
|
182
|
+
|
183
|
+
È anche possibile combinare queste sintassi: puoi prendere il secondo genitore del riferimento precedente (assumendo che si tratti di una commit d'incorporamento) usando `HEAD~3^2`, e così via.
|
184
|
+
|
185
|
+
### Intervalli di commit ###
|
186
|
+
|
187
|
+
Ora che sai come specificare singole commit, vediamo come specificare intervalli di commit. Ciò è particolarmente utile per gestire le tue diramazioni: se ne hai molte puoi usare gli intervalli per rispondere a domande come “cosa c’è in questa diramazione che non ho ancora incorporato?”
|
188
|
+
|
189
|
+
#### Due punti ####
|
190
|
+
|
191
|
+
Il modo più comune per specificare un intervallo è con i due punti che, praticamente, chiede a Git di risolvere l’intervallo tra commit che sia raggiungibile da una commit, ma non dall’altra. Immaginiamo di avere la cronologia dell’immagine 6-1
|
192
|
+
|
193
|
+
Insert 18333fig0601.png
|
194
|
+
Figure 6-1. Esempio di cronologia per la selezione di intervalli.
|
195
|
+
|
196
|
+
Vuoi vedere cosa sia nella tua diramazione sperimentale che non sia ancora stato incorporato nella master: puoi chiedere a Git di mostrarti solo il registro delle commit con `master..experiment`: questo significa “tutte le commit raggiungibili da experiment che non lo siano da master”. Affinché questi esempi siano sintetici ma chiari, invece del registro effettivo di Git, userò le lettere degli oggetti commit del diagramma:
|
197
|
+
|
198
|
+
$ git log master..experiment
|
199
|
+
D
|
200
|
+
C
|
201
|
+
|
202
|
+
Se volessi invece vedere il contrario, ovvero tutte le commit in `master` che non siano in `experiment`, puoi invertire i nomi dei branch: `experiment..master` ti mostra tutto ciò che è in `master` e che non sia raggiungibile da `experiment`:
|
203
|
+
|
204
|
+
$ git log experiment..master
|
205
|
+
F
|
206
|
+
E
|
207
|
+
|
208
|
+
Questo è utile se vuoi mantenere aggiornata la diramazione `experiment` e sapere cosa stai per incorporare. Un’altro caso in cui si usa spesso questa sintassi è quando stai per condividere delle commit verso un repository remoto:
|
209
|
+
|
210
|
+
$ git log origin/master..HEAD
|
211
|
+
|
212
|
+
Questo comando mostra tutte le commit della tua diramazione che non sono in quella `master` del tuo repository remoto `origin`. Se esegui `git push` quando la tua diramazione attuale è associata a `origin/master`, le commit elencate da `git log origin/master..HEAD` saranno quelle che saranno inviate al server.
|
213
|
+
Puoi anche omettere una delle parti della sintassi, e Git assumerà che sia HEAD. Per esempio puoi ottenere lo stesso risultato dell’esempio precedente scrivendo `git log origin/master..`: Git sostituisce la parte mancante con HEAD.
|
214
|
+
|
215
|
+
#### Punti multipli ####
|
216
|
+
|
217
|
+
La sintassi dei due punti è utile come la stenografia, ma potresti voler specificare più di due branch per indicare la tua revisione, per vedere le commit che sono nelle varie diramazioni che non siano in quella attuale. Git ti permette di farlo sia con `^` che con l’opzione `--not` prima di ciascun riferimento del quale vuoi vedere le commit raggiungibili. Quindi questi tre comandi sono equivalenti:
|
218
|
+
|
219
|
+
$ git log refA..refB
|
220
|
+
$ git log ^refA refB
|
221
|
+
$ git log refB --not refA
|
222
|
+
|
223
|
+
Questo è interessante, perché con questa sintassi puoi specificare più di due riferimenti nella tua richiesta, cosa che non puoi fare con i due punti. Se per esempio vuoi vedere tutte le commit che siano raggiungibili da `refA` o da `refB` ma non da `refC` puoi usare una delle seguenti alternative:
|
224
|
+
|
225
|
+
$ git log refA refB ^refC
|
226
|
+
$ git log refA refB --not refC
|
227
|
+
|
228
|
+
Questo produce un sistema di revisione molto potente che dovrebbe aiutarti a capire cosa c’è nelle tue diramazioni.
|
229
|
+
|
230
|
+
#### Tre punti ####
|
231
|
+
|
232
|
+
L’ultima sintassi per la selezione di intervalli è quella dei tre punti, che indica tutte le commit raggiungibili da uno qualsiasi dei riferimenti ma non da entrambi. Rivedi la cronologia delle commit nella Figura 6-1.
|
233
|
+
Se vuoi vedere cosa ci sia nel `master` o in `experiment` ma non i riferimenti comuni, puoi eseguire
|
234
|
+
|
235
|
+
$ git log master...experiment
|
236
|
+
F
|
237
|
+
E
|
238
|
+
D
|
239
|
+
C
|
240
|
+
|
241
|
+
Che ti mostra l’output normale del `log` mostrando solo le informazioni di quelle quattro commit nell'ordinamento cronologico normale.
|
242
|
+
|
243
|
+
Un'opzione comunemente usata in questi casi con il comando `log` è il parametro `--left-right`, che mostra da che lato dell'intervallo si trovi ciascuna commit dell’intervallo selezionato, che rende le informazioni molto più utili:
|
244
|
+
|
245
|
+
$ git log --left-right master...experiment
|
246
|
+
< F
|
247
|
+
< E
|
248
|
+
> D
|
249
|
+
> C
|
250
|
+
|
251
|
+
Con questi strumenti puoi dire facilmente a Git quale o quali commit vuoi ispezionare.
|
252
|
+
|
253
|
+
## Assemblaggio interattivo ##
|
254
|
+
|
255
|
+
Git viene distribuito con un paio di script che rendono più semplice l'uso della riga di comando. In questo capitolo vedremo alcuni comandi interattivi che possono aiutarti a modellare le tue commit perché includano solo determinate combinazioni di parti dei file. Questi strumenti sono molto utili se modifichi molti file tutti assieme e poi decidi che vuoi distribuire le modifiche in più commit puntuali, piuttosto che un'unica grossa commit confusa. In questo modo puoi fare che le tue commit separino logicamente le tue modifiche e possano essere facilmente revisionate dagli altri sviluppatori con cui lavori.
|
256
|
+
Se esegui `git add` con le opzioni `-i` o `--interactive`, Git entrerà nella modalità interattiva, mostrandoti qualcosa del genere:
|
257
|
+
|
258
|
+
$ git add -i
|
259
|
+
staged unstaged path
|
260
|
+
1: unchanged +0/-1 TODO
|
261
|
+
2: unchanged +1/-1 index.html
|
262
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
263
|
+
|
264
|
+
*** Commands ***
|
265
|
+
1: status 2: update 3: revert 4: add untracked
|
266
|
+
5: patch 6: diff 7: quit 8: help
|
267
|
+
What now>
|
268
|
+
|
269
|
+
Come vedi, questo comando mostra una vista della tua area di assemblaggio molto diversa: sono le stesse informazioni che otterà con il comando `git status`, ma in maniera più succinta e con più informazioni. Sulla sinistra mostra le modifiche che stai assemblando e quelle non ancora assemblate sulla destra.
|
270
|
+
|
271
|
+
Dopo questa sezione c'è quella dei Comandi. Qui puoi fare una serie di cose, incluso assemblare file, disassemblarli, assemblare alcune parti dei file, aggiungere file non ancora tracciati e vedere le differenze con ciò che è già stato assemblato.
|
272
|
+
|
273
|
+
### Assemblare e disassemblare file ###
|
274
|
+
|
275
|
+
Se digiti `2` o `u` alla richiesta `What now>`, lo script ti chiederà quale file vuoi assemblare:
|
276
|
+
|
277
|
+
What now> 2
|
278
|
+
staged unstaged path
|
279
|
+
1: unchanged +0/-1 TODO
|
280
|
+
2: unchanged +1/-1 index.html
|
281
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
282
|
+
Update>>
|
283
|
+
|
284
|
+
Per assemblare i file TODO e index.html, puoi digitare i numeri:
|
285
|
+
|
286
|
+
Update>> 1,2
|
287
|
+
staged unstaged path
|
288
|
+
* 1: unchanged +0/-1 TODO
|
289
|
+
* 2: unchanged +1/-1 index.html
|
290
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
291
|
+
Update>>
|
292
|
+
|
293
|
+
L'asterisco (`*`) vicino a ogni file, significa che è stato selezionato per essere assemblato. Se premi INVIO alla richiesta `Update>>`, Git assembla tutto ciò che è stato selezionato:
|
294
|
+
|
295
|
+
Update>>
|
296
|
+
updated 2 paths
|
297
|
+
|
298
|
+
*** Commands ***
|
299
|
+
1: status 2: update 3: revert 4: add untracked
|
300
|
+
5: patch 6: diff 7: quit 8: help
|
301
|
+
What now> 1
|
302
|
+
staged unstaged path
|
303
|
+
1: +0/-1 nothing TODO
|
304
|
+
2: +1/-1 nothing index.html
|
305
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
306
|
+
|
307
|
+
Ora puoi vedere che i file TODO e index.html sono assemblati e simplegit.rb non lo è ancora. Se ora vuoi disassemblare il file TODO, devi digitare `3` o `r` (come `revert` - annullare):
|
308
|
+
|
309
|
+
*** Commands ***
|
310
|
+
1: status 2: update 3: revert 4: add untracked
|
311
|
+
5: patch 6: diff 7: quit 8: help
|
312
|
+
What now> 3
|
313
|
+
staged unstaged path
|
314
|
+
1: +0/-1 nothing TODO
|
315
|
+
2: +1/-1 nothing index.html
|
316
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
317
|
+
Revert>> 1
|
318
|
+
staged unstaged path
|
319
|
+
* 1: +0/-1 nothing TODO
|
320
|
+
2: +1/-1 nothing index.html
|
321
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
322
|
+
Revert>> [enter]
|
323
|
+
reverted one path
|
324
|
+
|
325
|
+
Rivedendo lo stato di Git, puoi vedere che hai disassemblato il file TODO:
|
326
|
+
|
327
|
+
*** Commands ***
|
328
|
+
1: status 2: update 3: revert 4: add untracked
|
329
|
+
5: patch 6: diff 7: quit 8: help
|
330
|
+
What now> 1
|
331
|
+
staged unstaged path
|
332
|
+
1: unchanged +0/-1 TODO
|
333
|
+
2: +1/-1 nothing index.html
|
334
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
335
|
+
|
336
|
+
Per vedere le differenze di ciò che hai assemblato puoi digitare `6` o `d` (come differenza). Ti mostrerà un elenco dei tuoi file assemblati, e potrai selezionare quelli di cui vuoi vedere le modifiche assemblate. Questo fa la stessa cosa del comando `git diff --cached`:
|
337
|
+
|
338
|
+
*** Commands ***
|
339
|
+
1: status 2: update 3: revert 4: add untracked
|
340
|
+
5: patch 6: diff 7: quit 8: help
|
341
|
+
What now> 6
|
342
|
+
staged unstaged path
|
343
|
+
1: +1/-1 nothing index.html
|
344
|
+
Review diff>> 1
|
345
|
+
diff --git a/index.html b/index.html
|
346
|
+
index 4d07108..4335f49 100644
|
347
|
+
--- a/index.html
|
348
|
+
+++ b/index.html
|
349
|
+
@@ -16,7 +16,7 @@ Date Finder
|
350
|
+
|
351
|
+
<p id="out">...</p>
|
352
|
+
|
353
|
+
-<div id="footer">contact : support@github.com</div>
|
354
|
+
+<div id="footer">contact : email.support@github.com</div>
|
355
|
+
|
356
|
+
<script type="text/javascript">
|
357
|
+
|
358
|
+
Con questi comandi elementari puoi usare la modalità interattiva per interaggire un po' più facilmente con l'area di assemblagio.
|
359
|
+
|
360
|
+
### Assemblare i pezzi ###
|
361
|
+
|
362
|
+
Git può anche assemblare solo alcune parti di un file e non il resto. Se per esempio fai due modifiche al tuo simplegit.rb file e vuoi assemblarne solo una, con Git puoi farlo molto semplicemente. Al `prompt` digita `5` o `p` (come pezzo, `patch` ndt). Git ti chiederà quali file vuoi assemblare parzialmente e, per ciascuna sezione dei file selezionati, mostrerà blocchi di differenze chiedendoti se vuoi assemblarle, una per una:
|
363
|
+
|
364
|
+
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
|
365
|
+
index dd5ecc4..57399e0 100644
|
366
|
+
--- a/lib/simplegit.rb
|
367
|
+
+++ b/lib/simplegit.rb
|
368
|
+
@@ -22,7 +22,7 @@ class SimpleGit
|
369
|
+
end
|
370
|
+
|
371
|
+
def log(treeish = 'master')
|
372
|
+
- command("git log -n 25 #{treeish}")
|
373
|
+
+ command("git log -n 30 #{treeish}")
|
374
|
+
end
|
375
|
+
|
376
|
+
def blame(path)
|
377
|
+
Stage this hunk [y,n,a,d,/,j,J,g,e,?]?
|
378
|
+
|
379
|
+
A questo punto hai molte opzioni. Digitando `?` vedrai la lista di ciò che puoi fare:
|
380
|
+
|
381
|
+
Assemblare questo blocco [y,n,a,d,/,j,J,g,e,?]? ?
|
382
|
+
y - assembla questo blocco
|
383
|
+
n - non assemblare questo blocco
|
384
|
+
a - assembla questo blocco e tutti gli altri rimanenti nel file
|
385
|
+
d - non assemblare questo blocco né gli altri rimanenti nel file
|
386
|
+
g - seleziona un blocco per continuare
|
387
|
+
/ - cerca un blocco con una regex
|
388
|
+
j - salta questo blocco e vedi il successivo saltato
|
389
|
+
J - salta questo blocco e vedi il prossimo blocco
|
390
|
+
k - salta questo blocco e vedi il precedente saltato
|
391
|
+
K - salta questo blocco e vedi il blocco precedente
|
392
|
+
s - dividi il blocco attuale in blocchi più piccoli
|
393
|
+
e - modifica manualmente il blocco attuale
|
394
|
+
? - mostra l'aiuto
|
395
|
+
|
396
|
+
Generalmente digiterai `y` o `n` se vuoi assemblare tutti i blocchi, ma assemblare tutti quelli di un file o saltarne qualcuno per decidere in un secondo momento può essere molto prezioso. Se assembli solo alcuni blocchi di un file ma non gli altri, lo stato del tuo repository sarà così:
|
397
|
+
|
398
|
+
What now> 1
|
399
|
+
staged unstaged path
|
400
|
+
1: unchanged +0/-1 TODO
|
401
|
+
2: +1/-1 nothing index.html
|
402
|
+
3: +1/-1 +4/-0 lib/simplegit.rb
|
403
|
+
|
404
|
+
È interessante lo stato di simplegit.rb, dove alcune righe sono assemblate ma non le altre. Hai assemblato parzialmente questo file. A questo punto puoi uscire dall'area interattiva ed eseguire `git commit` per committare la parte di file assemblata.
|
405
|
+
|
406
|
+
Non devi essere nell'area interattiva per assemblare solo una parte di un file: puoi avviare lo stesso script dalla riga di comando con `git add -p` o `git add --patch`.
|
407
|
+
|
408
|
+
## Accantonare ##
|
409
|
+
|
410
|
+
Spesso, mentre stai lavorando ad una parte del tuo progetto, le cose possono essere in uno stato confusionario e tu vuoi passare a un'altra ramificazione per lavorare per un po' a qualcosa di diverso. Il problema è che non vuoi committare qualcosa fatta a metà per poi tornarci in un secondo momento. La risposta a questo problema è il comando `git stash`.
|
411
|
+
|
412
|
+
Questo comando prende tutte le modifiche della tua cartella di lavoro — cioè tutti i file tracciati che hai modificato e le modifiche assemblate — e le accantona in una pila di modifiche incomplete che puoi riapplicare in qualsiasi momento.
|
413
|
+
|
414
|
+
### Accantona il tuo lavoro ###
|
415
|
+
|
416
|
+
Per dimostrare come funziona, vai nella cartella del tuo progetto e modifica un paio di file e assemblane alcuni. Se esegui `git status`, puoi vederne lo stato "sporco":
|
417
|
+
|
418
|
+
$ git status
|
419
|
+
# On branch master
|
420
|
+
# Changes to be committed:
|
421
|
+
# (use "git reset HEAD <file>..." to unstage)
|
422
|
+
#
|
423
|
+
# modified: index.html
|
424
|
+
#
|
425
|
+
# Changes not staged for commit:
|
426
|
+
# (use "git add <file>..." to update what will be committed)
|
427
|
+
#
|
428
|
+
# modified: lib/simplegit.rb
|
429
|
+
#
|
430
|
+
|
431
|
+
Ora vuoi passare a un'altra diramazione, ma non vuoi ancora committare il tuo lavoro perché non è ancora pronto; accantona quindi le tue modifiche. Per aggiungere un nuovo livello alla pila devi eseguire `git stash`:
|
432
|
+
|
433
|
+
$ git stash
|
434
|
+
Saved working directory and index state \
|
435
|
+
"WIP on master: 049d078 added the index file"
|
436
|
+
HEAD is now at 049d078 added the index file
|
437
|
+
(To restore them type "git stash apply")
|
438
|
+
|
439
|
+
La tua cartella di lavoro ora è pulita:
|
440
|
+
|
441
|
+
$ git status
|
442
|
+
# On branch master
|
443
|
+
nothing to commit, working directory clean
|
444
|
+
|
445
|
+
A questo punto puoi passare facilmente a un'altra diramazione e lavorare ad altro; le tue modifiche sono salvate nella tua pila di accantonamento. Per vedere cosa c'è nella tua pila usa `git stash list`:
|
446
|
+
|
447
|
+
$ git stash list
|
448
|
+
stash@{0}: WIP on master: 049d078 added the index file
|
449
|
+
stash@{1}: WIP on master: c264051 Revert "added file_size"
|
450
|
+
stash@{2}: WIP on master: 21d80a5 added number to log
|
451
|
+
|
452
|
+
In questo caso hai due accantonamenti precedenti, e hai così accesso a tre lavori differenti accantonati. Puoi riapplicare quello che hai appena accantonato usando il comando mostrato nell'output d'aiuto del comando che hai usato quanto hai accantonato le tue modifiche: `git stash apply`. Se vuoi applicare uno degli accantonamenti precedenti, puoi specificarlo usandone il nome così: `git stash apply stash@{2}`. Se non specifiche un accantonamento Git suppone che ti riferisca all'ultimo e prova ad applicarlo:
|
453
|
+
|
454
|
+
$ git stash apply
|
455
|
+
# On branch master
|
456
|
+
# Changes not staged for commit:
|
457
|
+
# (use "git add <file>..." to update what will be committed)
|
458
|
+
#
|
459
|
+
# modified: index.html
|
460
|
+
# modified: lib/simplegit.rb
|
461
|
+
#
|
462
|
+
|
463
|
+
Puoi vedere che Git ha rimodificato i file che aveva rimosso quando hai salvato l'accantonamento. In questo caso avevi una cartella di lavoro pulita quando provasti ad applicare l'accantonamento e stai provando a riappricarlo alla stessa ramificazione da cui l'avevi salvato; ma non è necessario avere una cartella pulita per applicare un accantonamento né che sia la stessa ramificazione. Puoi salvare un accantonamento da una ramificazione, passare a un'altra e applicare le modifiche accantonate. Nella tua cartella puoi anche avere modifiche non ancora committate quando applichi un accantonamento: Git ti darà un conflitto d'incorporamento nel caso che qualcosa non si possa applicare senza problemi.
|
464
|
+
|
465
|
+
Le modifiche vengono riapplicate ai tuoi file, ma quello che avevi assemblato ora non lo sono. Per farlo devi eseguire il comando `git stash apply` con il parametro `--index` perché provi a riapplicare le modifiche assemblate. Se lo avessi fatto ti saresti trovato nella stessa posizione originale:
|
466
|
+
|
467
|
+
$ git stash apply --index
|
468
|
+
# On branch master
|
469
|
+
# Changes to be committed:
|
470
|
+
# (use "git reset HEAD <file>..." to unstage)
|
471
|
+
#
|
472
|
+
# modified: index.html
|
473
|
+
#
|
474
|
+
# Changes not staged for commit:
|
475
|
+
# (use "git add <file>..." to update what will be committed)
|
476
|
+
#
|
477
|
+
# modified: lib/simplegit.rb
|
478
|
+
#
|
479
|
+
|
480
|
+
L'opzione `apply` prova solo ad applicare le modifiche assemblate: continua per averle nel tuo accantonamento. Per cancellare l'accantonamento devi eseguire `git stash drop` con il nome dell'accantonamento da rimuovere:
|
481
|
+
|
482
|
+
$ git stash list
|
483
|
+
stash@{0}: WIP on master: 049d078 added the index file
|
484
|
+
stash@{1}: WIP on master: c264051 Revert "added file_size"
|
485
|
+
stash@{2}: WIP on master: 21d80a5 added number to log
|
486
|
+
$ git stash drop stash@{0}
|
487
|
+
Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)
|
488
|
+
|
489
|
+
Puoi eseguire anche `git stash pop` per applicare l'accantonamento e cancellare immediatamente dopo.
|
490
|
+
|
491
|
+
### Annullare una modifica accantonata ###
|
492
|
+
|
493
|
+
In alcuni scenari potresti voler applicare delle modifiche accantonate, fare dell'altro lavoro e successivamente voler rimuovere le modifiche che venivano dall'accantonamento. Git non ha un comando `stash unapply`, ma è possibile ottenere lo stesso risultato richiamando la modifica associata all'accantonamento e applicarla al contrario:
|
494
|
+
|
495
|
+
$ git stash show -p stash@{0} | git apply -R
|
496
|
+
|
497
|
+
Di nuovo, se non specifichi un accantonamento, Git assume che sia l'ultimo:
|
498
|
+
|
499
|
+
$ git stash show -p | git apply -R
|
500
|
+
|
501
|
+
Puoi voler creare un alias per avere un comando `stash-unapply` nel tuo Git. Per esempio:
|
502
|
+
|
503
|
+
$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
|
504
|
+
$ git stash apply
|
505
|
+
$ #... work work work
|
506
|
+
$ git stash-unapply
|
507
|
+
|
508
|
+
### Creare una diramazione da un accantonamento ###
|
509
|
+
|
510
|
+
Se accantoni del lavoro e lo lasci lì mentre continui a lavorare per un po' nella diramazione da cui hai creato l'accantonamento, potresti avere dei problemi a riapplicarlo. Se l'applicazione prova a modificare un file che avevi modificato successivamente, otterrai un conflitto d'incorporazione e dovrai risolverlo. Se vuoi un modo facile per ritestare le modifiche accantonate, puoi eseguire il comando `git stash branch`, che crea una diramazione, scarica la commit dov'eri quando hai accantonato il tuo lavoro, lo riapplica e, se ci riesce senza problemi, cancella l'accantonamento:
|
511
|
+
|
512
|
+
$ git stash branch testchanges
|
513
|
+
Switched to a new branch "testchanges"
|
514
|
+
# On branch testchanges
|
515
|
+
# Changes to be committed:
|
516
|
+
# (use "git reset HEAD <file>..." to unstage)
|
517
|
+
#
|
518
|
+
# modified: index.html
|
519
|
+
#
|
520
|
+
# Changes not staged for commit:
|
521
|
+
# (use "git add <file>..." to update what will be committed)
|
522
|
+
#
|
523
|
+
# modified: lib/simplegit.rb
|
524
|
+
#
|
525
|
+
Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)
|
526
|
+
|
527
|
+
Questa è una bella accorciatoioa per recuperare il lavoro accantonato e lavorarci in una nuova diramazione.
|
528
|
+
|
529
|
+
## Riscrivere la storia ##
|
530
|
+
|
531
|
+
Molto spesso, lavorando con Git, you may want to revise your commit history for some reason. One of the great things about Git is that it allows you to make decisions at the last possible moment. You can decide what files go into which commits right before you commit with the staging area, you can decide that you didn’t mean to be working on something yet with the stash command, and you can rewrite commits that already happened so they look like they happened in a different way. This can involve changing the order of the commits, changing messages or modifying files in a commit, squashing together or splitting apart commits, or removing commits entirely — all before you share your work with others.
|
532
|
+
|
533
|
+
In this section, you’ll cover how to accomplish these very useful tasks so that you can make your commit history look the way you want before you share it with others.
|
534
|
+
<!-- da tradurre fino a riga 840 -->
|
535
|
+
### Changing the Last Commit ###
|
536
|
+
|
537
|
+
Changing your last commit is probably the most common rewriting of history that you’ll do. You’ll often want to do two basic things to your last commit: change the commit message, or change the snapshot you just recorded by adding, changing and removing files.
|
538
|
+
|
539
|
+
If you only want to modify your last commit message, it’s very simple:
|
540
|
+
|
541
|
+
$ git commit --amend
|
542
|
+
|
543
|
+
That drops you into your text editor, which has your last commit message in it, ready for you to modify the message. When you save and close the editor, the editor writes a new commit containing that message and makes it your new last commit.
|
544
|
+
|
545
|
+
If you’ve committed and then you want to change the snapshot you committed by adding or changing files, possibly because you forgot to add a newly created file when you originally committed, the process works basically the same way. You stage the changes you want by editing a file and running `git add` on it or `git rm` to a tracked file, and the subsequent `git commit --amend` takes your current staging area and makes it the snapshot for the new commit.
|
546
|
+
|
547
|
+
You need to be careful with this technique because amending changes the SHA-1 of the commit. It’s like a very small rebase — don’t amend your last commit if you’ve already pushed it.
|
548
|
+
|
549
|
+
### Changing Multiple Commit Messages ###
|
550
|
+
|
551
|
+
To modify a commit that is farther back in your history, you must move to more complex tools. Git doesn’t have a modify-history tool, but you can use the rebase tool to rebase a series of commits onto the HEAD they were originally based on instead of moving them to another one. With the interactive rebase tool, you can then stop after each commit you want to modify and change the message, add files, or do whatever you wish. You can run rebase interactively by adding the `-i` option to `git rebase`. You must indicate how far back you want to rewrite commits by telling the command which commit to rebase onto.
|
552
|
+
|
553
|
+
For example, if you want to change the last three commit messages, or any of the commit messages in that group, you supply as an argument to `git rebase -i` the parent of the last commit you want to edit, which is `HEAD~2^` or `HEAD~3`. It may be easier to remember the `~3` because you’re trying to edit the last three commits; but keep in mind that you’re actually designating four commits ago, the parent of the last commit you want to edit:
|
554
|
+
|
555
|
+
$ git rebase -i HEAD~3
|
556
|
+
|
557
|
+
Remember again that this is a rebasing command — every commit included in the range `HEAD~3..HEAD` will be rewritten, whether you change the message or not. Don’t include any commit you’ve already pushed to a central server — doing so will confuse other developers by providing an alternate version of the same change.
|
558
|
+
|
559
|
+
Running this command gives you a list of commits in your text editor that looks something like this:
|
560
|
+
|
561
|
+
pick f7f3f6d changed my name a bit
|
562
|
+
pick 310154e updated README formatting and added blame
|
563
|
+
pick a5f4a0d added cat-file
|
564
|
+
|
565
|
+
# Rebase 710f0f8..a5f4a0d onto 710f0f8
|
566
|
+
#
|
567
|
+
# Commands:
|
568
|
+
# p, pick = use commit
|
569
|
+
# r, reword = use commit, but edit the commit message
|
570
|
+
# e, edit = use commit, but stop for amending
|
571
|
+
# s, squash = use commit, but meld into previous commit
|
572
|
+
# f, fixup = like "squash", but discard this commit's log message
|
573
|
+
# x, exec = run command (the rest of the line) using shell
|
574
|
+
#
|
575
|
+
# These lines can be re-ordered; they are executed from top to bottom.
|
576
|
+
#
|
577
|
+
# If you remove a line here THAT COMMIT WILL BE LOST.
|
578
|
+
#
|
579
|
+
# However, if you remove everything, the rebase will be aborted.
|
580
|
+
#
|
581
|
+
# Note that empty commits are commented out
|
582
|
+
|
583
|
+
It’s important to note that these commits are listed in the opposite order than you normally see them using the `log` command. If you run a `log`, you see something like this:
|
584
|
+
|
585
|
+
$ git log --pretty=format:"%h %s" HEAD~3..HEAD
|
586
|
+
a5f4a0d added cat-file
|
587
|
+
310154e updated README formatting and added blame
|
588
|
+
f7f3f6d changed my name a bit
|
589
|
+
|
590
|
+
Notice the reverse order. The interactive rebase gives you a script that it’s going to run. It will start at the commit you specify on the command line (`HEAD~3`) and replay the changes introduced in each of these commits from top to bottom. It lists the oldest at the top, rather than the newest, because that’s the first one it will replay.
|
591
|
+
|
592
|
+
You need to edit the script so that it stops at the commit you want to edit. To do so, change the word pick to the word edit for each of the commits you want the script to stop after. For example, to modify only the third commit message, you change the file to look like this:
|
593
|
+
|
594
|
+
edit f7f3f6d changed my name a bit
|
595
|
+
pick 310154e updated README formatting and added blame
|
596
|
+
pick a5f4a0d added cat-file
|
597
|
+
|
598
|
+
When you save and exit the editor, Git rewinds you back to the last commit in that list and drops you on the command line with the following message:
|
599
|
+
|
600
|
+
<!-- This is actually weird, as the SHA-1 of 7482e0d is not present in the list,
|
601
|
+
nor is the commit message. Please review
|
602
|
+
-->
|
603
|
+
|
604
|
+
$ git rebase -i HEAD~3
|
605
|
+
Stopped at 7482e0d... updated the gemspec to hopefully work better
|
606
|
+
You can amend the commit now, with
|
607
|
+
|
608
|
+
git commit --amend
|
609
|
+
|
610
|
+
Once you’re satisfied with your changes, run
|
611
|
+
|
612
|
+
git rebase --continue
|
613
|
+
|
614
|
+
These instructions tell you exactly what to do. Type
|
615
|
+
|
616
|
+
$ git commit --amend
|
617
|
+
|
618
|
+
Change the commit message, and exit the editor. Then, run
|
619
|
+
|
620
|
+
$ git rebase --continue
|
621
|
+
|
622
|
+
This command will apply the other two commits automatically, and then you’re done. If you change pick to edit on more lines, you can repeat these steps for each commit you change to edit. Each time, Git will stop, let you amend the commit, and continue when you’re finished.
|
623
|
+
|
624
|
+
### Reordering Commits ###
|
625
|
+
|
626
|
+
You can also use interactive rebases to reorder or remove commits entirely. If you want to remove the "added cat-file" commit and change the order in which the other two commits are introduced, you can change the rebase script from this
|
627
|
+
|
628
|
+
pick f7f3f6d changed my name a bit
|
629
|
+
pick 310154e updated README formatting and added blame
|
630
|
+
pick a5f4a0d added cat-file
|
631
|
+
|
632
|
+
to this:
|
633
|
+
|
634
|
+
pick 310154e updated README formatting and added blame
|
635
|
+
pick f7f3f6d changed my name a bit
|
636
|
+
|
637
|
+
When you save and exit the editor, Git rewinds your branch to the parent of these commits, applies `310154e` and then `f7f3f6d`, and then stops. You effectively change the order of those commits and remove the "added cat-file" commit completely.
|
638
|
+
|
639
|
+
### Squashing Commits ###
|
640
|
+
|
641
|
+
It’s also possible to take a series of commits and squash them down into a single commit with the interactive rebasing tool. The script puts helpful instructions in the rebase message:
|
642
|
+
|
643
|
+
#
|
644
|
+
# Commands:
|
645
|
+
# p, pick = use commit
|
646
|
+
# r, reword = use commit, but edit the commit message
|
647
|
+
# e, edit = use commit, but stop for amending
|
648
|
+
# s, squash = use commit, but meld into previous commit
|
649
|
+
# f, fixup = like "squash", but discard this commit's log message
|
650
|
+
# x, exec = run command (the rest of the line) using shell
|
651
|
+
#
|
652
|
+
# These lines can be re-ordered; they are executed from top to bottom.
|
653
|
+
#
|
654
|
+
# If you remove a line here THAT COMMIT WILL BE LOST.
|
655
|
+
#
|
656
|
+
# However, if you remove everything, the rebase will be aborted.
|
657
|
+
#
|
658
|
+
# Note that empty commits are commented out
|
659
|
+
|
660
|
+
If, instead of "pick" or "edit", you specify "squash", Git applies both that change and the change directly before it and makes you merge the commit messages together. So, if you want to make a single commit from these three commits, you make the script look like this:
|
661
|
+
|
662
|
+
pick f7f3f6d changed my name a bit
|
663
|
+
squash 310154e updated README formatting and added blame
|
664
|
+
squash a5f4a0d added cat-file
|
665
|
+
|
666
|
+
When you save and exit the editor, Git applies all three changes and then puts you back into the editor to merge the three commit messages:
|
667
|
+
|
668
|
+
# This is a combination of 3 commits.
|
669
|
+
# The first commit's message is:
|
670
|
+
changed my name a bit
|
671
|
+
|
672
|
+
# This is the 2nd commit message:
|
673
|
+
|
674
|
+
updated README formatting and added blame
|
675
|
+
|
676
|
+
# This is the 3rd commit message:
|
677
|
+
|
678
|
+
added cat-file
|
679
|
+
|
680
|
+
When you save that, you have a single commit that introduces the changes of all three previous commits.
|
681
|
+
|
682
|
+
### Splitting a Commit ###
|
683
|
+
|
684
|
+
Splitting a commit undoes a commit and then partially stages and commits as many times as commits you want to end up with. For example, suppose you want to split the middle commit of your three commits. Instead of "updated README formatting and added blame", you want to split it into two commits: "updated README formatting" for the first, and "added blame" for the second. You can do that in the `rebase -i` script by changing the instruction on the commit you want to split to "edit":
|
685
|
+
|
686
|
+
pick f7f3f6d changed my name a bit
|
687
|
+
edit 310154e updated README formatting and added blame
|
688
|
+
pick a5f4a0d added cat-file
|
689
|
+
|
690
|
+
When you save and exit the editor, Git rewinds to the parent of the first commit in your list, applies the first commit (`f7f3f6d`), applies the second (`310154e`), and drops you to the console. There, you can do a mixed reset of that commit with `git reset HEAD^`, which effectively undoes that commit and leaves the modified files unstaged. Now you can take the changes that have been reset, and create multiple commits out of them. Simply stage and commit files until you have several commits, and run `git rebase --continue` when you’re done:
|
691
|
+
|
692
|
+
$ git reset HEAD^
|
693
|
+
$ git add README
|
694
|
+
$ git commit -m 'updated README formatting'
|
695
|
+
$ git add lib/simplegit.rb
|
696
|
+
$ git commit -m 'added blame'
|
697
|
+
$ git rebase --continue
|
698
|
+
|
699
|
+
Git applies the last commit (`a5f4a0d`) in the script, and your history looks like this:
|
700
|
+
|
701
|
+
$ git log -4 --pretty=format:"%h %s"
|
702
|
+
1c002dd added cat-file
|
703
|
+
9b29157 added blame
|
704
|
+
35cfb2b updated README formatting
|
705
|
+
f3cc40e changed my name a bit
|
706
|
+
|
707
|
+
Once again, this changes the SHAs of all the commits in your list, so make sure no commit shows up in that list that you’ve already pushed to a shared repository.
|
708
|
+
|
709
|
+
### The Nuclear Option: filter-branch ###
|
710
|
+
|
711
|
+
There is another history-rewriting option that you can use if you need to rewrite a larger number of commits in some scriptable way — for instance, changing your e-mail address globally or removing a file from every commit. The command is `filter-branch`, and it can rewrite huge swaths of your history, so you probably shouldn’t use it unless your project isn’t yet public and other people haven’t based work off the commits you’re about to rewrite. However, it can be very useful. You’ll learn a few of the common uses so you can get an idea of some of the things it’s capable of.
|
712
|
+
|
713
|
+
#### Removing a File from Every Commit ####
|
714
|
+
|
715
|
+
This occurs fairly commonly. Someone accidentally commits a huge binary file with a thoughtless `git add .`, and you want to remove it everywhere. Perhaps you accidentally committed a file that contained a password, and you want to make your project open source. `filter-branch` is the tool you probably want to use to scrub your entire history. To remove a file named passwords.txt from your entire history, you can use the `--tree-filter` option to `filter-branch`:
|
716
|
+
|
717
|
+
$ git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
|
718
|
+
Rewrite 6b9b3cf04e7c5686a9cb838c3f36a8cb6a0fc2bd (21/21)
|
719
|
+
Ref 'refs/heads/master' was rewritten
|
720
|
+
|
721
|
+
The `--tree-filter` option runs the specified command after each checkout of the project and then recommits the results. In this case, you remove a file called passwords.txt from every snapshot, whether it exists or not. If you want to remove all accidentally committed editor backup files, you can run something like `git filter-branch --tree-filter "rm -f *~" HEAD`.
|
722
|
+
|
723
|
+
You’ll be able to watch Git rewriting trees and commits and then move the branch pointer at the end. It’s generally a good idea to do this in a testing branch and then hard-reset your master branch after you’ve determined the outcome is what you really want. To run `filter-branch` on all your branches, you can pass `--all` to the command.
|
724
|
+
|
725
|
+
#### Making a Subdirectory the New Root ####
|
726
|
+
|
727
|
+
Suppose you’ve done an import from another source control system and have subdirectories that make no sense (trunk, tags, and so on). If you want to make the `trunk` subdirectory be the new project root for every commit, `filter-branch` can help you do that, too:
|
728
|
+
|
729
|
+
$ git filter-branch --subdirectory-filter trunk HEAD
|
730
|
+
Rewrite 856f0bf61e41a27326cdae8f09fe708d679f596f (12/12)
|
731
|
+
Ref 'refs/heads/master' was rewritten
|
732
|
+
|
733
|
+
Now your new project root is what was in the `trunk` subdirectory each time. Git will also automatically remove commits that did not affect the subdirectory.
|
734
|
+
|
735
|
+
#### Changing E-Mail Addresses Globally ####
|
736
|
+
|
737
|
+
Another common case is that you forgot to run `git config` to set your name and e-mail address before you started working, or perhaps you want to open-source a project at work and change all your work e-mail addresses to your personal address. In any case, you can change e-mail addresses in multiple commits in a batch with `filter-branch` as well. You need to be careful to change only the e-mail addresses that are yours, so you use `--commit-filter`:
|
738
|
+
|
739
|
+
$ git filter-branch --commit-filter '
|
740
|
+
if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
|
741
|
+
then
|
742
|
+
GIT_AUTHOR_NAME="Scott Chacon";
|
743
|
+
GIT_AUTHOR_EMAIL="schacon@example.com";
|
744
|
+
git commit-tree "$@";
|
745
|
+
else
|
746
|
+
git commit-tree "$@";
|
747
|
+
fi' HEAD
|
748
|
+
|
749
|
+
This goes through and rewrites every commit to have your new address. Because commits contain the SHA-1 values of their parents, this command changes every commit SHA in your history, not just those that have the matching e-mail address.
|
750
|
+
|
751
|
+
### The Very Fast Nuclear Option: Big Friendly Giant Repo Cleaner (BFG) ###
|
752
|
+
|
753
|
+
[Roberto Tyley](https://github.com/rtyley) has written a similar tool to `filter-branch` called the BFG. BFG cannot do as much as `filter-branch`, but it is _very_ fast and on a large repository this can make a big difference. If the change you want to make is in the scope of BFG capaility, and you have performance issues, then you should consider using it.
|
754
|
+
|
755
|
+
See the [BFG](http://rtyley.github.io/bfg-repo-cleaner/) website for details.
|
756
|
+
|
757
|
+
## Debugging with Git ##
|
758
|
+
|
759
|
+
Git also provides a couple of tools to help you debug issues in your projects. Because Git is designed to work with nearly any type of project, these tools are pretty generic, but they can often help you hunt for a bug or culprit when things go wrong.
|
760
|
+
|
761
|
+
### File Annotation ###
|
762
|
+
|
763
|
+
If you track down a bug in your code and want to know when it was introduced and why, file annotation is often your best tool. It shows you what commit was the last to modify each line of any file. So, if you see that a method in your code is buggy, you can annotate the file with `git blame` to see when each line of the method was last edited and by whom. This example uses the `-L` option to limit the output to lines 12 through 22:
|
764
|
+
|
765
|
+
$ git blame -L 12,22 simplegit.rb
|
766
|
+
^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 12) def show(tree = 'master')
|
767
|
+
^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 13) command("git show #{tree}")
|
768
|
+
^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 14) end
|
769
|
+
^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 15)
|
770
|
+
9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 16) def log(tree = 'master')
|
771
|
+
79eaf55d (Scott Chacon 2008-04-06 10:15:08 -0700 17) command("git log #{tree}")
|
772
|
+
9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 18) end
|
773
|
+
9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 19)
|
774
|
+
42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 20) def blame(path)
|
775
|
+
42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 21) command("git blame #{path}")
|
776
|
+
42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 22) end
|
777
|
+
|
778
|
+
Notice that the first field is the partial SHA-1 of the commit that last modified that line. The next two fields are values extracted from that commit—the author name and the authored date of that commit — so you can easily see who modified that line and when. After that come the line number and the content of the file. Also note the `^4832fe2` commit lines, which designate that those lines were in this file’s original commit. That commit is when this file was first added to this project, and those lines have been unchanged since. This is a tad confusing, because now you’ve seen at least three different ways that Git uses the `^` to modify a commit SHA, but that is what it means here.
|
779
|
+
|
780
|
+
Another cool thing about Git is that it doesn’t track file renames explicitly. It records the snapshots and then tries to figure out what was renamed implicitly, after the fact. One of the interesting features of this is that you can ask it to figure out all sorts of code movement as well. If you pass `-C` to `git blame`, Git analyzes the file you’re annotating and tries to figure out where snippets of code within it originally came from if they were copied from elsewhere. Recently, I was refactoring a file named `GITServerHandler.m` into multiple files, one of which was `GITPackUpload.m`. By blaming `GITPackUpload.m` with the `-C` option, I could see where sections of the code originally came from:
|
781
|
+
|
782
|
+
$ git blame -C -L 141,153 GITPackUpload.m
|
783
|
+
f344f58d GITServerHandler.m (Scott 2009-01-04 141)
|
784
|
+
f344f58d GITServerHandler.m (Scott 2009-01-04 142) - (void) gatherObjectShasFromC
|
785
|
+
f344f58d GITServerHandler.m (Scott 2009-01-04 143) {
|
786
|
+
70befddd GITServerHandler.m (Scott 2009-03-22 144) //NSLog(@"GATHER COMMI
|
787
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 145)
|
788
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 146) NSString *parentSha;
|
789
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 147) GITCommit *commit = [g
|
790
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 148)
|
791
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 149) //NSLog(@"GATHER COMMI
|
792
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 150)
|
793
|
+
56ef2caf GITServerHandler.m (Scott 2009-01-05 151) if(commit) {
|
794
|
+
56ef2caf GITServerHandler.m (Scott 2009-01-05 152) [refDict setOb
|
795
|
+
56ef2caf GITServerHandler.m (Scott 2009-01-05 153)
|
796
|
+
|
797
|
+
This is really useful. Normally, you get as the original commit the commit where you copied the code over, because that is the first time you touched those lines in this file. Git tells you the original commit where you wrote those lines, even if it was in another file.
|
798
|
+
|
799
|
+
### Binary Search ###
|
800
|
+
|
801
|
+
Annotating a file helps if you know where the issue is to begin with. If you don’t know what is breaking, and there have been dozens or hundreds of commits since the last state where you know the code worked, you’ll likely turn to `git bisect` for help. The `bisect` command does a binary search through your commit history to help you identify as quickly as possible which commit introduced an issue.
|
802
|
+
|
803
|
+
Let’s say you just pushed out a release of your code to a production environment, you’re getting bug reports about something that wasn’t happening in your development environment, and you can’t imagine why the code is doing that. You go back to your code, and it turns out you can reproduce the issue, but you can’t figure out what is going wrong. You can bisect the code to find out. First you run `git bisect start` to get things going, and then you use `git bisect bad` to tell the system that the current commit you’re on is broken. Then, you must tell bisect when the last known good state was, using `git bisect good [good_commit]`:
|
804
|
+
|
805
|
+
$ git bisect start
|
806
|
+
$ git bisect bad
|
807
|
+
$ git bisect good v1.0
|
808
|
+
Bisecting: 6 revisions left to test after this
|
809
|
+
[ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo
|
810
|
+
|
811
|
+
Git figured out that about 12 commits came between the commit you marked as the last good commit (v1.0) and the current bad version, and it checked out the middle one for you. At this point, you can run your test to see if the issue exists as of this commit. If it does, then it was introduced sometime before this middle commit; if it doesn’t, then the problem was introduced sometime after the middle commit. It turns out there is no issue here, and you tell Git that by typing `git bisect good` and continue your journey:
|
812
|
+
|
813
|
+
$ git bisect good
|
814
|
+
Bisecting: 3 revisions left to test after this
|
815
|
+
[b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing
|
816
|
+
|
817
|
+
Now you’re on another commit, halfway between the one you just tested and your bad commit. You run your test again and find that this commit is broken, so you tell Git that with `git bisect bad`:
|
818
|
+
|
819
|
+
$ git bisect bad
|
820
|
+
Bisecting: 1 revisions left to test after this
|
821
|
+
[f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table
|
822
|
+
|
823
|
+
This commit is fine, and now Git has all the information it needs to determine where the issue was introduced. It tells you the SHA-1 of the first bad commit and show some of the commit information and which files were modified in that commit so you can figure out what happened that may have introduced this bug:
|
824
|
+
|
825
|
+
$ git bisect good
|
826
|
+
b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit
|
827
|
+
commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04
|
828
|
+
Author: PJ Hyett <pjhyett@example.com>
|
829
|
+
Date: Tue Jan 27 14:48:32 2009 -0800
|
830
|
+
|
831
|
+
secure this thing
|
832
|
+
|
833
|
+
:040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730
|
834
|
+
f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config
|
835
|
+
|
836
|
+
When you’re finished, you should run `git bisect reset` to reset your HEAD to where you were before you started, or you’ll end up in a weird state:
|
837
|
+
|
838
|
+
$ git bisect reset
|
839
|
+
|
840
|
+
This is a powerful tool that can help you check hundreds of commits for an introduced bug in minutes. In fact, if you have a script that will exit 0 if the project is good or non-0 if the project is bad, you can fully automate `git bisect`. First, you again tell it the scope of the bisect by providing the known bad and good commits. You can do this by listing them with the `bisect start` command if you want, listing the known bad commit first and the known good commit second:
|
841
|
+
|
842
|
+
$ git bisect start HEAD v1.0
|
843
|
+
$ git bisect run test-error.sh
|
844
|
+
|
845
|
+
Doing so automatically runs `test-error.sh` on each checked-out commit until Git finds the first broken commit. You can also run something like `make` or `make tests` or whatever you have that runs automated tests for you.
|
846
|
+
|
847
|
+
## Moduli ##
|
848
|
+
|
849
|
+
Capita spesso che, mentre stai lavorando a un progetto, debba includerne un altro. Potrebbe essere una libreria sviluppata da terze parti o che tu stai sviluppando separatamente e lo stai usando in vari super-progetti. In questi casi si pone un problema comune: si vuole essere in grado di trattare i due progetti separatamente ma essere tuttavia in grado di utilizzarne uno all'interno dell'altro.
|
850
|
+
|
851
|
+
Vediamo un esempio. Immagina di stare sviluppando un sito web creando dei feed Atom e, invece di scrivere da zero il codice per generare il contenuto Atom, decidi di utilizzare una libreria. Molto probabilmente dovrai includere del codice da una libreria condivisa come un’installazione di CPAN o una gem di Ruby, o copiare il sorgente nel tuo progetto. Il problema dell’includere la libreria è che è difficile personalizzarla e spesso più difficile da distribuire, perché è necessario assicurarsi che ogni client abbia a disposizione quella libreria. Il problema di includere il codice nel tuo progetto è che è difficile incorporare le modifiche eventualmente fatte nel progetto iniziale quando questo venisse aggiornato.
|
852
|
+
|
853
|
+
Git risolve questo problema utilizzando i moduli. I moduli consentono di avere un repository Git come una directory di un altro repository Git, che ti permette di clonare un altro repository nel tuo progetto e mantenere le commit separate.
|
854
|
+
|
855
|
+
### Lavorare con i moduli ###
|
856
|
+
|
857
|
+
Si supponga di voler aggiungere la libreria Rack (un’interfaccia gateway per server web in Ruby) al progetto, mantenendo le tue modifiche alla libreria e continuando a integrare le modifiche fatte a monte alla libreria. La prima cosa da fare è clonare il repository esterno nella subdirectory: aggiungi i progetti esterni come moduli col comando `git modulo aggiungono`:
|
858
|
+
|
859
|
+
$ git submodule add git://github.com/chneukirchen/rack.git rack
|
860
|
+
Initialized empty Git repository in /opt/subtest/rack/.git/
|
861
|
+
remote: Counting objects: 3181, done.
|
862
|
+
remote: Compressing objects: 100% (1534/1534), done.
|
863
|
+
remote: Total 3181 (delta 1951), reused 2623 (delta 1603)
|
864
|
+
Receiving objects: 100% (3181/3181), 675.42 KiB | 422 KiB/s, done.
|
865
|
+
Resolving deltas: 100% (1951/1951), done.
|
866
|
+
|
867
|
+
Ora, all'interno del tuo progetto, hai la directory `rack` che contiene il progetto Rack. Puoi andare in questa directory, fare le tue modifiche e aggiungere il tuo repository remoto per fare la push delle tue modifiche e prendere quelle disponibili, così come incorporare le modifiche del repository originale, e molto altro. Se esegui `git status` subito dopo aver aggiunto il modulo, vedrai due cose:
|
868
|
+
|
869
|
+
$ git status
|
870
|
+
# On branch master
|
871
|
+
# Changes to be committed:
|
872
|
+
# (use "git reset HEAD <file>..." to unstage)
|
873
|
+
#
|
874
|
+
# new file: .gitmodules
|
875
|
+
# new file: rack
|
876
|
+
#
|
877
|
+
|
878
|
+
Prima di tutto nota il file `.gitmodules`: è un file di configurazione che memorizza la mappatura tra l’URL del progetto e la directory locale dove lo hai scaricato:
|
879
|
+
|
880
|
+
$ cat .gitmodules
|
881
|
+
[submodule "rack"]
|
882
|
+
path = rack
|
883
|
+
url = git://github.com/chneukirchen/rack.git
|
884
|
+
|
885
|
+
Se hai più di un modulo, avrei più voci in questo file. È importante notare che anche questo file è versionato con tutti gli altri file, come il tuo `.gitignore` e viene trasferito con tutto il resto del tuo progetto. Questo è il modo in cui gli altri che clonano questo progetto sanno dove trovare i progetti dei moduli.
|
886
|
+
|
887
|
+
L'altro elenco in stato git uscita `git status` è la voce rack. Se si esegue `git diff` su questo, si vede qualcosa di interessante:
|
888
|
+
|
889
|
+
$ git diff --cached rack
|
890
|
+
diff --git a/rack b/rack
|
891
|
+
new file mode 160000
|
892
|
+
index 0000000..08d709f
|
893
|
+
--- /dev/null
|
894
|
+
+++ b/rack
|
895
|
+
@@ -0,0 +1 @@
|
896
|
+
+Subproject commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
|
897
|
+
|
898
|
+
Sebbene `rack` sia una subdirectory della tua directory di lavoro, Git lo vede come un modulo e non tiene traccia del suo contenuto quando non sei in quella directory. Git invece lo memorizza come una commit particolare da quel repository. Quando committi delle modifiche in quella directory, il super-project nota che l’HEAD è cambiato e registra la commit esatta dove sei; In questo modo, quando altri clonano questo progetto, possono ricreare esattamente l'ambiente.
|
899
|
+
|
900
|
+
Questo è un punto importante con i moduli: li memorizzi come la commit esatta dove sono. Non puoi memorizzare un modulo su `master` o qualche altro riferimento simbolico.
|
901
|
+
|
902
|
+
Quando committi vedi una cosa simile:
|
903
|
+
|
904
|
+
$ git commit -m 'first commit with submodule rack'
|
905
|
+
[master 0550271] first commit with submodule rack
|
906
|
+
2 files changed, 4 insertions(+), 0 deletions(-)
|
907
|
+
create mode 100644 .gitmodules
|
908
|
+
create mode 160000 rack
|
909
|
+
|
910
|
+
Nota il modo 160000 di ogni voce di rack. Questo è un modo speciale di Git che significa che stai memorizzando una commit per una directory piuttosto che una subdirectory o un file.
|
911
|
+
|
912
|
+
Puoi trattare la directory `rack` come un progetto separato e puoi aggiornare occasionalmente il tuo super-project con un puntatore all’ultima commit del sotto-project. Tutti i comandi di Git lavorano indipendentemente nelle due directories:
|
913
|
+
|
914
|
+
$ git log -1
|
915
|
+
commit 0550271328a0038865aad6331e620cd7238601bb
|
916
|
+
Author: Scott Chacon <schacon@gmail.com>
|
917
|
+
Date: Thu Apr 9 09:03:56 2009 -0700
|
918
|
+
|
919
|
+
first commit with submodule rack
|
920
|
+
$ cd rack/
|
921
|
+
$ git log -1
|
922
|
+
commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
|
923
|
+
Author: Christian Neukirchen <chneukirchen@gmail.com>
|
924
|
+
Date: Wed Mar 25 14:49:04 2009 +0100
|
925
|
+
|
926
|
+
Document version change
|
927
|
+
|
928
|
+
### Clonare un progetto con moduli ###
|
929
|
+
|
930
|
+
Cloneremo ora un progetto con dei moduli. Quando ne ricevi uno, avrai una directory che contiene i moduli, ma nessun file:
|
931
|
+
|
932
|
+
$ git clone git://github.com/schacon/myproject.git
|
933
|
+
Initialized empty Git repository in /opt/myproject/.git/
|
934
|
+
remote: Counting objects: 6, done.
|
935
|
+
remote: Compressing objects: 100% (4/4), done.
|
936
|
+
remote: Total 6 (delta 0), reused 0 (delta 0)
|
937
|
+
Receiving objects: 100% (6/6), done.
|
938
|
+
$ cd myproject
|
939
|
+
$ ls -l
|
940
|
+
total 8
|
941
|
+
-rw-r--r-- 1 schacon admin 3 Apr 9 09:11 README
|
942
|
+
drwxr-xr-x 2 schacon admin 68 Apr 9 09:11 rack
|
943
|
+
$ ls rack/
|
944
|
+
$
|
945
|
+
|
946
|
+
La directory `rack` c’è, ma è vuota. Devi eseguire due comandi: `git submodule init` per inizializzare il tuo file di configurazione locale e `git submodule update` per scaricare tutti i dati del progetto e scaricare le commit opportune elencate nel tuo super-progetto:
|
947
|
+
|
948
|
+
$ git submodule init
|
949
|
+
Submodule 'rack' (git://github.com/chneukirchen/rack.git) registered for path 'rack'
|
950
|
+
$ git submodule update
|
951
|
+
Initialized empty Git repository in /opt/myproject/rack/.git/
|
952
|
+
remote: Counting objects: 3181, done.
|
953
|
+
remote: Compressing objects: 100% (1534/1534), done.
|
954
|
+
remote: Total 3181 (delta 1951), reused 2623 (delta 1603)
|
955
|
+
Receiving objects: 100% (3181/3181), 675.42 KiB | 173 KiB/s, done.
|
956
|
+
Resolving deltas: 100% (1951/1951), done.
|
957
|
+
Submodule path 'rack': checked out '08d709f78b8c5b0fbeb7821e37fa53e69afcf433'
|
958
|
+
|
959
|
+
Ora la tua directory `rack` è nello stesso stato in cui era quando hai committal precedentemente. Se qualche altro sviluppatore facesse delle modifiche a rack e le committasse, quando tu scaricherai quel riferimento e lo integrerai nel tuo repository vedrai qualcosa di strano:
|
960
|
+
|
961
|
+
$ git merge origin/master
|
962
|
+
Updating 0550271..85a3eee
|
963
|
+
Fast forward
|
964
|
+
rack | 2 +-
|
965
|
+
1 files changed, 1 insertions(+), 1 deletions(-)
|
966
|
+
[master*]$ git status
|
967
|
+
# On branch master
|
968
|
+
# Changes not staged for commit:
|
969
|
+
# (use "git add <file>..." to update what will be committed)
|
970
|
+
# (use "git checkout -- <file>..." to discard changes in working directory)
|
971
|
+
#
|
972
|
+
# modified: rack
|
973
|
+
#
|
974
|
+
|
975
|
+
Quello di cui hai fatto il merge è fondamentalmente un cambiamento al puntatore del tuo modulo, ma non aggiorna il codice nella directory del modulo e sembra quindi che la tua directory di lavoro sia in uno stato ‘sporco’:
|
976
|
+
|
977
|
+
$ git diff
|
978
|
+
diff --git a/rack b/rack
|
979
|
+
index 6c5e70b..08d709f 160000
|
980
|
+
--- a/rack
|
981
|
+
+++ b/rack
|
982
|
+
@@ -1 +1 @@
|
983
|
+
-Subproject commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
|
984
|
+
+Subproject commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
|
985
|
+
|
986
|
+
Questo succede perché il tuo puntatore del modulo non è lo stesso della directory del modulo. Per correggerlo devi eseguire di nuovo `git submodule update` again:
|
987
|
+
|
988
|
+
$ git submodule update
|
989
|
+
remote: Counting objects: 5, done.
|
990
|
+
remote: Compressing objects: 100% (3/3), done.
|
991
|
+
remote: Total 3 (delta 1), reused 2 (delta 0)
|
992
|
+
Unpacking objects: 100% (3/3), done.
|
993
|
+
From git@github.com:schacon/rack
|
994
|
+
08d709f..6c5e70b master -> origin/master
|
995
|
+
Submodule path 'rack': checked out '6c5e70b984a60b3cecd395edd5b48a7575bf58e0'
|
996
|
+
|
997
|
+
E devi farlo ogni volta che scarichi delle modifiche al modulo nel progetto principale: è strano, ma funziona.
|
998
|
+
|
999
|
+
Un problema comune si verifica quando uno sviluppatore fa delle modifiche in un modulo ma non le trasmette al server pubblico, ma committa il puntatore a questo stato quando fa la pusg del superproject. Quando altri sviluppatori provano ad eseguire `git submodule update`, il sistema del modulo non riesce a trovare la commit a cui fa riferimento perché esiste solo sul sistema del primo sviluppatore. Quando ciò accade, viene visualizzato un errore come questo:
|
1000
|
+
|
1001
|
+
$ git submodule update
|
1002
|
+
fatal: reference isn’t a tree: 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
|
1003
|
+
Unable to checkout '6c5e70b984a60b3cecd395edd5ba7575bf58e0' in submodule path 'rack'
|
1004
|
+
|
1005
|
+
Devi quindi vedere chi è stato l’ultimo a cambiare il modulo:
|
1006
|
+
|
1007
|
+
$ git log -1 rack
|
1008
|
+
commit 85a3eee996800fcfa91e2119372dd4172bf76678
|
1009
|
+
Author: Scott Chacon <schacon@gmail.com>
|
1010
|
+
Date: Thu Apr 9 09:19:14 2009 -0700
|
1011
|
+
|
1012
|
+
added a submodule reference I will never make public. hahahahaha!
|
1013
|
+
|
1014
|
+
e mandarmi un’email e cazziarlo.
|
1015
|
+
|
1016
|
+
### Super-progetto ###
|
1017
|
+
|
1018
|
+
A volte gli sviluppatori vogliono scaricare una combinazione di subdirectory di un progetto grande, a seconda del team in cui lavorano. Questo è comune se vieni da CVS o Subversion, dove hai definito un modulo o un insieme di subdirectory e vuoi mantenere questo tipo di flusso di lavoro.
|
1019
|
+
|
1020
|
+
Un buon modo per farlo in Git è quello di rendere ciascuna sottodirectory un repository Git separato e creare quindi un repository Git con il super-progetto che contenga più moduli. Un vantaggio di questo approccio è che puoi definire meglio i rapporti tra i progetti con tag e branch nei super-progetti.
|
1021
|
+
|
1022
|
+
### Problemi con i moduli ###
|
1023
|
+
|
1024
|
+
Usare i moduli può comunque presentare qualche intoppo. Prima di tutto devi fare molta attenzione quando lavori nella directory del modulo. Quando esegui `git submodule update`, viene fatto il checkout della versione specifica del progetto, ma non del branch. Questo viene detto “avere l’HEAD separato: significa che il file HEAD punta direttamente alla commit, e non un riferimento simbolico. Il problema è che generalmente non vuoi lavorare in un ambiente separato perché è facile perdere commit, e non un riferimento simbolico. Il problema è che generalmente non vuoi lavorare in un ambiente separato perché è facile perdere le tue modifiche. Se inizi col comando `submodule update` e poi fai una commit nella directory del modulo senza aver creato prima un branch per lavorarci e quindi esegui una `git submodule update` dal super-progetto senz’aver committato nel frattempo, Git sovrascriverà le tue modifiche senza dirti nulla. Tecnicamente non hai perso il tuo lavoro, ma non avendo nessun branch che vi punti sarà difficile da recuperare.
|
1025
|
+
|
1026
|
+
Per evitare questo problema ti basta creare un branch quando lavori nella directory del modulo con `git checkout -b work` o qualcosa di equivalente. Quando successivamente aggiorni il modulo il tuo lavoro sarà di nuovo sovrascritto, ma avrai un puntatore per poterlo recuperare.
|
1027
|
+
|
1028
|
+
Cambiare branch in progetti con dei moduli può essere difficile. Se crei un nuovo branch, vi aggiungi un modulo e torni a un branch che non abbia il modulo, ti ritroverai la directory del modulo non ancora tracciata:
|
1029
|
+
|
1030
|
+
$ git checkout -b rack
|
1031
|
+
Switched to a new branch "rack"
|
1032
|
+
$ git submodule add git@github.com:schacon/rack.git rack
|
1033
|
+
Initialized empty Git repository in /opt/myproj/rack/.git/
|
1034
|
+
...
|
1035
|
+
Receiving objects: 100% (3184/3184), 677.42 KiB | 34 KiB/s, done.
|
1036
|
+
Resolving deltas: 100% (1952/1952), done.
|
1037
|
+
$ git commit -am 'added rack submodule'
|
1038
|
+
[rack cc49a69] added rack submodule
|
1039
|
+
2 files changed, 4 insertions(+), 0 deletions(-)
|
1040
|
+
create mode 100644 .gitmodules
|
1041
|
+
create mode 160000 rack
|
1042
|
+
$ git checkout master
|
1043
|
+
Switched to branch "master"
|
1044
|
+
$ git status
|
1045
|
+
# On branch master
|
1046
|
+
# Untracked files:
|
1047
|
+
# (use "git add <file>..." to include in what will be committed)
|
1048
|
+
#
|
1049
|
+
# rack/
|
1050
|
+
|
1051
|
+
Devi rimuoverla o spostarla e in entrambi i casi dovrai riclonarla quando torni al branch precedente e puoi quindi perdere le modifiche locali o i branch di cui non hai ancora fatto una push.
|
1052
|
+
|
1053
|
+
L'ultima avvertimento riguarda il passaggio da subdirectory a moduli. Se stai versionando dei file tuo nel progetto e vuoi spostarli in un modulo, è necessario devi fare attenzione, altrimenti Git si arrabbierà. Supponi di avere i file di rack in una directory del tuo progetto e decidi di trasformarla in un modulo. Se elimini la directory ed esegui il comando `submodule add`, Git ti strillerà:
|
1054
|
+
|
1055
|
+
$ rm -Rf rack/
|
1056
|
+
$ git submodule add git@github.com:schacon/rack.git rack
|
1057
|
+
'rack' already exists in the index
|
1058
|
+
|
1059
|
+
Devi prima rimuovere la directory `rack` dalla tua area di staging per poter quindi aggiungerla come modulo:
|
1060
|
+
|
1061
|
+
$ git rm -r rack
|
1062
|
+
$ git submodule add git@github.com:schacon/rack.git rack
|
1063
|
+
Initialized empty Git repository in /opt/testsub/rack/.git/
|
1064
|
+
remote: Counting objects: 3184, done.
|
1065
|
+
remote: Compressing objects: 100% (1465/1465), done.
|
1066
|
+
remote: Total 3184 (delta 1952), reused 2770 (delta 1675)
|
1067
|
+
Receiving objects: 100% (3184/3184), 677.42 KiB | 88 KiB/s, done.
|
1068
|
+
Resolving deltas: 100% (1952/1952), done.
|
1069
|
+
|
1070
|
+
Immagina ora di averlo fatto in un branch. Se ora torni a un branch dove quei file sono ancora nell’albero corrente piuttosto che nel modulo vedrai questo errore:
|
1071
|
+
|
1072
|
+
$ git checkout master
|
1073
|
+
error: Untracked working tree file 'rack/AUTHORS' would be overwritten by merge.
|
1074
|
+
(errore: il file 'rack/AUTHORS' non è versionato e sarà sovrascritto)
|
1075
|
+
|
1076
|
+
Devi quindi spostare la directory del modulo `rack` prima di poter tornare al branch che non ce l’aveva:
|
1077
|
+
|
1078
|
+
$ mv rack /tmp/
|
1079
|
+
$ git checkout master
|
1080
|
+
Switched to branch "master"
|
1081
|
+
$ ls
|
1082
|
+
README rack
|
1083
|
+
|
1084
|
+
Ora, quando tornerai indietro, troverai la directory `rack` vuota. Ora puoi eseguire `git submodule update` per ripopolarla o rispostare la directory `/tmp/rack` nella directory vuota.
|
1085
|
+
|
1086
|
+
## Subtree Merging ##
|
1087
|
+
|
1088
|
+
Ora che hai visto quali sono le difficoltà del sistema dei moduli vediamo un’alternativa per risolvere lo stesso problema. Quando Git fa dei merge vede prima quello di cui deve fare il merge e poi decide quale sia la strategia migliore da usare. Se stai facendo il merge due branch Git userà la strategia _ricorsiva_ (*recursive* in inglese). Se stai facendo il merge di più di due branch Git userà la strategia del polpo (*octopus* in inglese). Queste strategie sono scelte automaticamente, perché la strategia ricorsiva può gestire situazioni complesse di merge a tre vie (quando ci sono per esempio più antenati), ma può gestire solamente due branch alla volta. La strategia del polpo può gestire branch multipli ma agisce con più cautela per evitare conflitti difficili da risolvere, ed è quindi scelta come strategia predefinita se stai facendo il merge di più di due branch.
|
1089
|
+
|
1090
|
+
Ci sono comunque altre strategie tra cui scegliere. Una di questa è il merge *subtree* e la puoi usare per risolvere i problemi dei subprogetti. Vedremo ora come includere lo stesso rack come abbiamo fatto nella sezione precedente, usando però il merge subtree.
|
1091
|
+
|
1092
|
+
L’idea del merge subtree è che tu hai due progetti e uno di questi è mappato su una subdirectory dell’altro e viceversa. Quando specifichi il merge subtree Git è abbastanza intelligente da capire che uno è un albero dell’altro e farne il merge nel migliore dei modi: è piuttosto incredibile.
|
1093
|
+
|
1094
|
+
Aggiungi prima l’applicazione Rack al tuo progetto e aggiungi il progetto Rack come un riferimento remoto al tuo progetto, quindi fanne il checkout in un suo branch:
|
1095
|
+
|
1096
|
+
$ git remote add rack_remote git@github.com:schacon/rack.git
|
1097
|
+
$ git fetch rack_remote
|
1098
|
+
warning: no common commits
|
1099
|
+
remote: Counting objects: 3184, done.
|
1100
|
+
remote: Compressing objects: 100% (1465/1465), done.
|
1101
|
+
remote: Total 3184 (delta 1952), reused 2770 (delta 1675)
|
1102
|
+
Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, done.
|
1103
|
+
Resolving deltas: 100% (1952/1952), done.
|
1104
|
+
From git@github.com:schacon/rack
|
1105
|
+
* [new branch] build -> rack_remote/build
|
1106
|
+
* [new branch] master -> rack_remote/master
|
1107
|
+
* [new branch] rack-0.4 -> rack_remote/rack-0.4
|
1108
|
+
* [new branch] rack-0.9 -> rack_remote/rack-0.9
|
1109
|
+
$ git checkout -b rack_branch rack_remote/master
|
1110
|
+
Branch rack_branch set up to track remote branch refs/remotes/rack_remote/master.
|
1111
|
+
Switched to a new branch "rack_branch"
|
1112
|
+
|
1113
|
+
Ora hai la root del progetto Rack nel tuo branch `rack_branch` e il tuo progetto nel branch `master`. Se scarichi prima uno e poi l’altro vedrai che avranno due progetti sorgenti:
|
1114
|
+
|
1115
|
+
$ ls
|
1116
|
+
AUTHORS KNOWN-ISSUES Rakefile contrib lib
|
1117
|
+
COPYING README bin example test
|
1118
|
+
$ git checkout master
|
1119
|
+
Switched to branch "master"
|
1120
|
+
$ ls
|
1121
|
+
README
|
1122
|
+
|
1123
|
+
Ora vuoi inviare il progetto Rack nel tuo progetto `master` come una sottodirectory e in Git puoi farlo con `git read-tree`. Conoscerai meglio `read-tree` e i suoi amici nel Capitolo 9, ma per ora sappi che legge la radice di un branch nella tua area di staging della tua directory di lavoro. Sei appena ritornato nel tuo branch `master` e hai scaricato il branch `rack_branch` nella directory `rack` del branch `master` del tuo progetto principale:
|
1124
|
+
|
1125
|
+
$ git read-tree --prefix=rack/ -u rack_branch
|
1126
|
+
|
1127
|
+
Quando fai la commit sembra che tutti i file di Rack siano nella directory, come se li avessi copiati da un archivio. La cosa interessante è che può fare facilmente il merge da un branch all’altro, così che puoi importare gli aggiornamenti del progetto Rack passando a quel branch e facendo la pull:
|
1128
|
+
|
1129
|
+
$ git checkout rack_branch
|
1130
|
+
$ git pull
|
1131
|
+
|
1132
|
+
Tutte le modifiche del progetto Rack project vengono incorporate e sono pronte per essere committate in locale. Puoi fare anche l’opposto: modificare la directory `rack` e poi fare il merge nel branch `rack_branch` per inviarlo al mantenitore o farne la push al server remoto.
|
1133
|
+
|
1134
|
+
Per fare un confronto tra quello che hai nella directory `rack` e il codice nel branch `rack_branch` (e vedere se devi fare un merge o meno) non puoi usare il normale comando `diff`: devi usare invece `git diff-tree` con il branch con cui vuoi fare il confronto:
|
1135
|
+
|
1136
|
+
$ git diff-tree -p rack_branch
|
1137
|
+
|
1138
|
+
O confrontare quello che c’è nella directory `rack` con quello che c’era nel branch `master` l’ultima volta che l’hai scaricato, col comando
|
1139
|
+
|
1140
|
+
$ git diff-tree -p rack_remote/master
|
1141
|
+
|
1142
|
+
## Sommario ##
|
1143
|
+
|
1144
|
+
Hai visto numerosi strumenti avanzati che ti permettono di manipolare le tue commit e la tua area di staging in modo più preciso. Quando incontrassi dei problemi dovresti essere facilmente in grado di capire quale commit li ha generati, quando e chi ne è l’autore. Se desideri usare dei sotto-progetti nel tuo progetto e hai appreso alcuni modi per soddisfare tali esigenze. A questo punto dovresti essere in grado di fare in Git la maggior parte delle cose sulla riga di comando di uso quotidiano, e sentirti a tuo agio facendole.
|