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,1356 @@
|
|
1
|
+
# Utilitaires Git #
|
2
|
+
|
3
|
+
À présent, vous avez appris les commandes et modes de fonctionnement usuels requis pour gérer et maintenir un dépôt Git pour la gestion de votre code source.
|
4
|
+
Vous avez déroulé les routines de suivi et de validation de fichiers, vous avez exploité la puissance de l'index, de la création et de la fusion de branches locales de travail.
|
5
|
+
|
6
|
+
Maintenant, vous allez explorer un certain nombre de fonctionnalités particulièrement efficaces, fonctionnalités que vous utiliserez moins souvent mais dont vous pourriez avoir l'usage à un moment ou à un autre.
|
7
|
+
|
8
|
+
## Sélection des versions ##
|
9
|
+
|
10
|
+
Git vous permet d'adresser certains *commits* ou un ensemble de *commits* de différentes façons.
|
11
|
+
Si elles ne sont pas toutes évidentes, il est bon de les connaître.
|
12
|
+
|
13
|
+
### Révisions ponctuelles ###
|
14
|
+
|
15
|
+
Naturellement, vous pouvez référencer un *commit* par sa signature SHA-1, mais il existe des méthodes plus confortables pour les humains.
|
16
|
+
Cette section présente les méthodes pour référencer un *commit* simple.
|
17
|
+
|
18
|
+
### Empreinte SHA courte ###
|
19
|
+
|
20
|
+
Git est capable de deviner de quel *commit* vous parlez si vous ne fournissez que quelques caractères du début de la signature, tant que votre SHA-1 partiel comporte au moins 4 caractères et ne correspond pas à plusieurs *commits*.
|
21
|
+
Dans ces conditions, un seul objet correspondra à ce SHA-1 partiel.
|
22
|
+
|
23
|
+
Par exemple, pour afficher un *commit* précis, supposons que vous exécutiez `git log` et que vous identifiiez le *commit* où vous avez introduit une fonctionnalité précise.
|
24
|
+
|
25
|
+
$ git log
|
26
|
+
commit 734713bc047d87bf7eac9674765ae793478c50d3
|
27
|
+
Author: Scott Chacon <schacon@gmail.com>
|
28
|
+
Date: Fri Jan 2 18:32:33 2009 -0800
|
29
|
+
|
30
|
+
fixed refs handling, added gc auto, updated tests
|
31
|
+
|
32
|
+
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
|
33
|
+
Merge: 1c002dd... 35cfb2b...
|
34
|
+
Author: Scott Chacon <schacon@gmail.com>
|
35
|
+
Date: Thu Dec 11 15:08:43 2008 -0800
|
36
|
+
|
37
|
+
Merge commit 'phedders/rdocs'
|
38
|
+
|
39
|
+
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
|
40
|
+
Author: Scott Chacon <schacon@gmail.com>
|
41
|
+
Date: Thu Dec 11 14:58:32 2008 -0800
|
42
|
+
|
43
|
+
added some blame and merge stuff
|
44
|
+
|
45
|
+
Pour cet exemple, choisissons `1c002dd...`.
|
46
|
+
Si vous affichez le contenu de ce *commit* via `git show`, les commandes suivantes sont équivalentes (en partant du principe que les SHA-1 courts ne sont pas ambigus).
|
47
|
+
|
48
|
+
$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
|
49
|
+
$ git show 1c002dd4b536e7479f
|
50
|
+
$ git show 1c002d
|
51
|
+
|
52
|
+
Git peut déterminer une référence SHA-1 tout à la fois la plus courte possible et non ambigüe.
|
53
|
+
Ajoutez l'option `--abbrev-commit` à la commande `git log` et le résultat affiché utilisera des valeurs plus courtes mais uniques ; par défaut Git retiendra 7 caractères et augmentera au besoin :
|
54
|
+
|
55
|
+
$ git log --abbrev-commit --pretty=oneline
|
56
|
+
ca82a6d changed the version number
|
57
|
+
085bb3b removed unnecessary test code
|
58
|
+
a11bef0 first commit
|
59
|
+
|
60
|
+
En règle générale, entre 8 et 10 caractères sont largement suffisant pour assurer l'unicité dans un projet.
|
61
|
+
Un des plus gros projets utilisant Git, le noyau Linux, nécessite de plus en plus fréquemment 12 caractères sur les 40 possibles pour assurer l'unicité.
|
62
|
+
|
63
|
+
### Quelques mots sur SHA-1 ###
|
64
|
+
|
65
|
+
Beaucoup de gens s'inquiètent qu'à un moment donné ils auront, par des circonstances hasardeuses, deux objets dans leur référentiel de hachage de même empreinte SHA-1.
|
66
|
+
Qu'en est-il réellement ?
|
67
|
+
|
68
|
+
S'il vous arrivait de valider un objet qui se hache à la même empreinte SHA-1 qu'un objet existant dans votre référentiel, Git verrait l'objet existant déjà dans votre base de données et présumerait qu'il était déjà enregistré.
|
69
|
+
Si vous essayez de récupérer l'objet de nouveau à un moment donné, vous auriez toujours les données du premier objet.
|
70
|
+
|
71
|
+
Quoi qu'il en soit, vous devriez être conscient à quel point ce scénario est ridiculement improbable.
|
72
|
+
Une empreinte SHA-1 porte sur 20 octets soit 160 bits.
|
73
|
+
Le nombre d'objets aléatoires à hacher requis pour assurer une probabilité de collision de 50 % vaut environ 2^80 (la formule pour calculer la probabilité de collision est `p = (n(n-1)/2) * (1/2^160)`).
|
74
|
+
2^80 vaut 1,2 × 10^24 soit 1 million de milliards de milliards.
|
75
|
+
Cela représente 1200 fois le nombre de grains de sable sur Terre.
|
76
|
+
|
77
|
+
Voici un exemple pour vous donner une idée de ce qui pourrait provoquer une collision du SHA-1.
|
78
|
+
Si tous les 6,5 milliards d'humains sur Terre programmaient et que chaque seconde, chacun produisait du code équivalent à l'historique entier du noyau Linux (1 million d'objets Git) et le poussait sur un énorme dépôt Git, cela prendrait 5 ans pour que ce dépôt contienne assez d'objets pour avoir une probabilité de 50 % qu'une seule collision SHA-1 existe.
|
79
|
+
Il y a une probabilité plus grande que tous les membres de votre équipe de programmation soient attaqués et tués par des loups dans des incidents sans relation la même nuit.
|
80
|
+
|
81
|
+
### Références de branches ###
|
82
|
+
|
83
|
+
La méthode la plus commune pour désigner un *commit* est une branche y pointant.
|
84
|
+
Dès lors, vous pouvez utiliser le nom de la branche dans toute commande utilisant un objet de type *commit* ou un SHA-1.
|
85
|
+
Par exemple, si vous souhaitez afficher le dernier *commit* d'une branche, les commandes suivantes sont équivalentes, en supposant que la branche `sujet1` pointe sur `ca82a6d` :
|
86
|
+
|
87
|
+
$ git show ca82a6dff817ec66f44342007202690a93763949
|
88
|
+
$ git show sujet1
|
89
|
+
|
90
|
+
Pour connaître l'empreinte SHA sur laquelle pointe une branche ou pour savoir parmi tous les exemples précédents ce que cela donne en terme de SHA, vous pouvez utiliser la commande de plomberie nommée `rev-parse`.
|
91
|
+
Référez-vous au chapitre 9 pour plus d'informations sur les commandes de plomberie ; `rev-parse` sert aux opérations de bas niveau et n'est pas conçue pour être utilisée au jour le jour.
|
92
|
+
Quoi qu'il en soit, elle se révèle utile pour comprendre ce qui se passe.
|
93
|
+
Je vous invite à tester `rev-parse` sur votre propre branche.
|
94
|
+
|
95
|
+
$ git rev-parse sujet1
|
96
|
+
ca82a6dff817ec66f44342007202690a93763949
|
97
|
+
|
98
|
+
### Raccourcis RefLog ###
|
99
|
+
|
100
|
+
Git maintient en arrière-plan un historique des références où sont passés HEAD et vos branches sur les derniers mois — ceci s'appelle le _reflog_.
|
101
|
+
|
102
|
+
Vous pouvez le consulter avec la commande `git reflog` :
|
103
|
+
|
104
|
+
$ git reflog
|
105
|
+
734713b... HEAD@{0}: commit: fixed refs handling, added gc auto, updated
|
106
|
+
d921970... HEAD@{1}: merge phedders/rdocs: Merge made by recursive.
|
107
|
+
1c002dd... HEAD@{2}: commit: added some blame and merge stuff
|
108
|
+
1c36188... HEAD@{3}: rebase -i (squash): updating HEAD
|
109
|
+
95df984... HEAD@{4}: commit: # This is a combination of two commits.
|
110
|
+
1c36188... HEAD@{5}: rebase -i (squash): updating HEAD
|
111
|
+
7e05da5... HEAD@{6}: rebase -i (pick): updating HEAD
|
112
|
+
|
113
|
+
À chaque fois que l'extrémité de votre branche est modifiée, Git enregistre cette information pour vous dans son historique temporaire.
|
114
|
+
Vous pouvez référencer d'anciens *commits* avec cette donnée.
|
115
|
+
Si vous souhaitez consulter le n-ième antécédent de votre HEAD, vous pouvez utiliser la référence `@{n}` du reflog, 5 dans cet exemple :
|
116
|
+
|
117
|
+
$ git show HEAD@{5}
|
118
|
+
|
119
|
+
Vous pouvez également remonter le temps et savoir où en était une branche à une date donnée.
|
120
|
+
Par exemple, pour savoir où en était la branche `master` hier (*yesterday* en anglais), tapez :
|
121
|
+
|
122
|
+
$ git show master@{yesterday}
|
123
|
+
|
124
|
+
Cette technique fonctionne uniquement si l'information est encore présente dans le reflog et vous ne pourrez donc pas le consulter sur des *commits* trop anciens.
|
125
|
+
|
126
|
+
Pour consulter le reflog au format `git log`, exécutez: `git log -g` :
|
127
|
+
|
128
|
+
$ git log -g master
|
129
|
+
commit 734713bc047d87bf7eac9674765ae793478c50d3
|
130
|
+
Reflog: master@{0} (Scott Chacon <schacon@gmail.com>)
|
131
|
+
Reflog message: commit: fixed refs handling, added gc auto, updated
|
132
|
+
Author: Scott Chacon <schacon@gmail.com>
|
133
|
+
Date: Fri Jan 2 18:32:33 2009 -0800
|
134
|
+
|
135
|
+
fixed refs handling, added gc auto, updated tests
|
136
|
+
|
137
|
+
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
|
138
|
+
Reflog: master@{1} (Scott Chacon <schacon@gmail.com>)
|
139
|
+
Reflog message: merge phedders/rdocs: Merge made by recursive.
|
140
|
+
Author: Scott Chacon <schacon@gmail.com>
|
141
|
+
Date: Thu Dec 11 15:08:43 2008 -0800
|
142
|
+
|
143
|
+
Merge commit 'phedders/rdocs'
|
144
|
+
|
145
|
+
Veuillez noter que le reflog ne stocke que des informations locales, c'est un historique de ce que vous avez fait dans votre dépôt.
|
146
|
+
Les références sont différentes pour un autre dépôt et juste après le clone d'un dépôt, votre reflog sera vide puisque qu'aucune activité ne s'y sera produite.
|
147
|
+
Exécuter `git show HEAD@{2.months.ago}` ne fonctionnera que si vous avez dupliqué ce projet depuis au moins 2 mois — si vous l'avez dupliqué il y a 5 minutes, vous n'obtiendrez rien.
|
148
|
+
|
149
|
+
### Références passées ###
|
150
|
+
|
151
|
+
Une solution fréquente pour référencer un *commit* est d'utiliser sa descendance.
|
152
|
+
Si vous suffixez une référence par `^`, Git la résoudra comme étant le parent de cette référence.
|
153
|
+
Supposons que vous consultiez votre historique :
|
154
|
+
|
155
|
+
$ git log --pretty=format:'%h %s' --graph
|
156
|
+
* 734713b fix sur la gestion des refs, ajout gc auto, mise à jour des tests
|
157
|
+
* d921970 Merge commit 'phedders/rdocs'
|
158
|
+
|\
|
159
|
+
| * 35cfb2b modifs minor rdoc
|
160
|
+
* | 1c002dd ajout blame and merge
|
161
|
+
|/
|
162
|
+
* 1c36188 ignore *.gem
|
163
|
+
* 9b29157 ajout open3_detach à la liste des fichiers gemspcec
|
164
|
+
|
165
|
+
Alors, vous pouvez consulter le *commit* précédent en spécifiant `HEAD^`, ce qui signifie « le parent de HEAD » :
|
166
|
+
|
167
|
+
$ git show HEAD^
|
168
|
+
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
|
169
|
+
Merge: 1c002dd... 35cfb2b...
|
170
|
+
Author: Scott Chacon <schacon@gmail.com>
|
171
|
+
Date: Thu Dec 11 15:08:43 2008 -0800
|
172
|
+
|
173
|
+
Merge commit 'phedders/rdocs'
|
174
|
+
|
175
|
+
Vous pouvez également spécifier un nombre après `^` — par exemple, `d921970^2` signifie « le second parent de d921970 ».
|
176
|
+
Cette syntaxe ne sert que pour les *commits* de fusion, qui ont plus d'un parent.
|
177
|
+
Le premier parent est la branche où vous avez fusionné, et le second est le *commit* de la branche que vous avez fusionnée :
|
178
|
+
|
179
|
+
$ git show d921970^
|
180
|
+
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
|
181
|
+
Author: Scott Chacon <schacon@gmail.com>
|
182
|
+
Date: Thu Dec 11 14:58:32 2008 -0800
|
183
|
+
|
184
|
+
ajout blame and merge
|
185
|
+
|
186
|
+
$ git show d921970^2
|
187
|
+
commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548
|
188
|
+
Author: Paul Hedderly <paul+git@mjr.org>
|
189
|
+
Date: Wed Dec 10 22:22:03 2008 +0000
|
190
|
+
|
191
|
+
modifs minor rdoc
|
192
|
+
|
193
|
+
Une autre solution courante pour spécifier une référence est le `~`.
|
194
|
+
Il fait également référence au premier parent, donc `HEAD~` et `HEAD^` sont équivalents.
|
195
|
+
La différence se fait sentir si vous spécifiez un nombre.
|
196
|
+
`HEAD~2` signifie « le premier parent du premier parent », ou bien « le grand-parent » ; on remonte les premiers parents autant de fois que demandé.
|
197
|
+
Par exemple, dans l'historique précédemment présenté, `HEAD~3` serait :
|
198
|
+
|
199
|
+
$ git show HEAD~3
|
200
|
+
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
|
201
|
+
Author: Tom Preston-Werner <tom@mojombo.com>
|
202
|
+
Date: Fri Nov 7 13:47:59 2008 -0500
|
203
|
+
|
204
|
+
ignore *.gem
|
205
|
+
|
206
|
+
Cela peut aussi s'écrire `HEAD^^^`, qui là encore est le premier parent du premier parent du premier parent :
|
207
|
+
|
208
|
+
$ git show HEAD^^^
|
209
|
+
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
|
210
|
+
Author: Tom Preston-Werner <tom@mojombo.com>
|
211
|
+
Date: Fri Nov 7 13:47:59 2008 -0500
|
212
|
+
|
213
|
+
ignore *.gem
|
214
|
+
|
215
|
+
Vous pouvez également combiner ces syntaxes — vous pouvez obtenir le second parent de la référence précédente (en supposant que c'était un *commit* de fusion) en utilisant `HEAD~3^2`, etc.
|
216
|
+
|
217
|
+
### Plages de *commits* ###
|
218
|
+
|
219
|
+
À présent que vous pouvez spécifier des *commits* individuels, voyons comment spécifier des plages de *commits*.
|
220
|
+
Ceci est particulièrement pratique pour la gestion des branches — si vous avez beaucoup de branches, vous pouvez utiliser les plages pour répondre à des questions telles que « Quel travail sur cette branche n'ai-je pas encore fusionné sur ma branche principale ? ».
|
221
|
+
|
222
|
+
#### Double point ####
|
223
|
+
|
224
|
+
La spécification de plage de *commits* la plus fréquente est la syntaxe double-point.
|
225
|
+
En gros, cela demande à Git de résoudre la plage des *commits* qui sont accessibles depuis un *commit* mais ne le sont pas depuis un autre.
|
226
|
+
Par exemple, disons que votre historique ressemble à celui de la figure 6-1.
|
227
|
+
|
228
|
+
Insert 18333fig0601.png
|
229
|
+
Figure 6-1. Exemple d'historique pour la sélection de plages de *commits*.
|
230
|
+
|
231
|
+
Si vous voulez savoir ce qui n'a pas encore été fusionné sur votre branche `master` depuis votre branche `experience`, vous pouvez demander à Git de vous montrer un listing des *commits* avec `master..experience` — ce qui signifie « tous les *commits* accessibles par `experience` qui ne le sont pas par `master` ».
|
232
|
+
Dans un souci de brièveté et de clarté de ces exemples, je vais utiliser les lettres des *commits* issus du diagramme à la place du vrai listing dans l'ordre où ils auraient dû être affichés :
|
233
|
+
|
234
|
+
$ git log master..experiment
|
235
|
+
D
|
236
|
+
C
|
237
|
+
|
238
|
+
D'un autre côté, si vous souhaitez voir l'opposé — tous les *commits* dans `master` mais pas encore dans `experience` — vous pouvez inverser les noms de branches, `experience..master` vous montre tout ce que `master` accède mais qu'`experience` ne voit pas :
|
239
|
+
|
240
|
+
$ git log experience..master
|
241
|
+
F
|
242
|
+
E
|
243
|
+
|
244
|
+
C'est pratique si vous souhaitez maintenir `experience` à jour et anticiper les fusions.
|
245
|
+
Un autre cas d'utilisation fréquent consiste à voir ce que vous vous apprêtez à pousser sur une branche distante :
|
246
|
+
|
247
|
+
$ git log origin/master..HEAD
|
248
|
+
|
249
|
+
Cette commande vous affiche tous les *commits* de votre branche courante qui ne sont pas sur la branche `master` du dépôt distant `origin`.
|
250
|
+
Si vous exécutez `git push` et que votre branche courante suit `origin/master`, les *commits* listés par `git log origin/master..HEAD` sont les *commits* qui seront transférés sur le serveur.
|
251
|
+
Vous pouvez également laisser tomber une borne de la syntaxe pour faire comprendre à Git que vous parlez de HEAD.
|
252
|
+
Par exemple, vous pouvez obtenir les mêmes résultats que précédemment en tapant `git log origin/master..` — Git utilise HEAD si une des bornes est manquante.
|
253
|
+
|
254
|
+
#### Emplacements multiples ####
|
255
|
+
|
256
|
+
La syntaxe double-point est pratique comme raccourci ; mais peut-être souhaitez-vous utiliser plus d'une branche pour spécifier une révision, comme pour voir quels *commits* sont dans plusieurs branches mais sont absents de la branche courante.
|
257
|
+
Git vous permet cela avec `^` ou `--not` en préfixe de toute référence de laquelle vous ne souhaitez pas voir les *commits*.
|
258
|
+
Les 3 commandes ci-après sont équivalentes :
|
259
|
+
|
260
|
+
$ git log refA..refB
|
261
|
+
$ git log ^refA refB
|
262
|
+
$ git log refB --not refA
|
263
|
+
|
264
|
+
C'est utile car cela vous permet de spécifier plus de 2 références dans votre requête, ce que vous ne pouvez accomplir avec la syntaxe double-point.
|
265
|
+
Par exemple, si vous souhaitez voir les *commits* qui sont accessibles depuis `refA` et `refB` mais pas depuis `refC`, vous pouvez taper ces 2 commandes :
|
266
|
+
|
267
|
+
$ git log refA refB ^refC
|
268
|
+
$ git log refA refB --not refC
|
269
|
+
|
270
|
+
Ceci vous fournit un système de requêtage des révisions très puissant, pour vous aider à saisir ce qui se trouve sur vos branches.
|
271
|
+
|
272
|
+
#### Triple point ####
|
273
|
+
|
274
|
+
La dernière syntaxe majeure de sélection de plage de *commits* est la syntaxe triple-point qui spécifie tous les *commits* accessibles par l'une des deux références, exclusivement.
|
275
|
+
Toujours avec l'exemple d'historique à la figure 6-1, si vous voulez voir ce qui se trouve sur `master` ou `experience` mais pas sur les deux, exécutez :
|
276
|
+
|
277
|
+
$ git log master...experience
|
278
|
+
F
|
279
|
+
E
|
280
|
+
D
|
281
|
+
C
|
282
|
+
|
283
|
+
Encore une fois, cela vous donne un `log` normal mais ne vous montre les informations que pour ces quatre *commits*, dans l'ordre naturel des dates de validation.
|
284
|
+
|
285
|
+
Une option courante à utiliser avec la commande `log` dans ce cas est `--left-right` qui vous montre la borne de la plage à laquelle ce *commit* appartient.
|
286
|
+
Cela rend les données plus utiles :
|
287
|
+
|
288
|
+
$ git log --left-right master...experience
|
289
|
+
< F
|
290
|
+
< E
|
291
|
+
> D
|
292
|
+
> C
|
293
|
+
|
294
|
+
Avec ces outils, vous pourrez spécifier à Git les *commits* que vous souhaitez inspecter.
|
295
|
+
|
296
|
+
## Indexation interactive ##
|
297
|
+
|
298
|
+
Git propose quelques scripts qui rendent les opérations en ligne de commande plus simples.
|
299
|
+
Nous allons à présent découvrir des commandes interactives vous permettant de choisir les fichiers ou les parties d'un fichier à incorporer à un *commit*.
|
300
|
+
Ces outils sont particulièrement pratiques si vous modifiez un grand nombre de fichiers et que vous souhaitez valider ces changements en modifications plus atomiques plutôt que d'un tenant.
|
301
|
+
De la sorte, vous vous assurez que vos *commits* sont des ensembles cohérents de modifications et qu'ils peuvent être facilement revus par vos collaborateurs.
|
302
|
+
Si vous exécutez `git add` avec l'option `-i` ou `--interactive`, Git entre en mode interactif et affiche quelque chose comme :
|
303
|
+
|
304
|
+
$ git add -i
|
305
|
+
staged unstaged path
|
306
|
+
1: unchanged +0/-1 TODO
|
307
|
+
2: unchanged +1/-1 index.html
|
308
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
309
|
+
|
310
|
+
*** Commands ***
|
311
|
+
1: status 2: update 3: revert 4: add untracked
|
312
|
+
5: patch 6: diff 7: quit 8: help
|
313
|
+
What now>
|
314
|
+
|
315
|
+
Vous vous apercevrez que cette commande propose une vue bien différente de votre index ; en gros, c'est la même information que vous auriez obtenue avec `git status` mais en plus succinct et plus instructif.
|
316
|
+
Cela liste les modifications que vous avez indexées à gauche et celles hors index à droite.
|
317
|
+
|
318
|
+
En dessous vient la section des commandes (*Commands*).
|
319
|
+
Vous aurez accès à un certain nombre d'actions, notamment indexer des fichiers, les enlever de l'index, indexer des parties de fichiers, ajouter des fichiers non indexés, et vérifier les différences de ce que vous avez indexé.
|
320
|
+
|
321
|
+
### Indexation des fichiers ###
|
322
|
+
|
323
|
+
Si vous tapez `2` ou `u` au prompt `What now>`, le script vous demande quels fichiers vous voulez indexer :
|
324
|
+
|
325
|
+
What now> 2
|
326
|
+
staged unstaged path
|
327
|
+
1: unchanged +0/-1 TODO
|
328
|
+
2: unchanged +1/-1 index.html
|
329
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
330
|
+
Update>>
|
331
|
+
|
332
|
+
Pour indexer les fichiers TODO et index.html, vous pouvez taper ces nombres :
|
333
|
+
|
334
|
+
Update>> 1,2
|
335
|
+
staged unstaged path
|
336
|
+
* 1: unchanged +0/-1 TODO
|
337
|
+
* 2: unchanged +1/-1 index.html
|
338
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
339
|
+
Update>>
|
340
|
+
|
341
|
+
Le caractère `*` au début de la ligne de chaque fichier indique que celui-ci est sélectionné.
|
342
|
+
Si vous tapez Entrée sur l'invite `Update>>`, Git prend tout ce qui est sélectionné et l'indexe pour vous :
|
343
|
+
|
344
|
+
Update>>
|
345
|
+
updated 2 paths
|
346
|
+
|
347
|
+
*** Commands ***
|
348
|
+
1: status 2: update 3: revert 4: add untracked
|
349
|
+
5: patch 6: diff 7: quit 8: help
|
350
|
+
What now> 1
|
351
|
+
staged unstaged path
|
352
|
+
1: +0/-1 nothing TODO
|
353
|
+
2: +1/-1 nothing index.html
|
354
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
355
|
+
|
356
|
+
À présent, vous pouvez voir que les fichiers TODO et index.html sont indexés (*staged* en anglais) et que `simplegit.rb` ne l'est toujours pas.
|
357
|
+
Si vous souhaitez enlever de l'index le fichier TODO, utilisez `3` (ou `r` pour revert en anglais) :
|
358
|
+
|
359
|
+
*** Commands ***
|
360
|
+
1: status 2: update 3: revert 4: add untracked
|
361
|
+
5: patch 6: diff 7: quit 8: help
|
362
|
+
What now> 3
|
363
|
+
staged unstaged path
|
364
|
+
1: +0/-1 nothing TODO
|
365
|
+
2: +1/-1 nothing index.html
|
366
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
367
|
+
Revert>> 1
|
368
|
+
staged unstaged path
|
369
|
+
* 1: +0/-1 nothing TODO
|
370
|
+
2: +1/-1 nothing index.html
|
371
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
372
|
+
Revert>> [enter]
|
373
|
+
reverted one path
|
374
|
+
|
375
|
+
Un aperçu rapide à votre statut Git et vous pouvez voir que vous avez enlevé le fichier TODO de l'index :
|
376
|
+
|
377
|
+
*** Commands ***
|
378
|
+
1: status 2: update 3: revert 4: add untracked
|
379
|
+
5: patch 6: diff 7: quit 8: help
|
380
|
+
What now> 1
|
381
|
+
staged unstaged path
|
382
|
+
1: unchanged +0/-1 TODO
|
383
|
+
2: +1/-1 nothing index.html
|
384
|
+
3: unchanged +5/-1 lib/simplegit.rb
|
385
|
+
|
386
|
+
Pour voir la modification que vous avez indexée, utilisez `6` ou `d` (pour différence).
|
387
|
+
Cela vous affiche la liste des fichiers indexés et vous pouvez choisir ceux pour lesquels vous voulez consulter la différence.
|
388
|
+
C'est équivalent à `git diff --cached` en ligne de commande :
|
389
|
+
|
390
|
+
*** Commands ***
|
391
|
+
1: status 2: update 3: revert 4: add untracked
|
392
|
+
5: patch 6: diff 7: quit 8: help
|
393
|
+
What now> 6
|
394
|
+
staged unstaged path
|
395
|
+
1: +1/-1 nothing index.html
|
396
|
+
Review diff>> 1
|
397
|
+
diff --git a/index.html b/index.html
|
398
|
+
index 4d07108..4335f49 100644
|
399
|
+
--- a/index.html
|
400
|
+
+++ b/index.html
|
401
|
+
@@ -16,7 +16,7 @@ Date Finder
|
402
|
+
|
403
|
+
<p id="out">...</p>
|
404
|
+
|
405
|
+
-<div id="footer">contact : support@github.com</div>
|
406
|
+
+<div id="footer">contact : email.support@github.com</div>
|
407
|
+
|
408
|
+
<script type="text/javascript">
|
409
|
+
|
410
|
+
Avec ces commandes élémentaires, vous pouvez utiliser l'ajout interactif pour manipuler votre index un peu plus facilement.
|
411
|
+
|
412
|
+
### Indexations partielles ###
|
413
|
+
|
414
|
+
Git est également capable d'indexer certaines parties d'un fichier.
|
415
|
+
Par exemple, si vous modifiez en deux endroits votre fichier `simplegit.rb` et que vous souhaitez indexer une modification seulement, cela peut se faire très aisément avec Git.
|
416
|
+
En mode interactif, tapez `5` ou `p` (pour *patch* en anglais).
|
417
|
+
Git vous demandera quels fichiers vous voulez indexer partiellement, puis, pour chacun des fichiers sélectionnés, il affichera les parties du fichier où il y a des différences et vous demandera si vous souhaitez les indexer, une par une :
|
418
|
+
|
419
|
+
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
|
420
|
+
index dd5ecc4..57399e0 100644
|
421
|
+
--- a/lib/simplegit.rb
|
422
|
+
+++ b/lib/simplegit.rb
|
423
|
+
@@ -22,7 +22,7 @@ class SimpleGit
|
424
|
+
end
|
425
|
+
|
426
|
+
def log(treeish = 'master')
|
427
|
+
- command("git log -n 25 #{treeish}")
|
428
|
+
+ command("git log -n 30 #{treeish}")
|
429
|
+
end
|
430
|
+
|
431
|
+
def blame(path)
|
432
|
+
Stage this hunk [y,n,a,d,/,j,J,g,e,?]?
|
433
|
+
|
434
|
+
À cette étape, vous disposez de bon nombre d'options.
|
435
|
+
`?` vous liste les actions possibles dont voici une traduction :
|
436
|
+
|
437
|
+
indexer cette partie [y,n,a,d,/,j,J,g,e,?]?
|
438
|
+
y - indexer cette partie
|
439
|
+
n - ne pas indexer cette partie
|
440
|
+
a - indexer cette partie et toutes celles restantes dans ce fichier
|
441
|
+
d - ne pas indexer cette partie ni aucune de celles restantes dans ce fichier
|
442
|
+
g - sélectionner une partie à voir
|
443
|
+
/ - chercher une partie correspondant à la regexp donnée
|
444
|
+
j - laisser cette partie non décidée, voir la prochaine partie non encore décidée
|
445
|
+
J - laisser cette partie non décidée, voir la prochaine partie
|
446
|
+
k - laisser cette partie non décidée, voir la partie non encore décidée précédente
|
447
|
+
K - laisser cette partie non décidée, voir la partie précédente
|
448
|
+
s - couper la partie courante en parties plus petites
|
449
|
+
e - modifier manuellement la partie courante
|
450
|
+
? - afficher l'aide
|
451
|
+
|
452
|
+
En règle générale, vous choisirez `y` ou `n` pour indexer ou non chacun des blocs, mais tout indexer pour certains fichiers ou remettre à plus tard le choix pour un bloc peut également être utile.
|
453
|
+
Si vous indexez une partie d'un fichier et une autre non, votre statut ressemblera à peu près à ceci :
|
454
|
+
|
455
|
+
What now> 1
|
456
|
+
staged unstaged path
|
457
|
+
1: unchanged +0/-1 TODO
|
458
|
+
2: +1/-1 nothing index.html
|
459
|
+
3: +1/-1 +4/-0 lib/simplegit.rb
|
460
|
+
|
461
|
+
Le statut pour le fichier `simplegit.rb` est intéressant.
|
462
|
+
Il vous montre que quelques lignes sont indexées et d'autres non.
|
463
|
+
Vous avez partiellement indexé ce fichier.
|
464
|
+
Dès lors, vous pouvez quitter l'ajout interactif et exécuter `git commit` pour valider les fichiers partiellement indexés.
|
465
|
+
|
466
|
+
Enfin, vous pouvez vous passer du mode interactif pour indexer partiellement un fichier ; vous pouvez faire de même avec `git add -p` ou `git add --patch` en ligne de commande.
|
467
|
+
|
468
|
+
## Le remisage ##
|
469
|
+
|
470
|
+
Souvent, lorsque vous avez travaillé sur une partie de votre projet, les choses sont dans un état instable mais vous voulez changer de branche pour travailler momentanément sur autre chose.
|
471
|
+
Le problème est que vous ne voulez pas valider un travail à moitié fait seulement pour pouvoir y revenir plus tard.
|
472
|
+
La réponse à cette problématique est la commande `git stash`.
|
473
|
+
|
474
|
+
Remiser prend l'état en cours de votre répertoire de travail, c'est-à-dire les fichiers modifiés et l'index, et l'enregistre dans la pile des modifications non finies que vous pouvez réappliquer à n'importe quel moment.
|
475
|
+
|
476
|
+
### Remiser votre travail ###
|
477
|
+
|
478
|
+
Pour démontrer cette possibilité, allez dans votre projet et commencez à travailler sur quelques fichiers et à indexer l'un de ces changements.
|
479
|
+
Si vous exécutez `git status`, vous pouvez voir votre état instable :
|
480
|
+
|
481
|
+
$ git status
|
482
|
+
# On branch master
|
483
|
+
# Changes to be committed:
|
484
|
+
# (use "git reset HEAD <file>..." to unstage)
|
485
|
+
#
|
486
|
+
# modified: index.html
|
487
|
+
#
|
488
|
+
# Changes not staged for commit:
|
489
|
+
# (use "git add <file>..." to update what will be committed)
|
490
|
+
#
|
491
|
+
# modified: lib/simplegit.rb
|
492
|
+
#
|
493
|
+
|
494
|
+
À ce moment-là, vous voulez changer de branche, mais vous ne voulez pas encore valider ce travail ; vous allez donc remiser vos modifications.
|
495
|
+
Pour créer une nouvelle remise sur votre pile, exécutez `git stash` :
|
496
|
+
|
497
|
+
$ git stash
|
498
|
+
Saved working directory and index state \
|
499
|
+
"WIP on master: 049d078 added the index file"
|
500
|
+
HEAD is now at 049d078 added the index file
|
501
|
+
(To restore them type "git stash apply")
|
502
|
+
|
503
|
+
Votre répertoire de travail est propre :
|
504
|
+
|
505
|
+
$ git status
|
506
|
+
# On branch master
|
507
|
+
nothing to commit, working directory clean
|
508
|
+
|
509
|
+
À ce moment, vous pouvez facilement changer de branche et travailler autre part ; vos modifications sont conservées dans votre pile.
|
510
|
+
Pour voir quelles remises vous avez sauvegardées, vous pouvez utiliser la commande `git stash list` :
|
511
|
+
|
512
|
+
$ git stash list
|
513
|
+
stash@{0}: WIP on master: 049d078 added the index file
|
514
|
+
stash@{1}: WIP on master: c264051... Revert "added file_size"
|
515
|
+
stash@{2}: WIP on master: 21d80a5... added number to log
|
516
|
+
|
517
|
+
Dans ce cas, deux remises ont été créées précédemment, vous avez donc accès à trois travaux remisés différents.
|
518
|
+
Vous pouvez réappliquer celui que vous venez juste de remiser en utilisant la commande affichée dans la sortie d'aide de la première commande de remise : `git stash apply`.
|
519
|
+
Si vous voulez appliquer une remise plus ancienne, vous pouvez la spécifier en la nommant, comme ceci : `git stash apply stash@{2}`.
|
520
|
+
Si vous ne spécifiez pas une remise, Git présume que vous voulez la remise la plus récente et essaye de l'appliquer.
|
521
|
+
|
522
|
+
$ git stash apply
|
523
|
+
# On branch master
|
524
|
+
# Changes not staged for commit:
|
525
|
+
# (use "git add <file>..." to update what will be committed)
|
526
|
+
#
|
527
|
+
# modified: index.html
|
528
|
+
# modified: lib/simplegit.rb
|
529
|
+
#
|
530
|
+
|
531
|
+
Vous pouvez observer que Git remodifie les fichiers non validés lorsque vous avez créé la remise.
|
532
|
+
Dans ce cas, vous aviez un répertoire de travail propre lorsque vous avez essayé d'appliquer la remise et vous l'avez fait sur la même branche que celle où vous l'aviez créée ; mais avoir un répertoire de travail propre et l'appliquer sur la même branche n'est pas nécessaire pour réussir à appliquer une remise.
|
533
|
+
Vous pouvez très bien créer une remise sur une branche, changer de branche et essayer d'appliquer les modifications.
|
534
|
+
Vous pouvez même avoir des fichiers modifiés et non validés dans votre répertoire de travail quand vous appliquez une remise, Git vous indique les conflits de fusions si quoi que ce soit ne s'applique pas proprement.
|
535
|
+
|
536
|
+
Par défaut, les modifications de vos fichiers sont réappliquées, mais pas les indexations.
|
537
|
+
Pour cela, vous devez exécuter la commande `git stash apply` avec l'option `--index` pour demander à Git d'essayer de réappliquer les modifications de votre index.
|
538
|
+
Si vous exécutez cela à la place de la commande précédente, vous vous retrouvez dans la position d'origine de la remise :
|
539
|
+
|
540
|
+
$ git stash apply --index
|
541
|
+
# On branch master
|
542
|
+
# Changes to be committed:
|
543
|
+
# (use "git reset HEAD <file>..." to unstage)
|
544
|
+
#
|
545
|
+
# modified: index.html
|
546
|
+
#
|
547
|
+
# Changes not staged for commit:
|
548
|
+
# (use "git add <file>..." to update what will be committed)
|
549
|
+
#
|
550
|
+
# modified: lib/simplegit.rb
|
551
|
+
#
|
552
|
+
|
553
|
+
L'option `apply` essaye seulement d'appliquer le travail remisé, vous aurez toujours la remise dans votre pile.
|
554
|
+
Pour la supprimer, vous pouvez exécuter `git stash drop` avec le nom de la remise à supprimer :
|
555
|
+
|
556
|
+
$ git stash list
|
557
|
+
stash@{0}: WIP on master: 049d078 added the index file
|
558
|
+
stash@{1}: WIP on master: c264051... Revert "added file_size"
|
559
|
+
stash@{2}: WIP on master: 21d80a5... added number to log
|
560
|
+
$ git stash drop stash@{0}
|
561
|
+
Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)
|
562
|
+
|
563
|
+
Vous pouvez également exécuter `git stash pop` pour appliquer et supprimer immédiatement la remise de votre pile.
|
564
|
+
|
565
|
+
### Défaire l'effet d'une remise ###
|
566
|
+
|
567
|
+
Dans certains cas, il est souhaitable de pouvoir appliquer une modification remisée, réaliser d'autres modifications, puis défaire les modifications de la remise.
|
568
|
+
Git ne fournit pas de commande `stash unapply` mais il est possible d'obtenir le même effet en extrayant les modifications qui constituent la remise et en appliquant leur inverse :
|
569
|
+
|
570
|
+
$ git stash show -p stash@{0} | git apply -R
|
571
|
+
|
572
|
+
Ici aussi, si la remise n'est pas indiquée, Git utilise la plus récente.
|
573
|
+
|
574
|
+
$ git stash show -p | git apply -R
|
575
|
+
|
576
|
+
La création d'un alias permettra d'ajouter effectivement la commande `stash-unapply` à votre Git.
|
577
|
+
Par exemple :
|
578
|
+
|
579
|
+
$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
|
580
|
+
$ git stash apply
|
581
|
+
$ #... work work work
|
582
|
+
$ git stash-unapply
|
583
|
+
|
584
|
+
### Créer une branche depuis une remise ###
|
585
|
+
|
586
|
+
Si vous remisez votre travail, et l'oubliez pendant un temps en continuant sur la branche où vous avez créé la remise, vous pouvez avoir un problème en réappliquant le travail.
|
587
|
+
Si l'application de la remise essaye de modifier un fichier que vous avez modifié depuis, vous allez obtenir des conflits de fusion et vous devrez essayer de les résoudre.
|
588
|
+
Si vous voulez un moyen plus facile de tester une nouvelle fois les modifications remisées, vous pouvez exécuter `git stash branch`, qui créera une nouvelle branche à votre place, récupérant le *commit* où vous étiez lorsque vous avez créé la remise, réappliquera votre travail dedans, et supprimera finalement votre remise si cela a réussi :
|
589
|
+
|
590
|
+
$ git stash branch testchanges
|
591
|
+
Switched to a new branch "testchanges"
|
592
|
+
# On branch testchanges
|
593
|
+
# Changes to be committed:
|
594
|
+
# (use "git reset HEAD <file>..." to unstage)
|
595
|
+
#
|
596
|
+
# modified: index.html
|
597
|
+
#
|
598
|
+
# Changes not staged for commit:
|
599
|
+
# (use "git add <file>..." to update what will be committed)
|
600
|
+
#
|
601
|
+
# modified: lib/simplegit.rb
|
602
|
+
#
|
603
|
+
Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)
|
604
|
+
|
605
|
+
C'est un bon raccourci pour récupérer facilement du travail remisé et pouvoir travailler dessus dans une nouvelle branche.
|
606
|
+
|
607
|
+
## Réécrire l'historique ##
|
608
|
+
|
609
|
+
Bien souvent, lorsque vous travaillez avec Git, vous souhaitez modifier votre historique de validation pour une raison quelconque.
|
610
|
+
Une des choses merveilleuses de Git est qu'il vous permet de prendre des décisions le plus tard possible.
|
611
|
+
Vous pouvez décider quels fichiers vont dans quel *commit* avant que vous ne validiez l'index, vous pouvez décider que vous ne voulez pas encore montrer que vous travaillez sur quelque chose avec les remises, et vous pouvez réécrire les *commits* déjà sauvegardés pour qu'ils ressemblent à quelque chose d'autre.
|
612
|
+
Cela peut signifier changer l'ordre des *commits*, modifier les messages ou modifier les fichiers appartenant au *commit*, rassembler ou scinder des *commits*, ou supprimer complètement des *commits* ; tout ceci avant de les partager avec les autres.
|
613
|
+
|
614
|
+
Dans cette section, nous expliquerons comment accomplir ces tâches très utiles pour que vous puissiez remodeler votre historique de validation comme vous le souhaitez avant de le partager avec autrui.
|
615
|
+
|
616
|
+
### Modifier la dernière validation ###
|
617
|
+
|
618
|
+
Modifier votre dernière validation est probablement la réécriture de l'historique que vous allez utiliser le plus souvent.
|
619
|
+
Vous voudrez souvent faire deux choses basiques à votre dernier *commit* : modifier le message de validation ou changer le contenu que vous avez enregistré en ajoutant, modifiant ou supprimant des fichiers.
|
620
|
+
|
621
|
+
Si vous voulez seulement modifier votre dernier message de validation, c'est vraiment simple :
|
622
|
+
|
623
|
+
$ git commit --amend
|
624
|
+
|
625
|
+
Cela ouvre votre éditeur de texte contenant votre dernier message, prêt à être modifié.
|
626
|
+
Lorsque vous sauvegardez et fermez l'éditeur, Git enregistre la nouvelle validation contenant le message et en fait votre dernier *commit*.
|
627
|
+
|
628
|
+
Si vous voulez modifier le contenu de votre validation en ajoutant ou modifiant des fichiers, sûrement parce que vous avez oublié d'ajouter les fichiers nouvellement créés quand vous avez validé la première fois, la procédure fonctionne grosso-modo de la même manière.
|
629
|
+
Vous indexez les modifications que vous voulez en exécutant `git add` ou `git rm`, et le prochain `git commit --amend` prendra votre index courant et en fera le contenu de votre nouvelle validation.
|
630
|
+
|
631
|
+
Vous devez être prudent avec cette technique car votre modification modifie également le SHA-1 du *commit*.
|
632
|
+
Cela ressemble à un tout petit `rebase`.
|
633
|
+
Ne modifiez pas votre dernière validation si vous l'avez déjà publiée !
|
634
|
+
|
635
|
+
### Modifier plusieurs messages de validation ###
|
636
|
+
|
637
|
+
Pour modifier une validation qui est plus loin dans votre historique, vous devez utiliser des outils plus complexes.
|
638
|
+
Git ne contient pas d'outil de modification d'historique, mais vous pouvez utiliser l'outil `rebase` pour rebaser une suite de *commits* depuis la branche HEAD plutôt que de les déplacer vers une autre branche.
|
639
|
+
Avec l'outil `rebase` interactif, vous pouvez vous arrêter après chaque *commit* que vous voulez modifier et changer le message, ajouter des fichiers ou quoique ce soit que vous voulez.
|
640
|
+
Vous pouvez exécuter `rebase` interactivement en ajoutant l'option `-i` à `git rebase`.
|
641
|
+
Vous devez indiquer jusqu'à quand remonter dans votre historique en donnant à la commande le *commit* sur lequel vous voulez vous rebaser.
|
642
|
+
|
643
|
+
Par exemple, si vous voulez modifier les 3 derniers messages de validation ou n'importe lequel des messages dans ce groupe, vous fournissez à `git rebase -i` le parent du dernier *commit* que vous voulez éditer, qui est `HEAD~2^` or `HEAD~3`.
|
644
|
+
Il peut être plus facile de se souvenir de `~3`, car vous essayez de modifier les 3 derniers *commits*, mais gardez à l'esprit que vous désignez le 4e, le parent du dernier *commit* que vous voulez modifier :
|
645
|
+
|
646
|
+
$ git rebase -i HEAD~3
|
647
|
+
|
648
|
+
Souvenez-vous également que ceci est une commande de rebasage, chaque *commit* inclus dans l'intervalle `HEAD~3..HEAD` sera réécrit, que vous changiez le message ou non.
|
649
|
+
N'incluez pas, dans cette commande, de *commit* que vous avez déjà poussé sur un serveur central.
|
650
|
+
Le faire entraînera la confusion chez les autres développeurs en leur fournissant une version altérée des mêmes modifications.
|
651
|
+
|
652
|
+
Exécuter cette commande vous donne la liste des validations dans votre éditeur de texte, ce qui ressemble à :
|
653
|
+
|
654
|
+
pick f7f3f6d changed my name a bit
|
655
|
+
pick 310154e updated README formatting and added blame
|
656
|
+
pick a5f4a0d added cat-file
|
657
|
+
|
658
|
+
# Rebase 710f0f8..a5f4a0d onto 710f0f8
|
659
|
+
#
|
660
|
+
# Commands:
|
661
|
+
# p, pick = use commit
|
662
|
+
# e, edit = use commit, but stop for amending
|
663
|
+
# s, squash = use commit, but meld into previous commit
|
664
|
+
#
|
665
|
+
# If you remove a line here THAT COMMIT WILL BE LOST.
|
666
|
+
# However, if you remove everything, the rebase will be aborted.
|
667
|
+
#
|
668
|
+
|
669
|
+
Il est important de signaler que les *commits* sont listés dans l'ordre inverse de celui que vous voyez normalement en utilisant la commande `log`.
|
670
|
+
Si vous exécutez la commande `log`, vous verrez quelque chose de ce genre :
|
671
|
+
|
672
|
+
$ git log --pretty=format:"%h %s" HEAD~3..HEAD
|
673
|
+
a5f4a0d added cat-file
|
674
|
+
310154e updated README formatting and added blame
|
675
|
+
f7f3f6d changed my name a bit
|
676
|
+
|
677
|
+
Remarquez l'ordre inverse.
|
678
|
+
Le rebasage interactif va créer un script à exécuter.
|
679
|
+
Il commencera au *commit* que vous spécifiez sur la ligne de commande (`HEAD~3`) et refera les modifications introduites dans chacun des *commits* du début à la fin.
|
680
|
+
Il ordonne donc le plus vieux au début, plutôt que le plus récent, car c'est celui qu'il refera en premier.
|
681
|
+
|
682
|
+
Vous devez éditer le script afin qu'il s'arrête au *commit* que vous voulez modifier.
|
683
|
+
Pour cela, remplacer le mot « pick » par le mot « edit » pour chaque *commit* après lequel vous voulez que le script s'arrête.
|
684
|
+
Par exemple, pour modifier uniquement le message du troisième *commit*, vous modifiez le fichier pour ressembler à :
|
685
|
+
|
686
|
+
edit f7f3f6d changed my name a bit
|
687
|
+
pick 310154e updated README formatting and added blame
|
688
|
+
pick a5f4a0d added cat-file
|
689
|
+
|
690
|
+
Au moment où vous sauvegardez et quittez l'éditeur, Git revient au dernier *commit* de cette liste et vous laisse sur une ligne de commande avec le message suivant :
|
691
|
+
|
692
|
+
$ git rebase -i HEAD~3
|
693
|
+
Stopped at 7482e0d... updated the gemspec to hopefully work better
|
694
|
+
You can amend the commit now, with
|
695
|
+
|
696
|
+
git commit --amend
|
697
|
+
|
698
|
+
Once you’re satisfied with your changes, run
|
699
|
+
|
700
|
+
git rebase --continue
|
701
|
+
|
702
|
+
Ces instructions vous disent exactement quoi faire.
|
703
|
+
Entrez :
|
704
|
+
|
705
|
+
$ git commit --amend
|
706
|
+
|
707
|
+
Modifiez le message de *commit* et quittez l'éditeur.
|
708
|
+
Puis exécutez :
|
709
|
+
|
710
|
+
$ git rebase --continue
|
711
|
+
|
712
|
+
Cette commande appliquera les deux autres *commits* automatiquement.
|
713
|
+
Si vous remplacez « pick » en « edit » sur plusieurs lignes, vous pouvez répéter ces étapes pour chaque *commit* que vous avez marqué pour modification.
|
714
|
+
Chaque fois, Git s'arrêtera, vous laissant modifier le *commit* et continuera lorsque vous aurez fini.
|
715
|
+
|
716
|
+
### Réordonner les *commits* ###
|
717
|
+
|
718
|
+
Vous pouvez également utiliser les rebasages interactifs afin de réordonner ou supprimer entièrement des *commits*.
|
719
|
+
Si vous voulez supprimer le *commit* « added cat-file » et modifier l'ordre dans lequel les deux autres *commits* se trouvent dans l'historique, vous pouvez modifier le script de rebasage :
|
720
|
+
|
721
|
+
pick f7f3f6d changed my name a bit
|
722
|
+
pick 310154e updated README formatting and added blame
|
723
|
+
pick a5f4a0d added cat-file
|
724
|
+
|
725
|
+
afin qu'il ressemble à ceci :
|
726
|
+
|
727
|
+
pick 310154e updated README formatting and added blame
|
728
|
+
pick f7f3f6d changed my name a bit
|
729
|
+
|
730
|
+
Lorsque vous sauvegardez et quittez l'éditeur, Git remet votre branche au niveau du parent de ces *commits*, applique `310154e` puis `f7f3f6d` et s'arrête.
|
731
|
+
Vous venez de modifier l'ordre de ces *commits* et de supprimer entièrement le *commit* « added cat-file ».
|
732
|
+
|
733
|
+
### Rassembler des *commits* ###
|
734
|
+
|
735
|
+
Il est également possible de prendre une série de *commits* et de les rassembler en un seul avec l'outil de rebasage interactif.
|
736
|
+
Le script affiche des instructions utiles dans le message de rebasage :
|
737
|
+
|
738
|
+
#
|
739
|
+
# Commands:
|
740
|
+
# p, pick = use commit
|
741
|
+
# e, edit = use commit, but stop for amending
|
742
|
+
# s, squash = use commit, but meld into previous commit
|
743
|
+
#
|
744
|
+
# If you remove a line here THAT COMMIT WILL BE LOST.
|
745
|
+
# However, if you remove everything, the rebase will be aborted.
|
746
|
+
#
|
747
|
+
|
748
|
+
Si, à la place de « pick » ou « edit », vous spécifiez « squash », Git applique cette modification et la modification juste précédente et fusionne les messages de validation.
|
749
|
+
Donc, si vous voulez faire un seul *commit* de ces trois validations, vous faites en sorte que le script ressemble à ceci :
|
750
|
+
|
751
|
+
pick f7f3f6d changed my name a bit
|
752
|
+
squash 310154e updated README formatting and added blame
|
753
|
+
squash a5f4a0d added cat-file
|
754
|
+
|
755
|
+
Lorsque vous sauvegardez et quittez l'éditeur, Git applique ces trois modifications et vous remontre l'éditeur contenant maintenant la fusion des 3 messages de validation :
|
756
|
+
|
757
|
+
# This is a combination of 3 commits.
|
758
|
+
# The first commit's message is:
|
759
|
+
changed my name a bit
|
760
|
+
|
761
|
+
# This is the 2nd commit message:
|
762
|
+
|
763
|
+
updated README formatting and added blame
|
764
|
+
|
765
|
+
# This is the 3rd commit message:
|
766
|
+
|
767
|
+
added cat-file
|
768
|
+
|
769
|
+
Lorsque vous sauvegardez cela, vous obtenez un seul *commit* amenant les modifications des trois *commits* précédents.
|
770
|
+
|
771
|
+
### Diviser un *commit* ###
|
772
|
+
|
773
|
+
Pour diviser un *commit*, il doit être défait, puis partiellement indexé et validé autant de fois que vous voulez pour en finir avec lui.
|
774
|
+
Par exemple, supposons que vous voulez diviser le *commit* du milieu dans l'exemple des trois *commits* précédents.
|
775
|
+
Plutôt que « updated README formatting and added blame », vous voulez le diviser en deux *commits* : « updated README formatting » pour le premier, et « added blame » pour le deuxième.
|
776
|
+
Vous pouvez le faire avec le script `rebase -i` en remplaçant l'instruction sur le *commit* que vous voulez diviser en « edit » :
|
777
|
+
|
778
|
+
pick f7f3f6d changed my name a bit
|
779
|
+
edit 310154e updated README formatting and added blame
|
780
|
+
pick a5f4a0d added cat-file
|
781
|
+
|
782
|
+
Puis, lorsque le script vous laissera accès à la ligne de commande, vous annulerez (*reset*) ce *commit*, vous reprendrez les modifications que vous voulez pour créer plusieurs *commits*.
|
783
|
+
En reprenant l'exemple, lorsque vous sauvegardez et quittez l'éditeur, Git revient au parent de votre premier *commit* de votre liste, applique le premier *commit* (`f7f3f6d`), applique le deuxième (`310154e`), et vous laisse accès à la console.
|
784
|
+
Là, vous pouvez faire une réinitialisation mélangée (*mixed reset*) de ce *commit* avec `git reset HEAD^`, qui défait ce *commit* et laisse les fichiers modifiés non indexés.
|
785
|
+
Maintenant, vous pouvez indexer et valider les fichiers sur plusieurs validations, et exécuter `git rebase --continue` quand vous avez fini :
|
786
|
+
|
787
|
+
$ git reset HEAD^
|
788
|
+
$ git add README
|
789
|
+
$ git commit -m 'updated README formatting'
|
790
|
+
$ git add lib/simplegit.rb
|
791
|
+
$ git commit -m 'added blame'
|
792
|
+
$ git rebase --continue
|
793
|
+
|
794
|
+
Git applique le dernier *commit* (`a5f4a0d`) de votre script, et votre historique ressemblera alors à :
|
795
|
+
|
796
|
+
$ git log -4 --pretty=format:"%h %s"
|
797
|
+
1c002dd added cat-file
|
798
|
+
9b29157 added blame
|
799
|
+
35cfb2b updated README formatting
|
800
|
+
f3cc40e changed my name a bit
|
801
|
+
|
802
|
+
Une fois encore, ceci modifie les empreintes SHA de tous les *commits* dans votre liste, soyez donc sûr qu'aucun *commit* de cette liste n'ait été poussé dans un dépôt partagé.
|
803
|
+
|
804
|
+
### L'option nucléaire : `filter-branch` ###
|
805
|
+
|
806
|
+
Il existe une autre option de la réécriture d'historique que vous pouvez utiliser si vous avez besoin de réécrire un grand nombre de *commits* d'une manière scriptable ; par exemple, modifier globalement votre adresse mail ou supprimer un fichier de tous les *commits*.
|
807
|
+
La commande est `filter-branch`, et elle peut réécrire des pans entiers de votre historique, vous ne devriez donc pas l'utiliser à moins que votre projet ne soit pas encore public ou que personne n'ait encore travaillé sur les *commits* que vous allez réécrire.
|
808
|
+
Cependant, cela peut être très utile.
|
809
|
+
Vous allez maintenant apprendre quelques usages communs pour vous donner une idée de ses capacités.
|
810
|
+
|
811
|
+
#### Supprimer un fichier de chaque *commit* ####
|
812
|
+
|
813
|
+
Cela arrive assez fréquemment.
|
814
|
+
Quelqu'un a accidentellement validé un énorme fichier binaire avec une commande `git add .` irréfléchie, et vous voulez le supprimer partout.
|
815
|
+
Vous avez peut-être validé un fichier contenant un mot de passe et vous voulez rendre votre projet open source.
|
816
|
+
`filter-branch` est l'outil que vous voulez probablement utiliser pour nettoyer votre historique entier.
|
817
|
+
Pour supprimer un fichier nommé « passwords.txt » de tout votre historique, vous pouvez utiliser l'option `--tree-filter` de `filter-branch` :
|
818
|
+
|
819
|
+
$ git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
|
820
|
+
Rewrite 6b9b3cf04e7c5686a9cb838c3f36a8cb6a0fc2bd (21/21)
|
821
|
+
Ref 'refs/heads/master' was rewritten
|
822
|
+
|
823
|
+
L'option `--tree-filter` exécute la commande spécifiée pour chaque *commit* et le revalide ensuite.
|
824
|
+
Dans le cas présent, vous supprimez le fichier nommé « passwords.txt » de chaque contenu, qu'il existait ou non.
|
825
|
+
Si vous voulez supprimer tous les fichiers temporaires des éditeurs validés accidentellement, vous pouvez exécuter une commande telle que `git filter-branch --tree-filter "find * -type f -name '*~' -delete" HEAD`.
|
826
|
+
|
827
|
+
Vous pourrez alors regarder Git réécrire l'arbre des *commits* et revalider à chaque fois, pour finir en modifiant la référence de la branche.
|
828
|
+
C'est généralement une bonne idée de le faire dans un branche de test puis de faire une réinitialisation forte (*hard-reset*) de votre branche `master` si le résultat vous convient.
|
829
|
+
Pour exécuter `filter-branch` sur toutes vos branches, vous pouvez ajouter `--all` à la commande.
|
830
|
+
|
831
|
+
#### Faire d'un sous-répertoire la nouvelle racine ####
|
832
|
+
|
833
|
+
Supposons que vous avez importé votre projet depuis un autre système de gestion de configuration et que vous avez des sous-répertoires qui n'ont aucun sens (trunk, tags, etc.).
|
834
|
+
Si vous voulez faire en sorte que le sous-répertoire `trunk` soit la nouvelle racine de votre projet pour tous les *commits*, `filter-branch` peut aussi vous aider à le faire :
|
835
|
+
|
836
|
+
$ git filter-branch --subdirectory-filter trunk HEAD
|
837
|
+
Rewrite 856f0bf61e41a27326cdae8f09fe708d679f596f (12/12)
|
838
|
+
Ref 'refs/heads/master' was rewritten
|
839
|
+
|
840
|
+
Maintenant votre nouvelle racine est remplacée par le contenu du répertoire `trunk`.
|
841
|
+
De plus, Git supprimera automatiquement les *commits* qui n'affectent pas ce sous-répertoire.
|
842
|
+
|
843
|
+
#### Modifier globalement l'adresse mail ####
|
844
|
+
|
845
|
+
Un autre cas habituel est que vous oubliez d'exécuter `git config` pour configurer votre nom et votre adresse mail avant de commencer à travailler, ou vous voulez peut-être rendre un projet du boulot open source et donc changer votre adresse professionnelle pour celle personnelle.
|
846
|
+
Dans tous les cas, vous pouvez modifier l'adresse mail dans plusieurs *commits* avec un script `filter-branch`.
|
847
|
+
Vous devez faire attention de ne changer que votre adresse mail, utilisez donc `--commit-filter` :
|
848
|
+
|
849
|
+
$ git filter-branch --commit-filter '
|
850
|
+
if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
|
851
|
+
then
|
852
|
+
GIT_AUTHOR_NAME="Scott Chacon";
|
853
|
+
GIT_AUTHOR_EMAIL="schacon@example.com";
|
854
|
+
git commit-tree "$@";
|
855
|
+
else
|
856
|
+
git commit-tree "$@";
|
857
|
+
fi' HEAD
|
858
|
+
|
859
|
+
Cela passe sur chaque *commit* et le réécrit pour avoir votre nouvelle adresse.
|
860
|
+
Mais puisque les *commits* contiennent l'empreinte SHA-1 de leur parent, cette commande modifie tous les *commits* dans votre historique, pas seulement ceux correspondant à votre adresse mail.
|
861
|
+
|
862
|
+
## Deboguer avec Git ##
|
863
|
+
|
864
|
+
Git fournit aussi quelques outils pour vous aider à déboguer votre projet.
|
865
|
+
Puisque Git est conçu pour fonctionner avec pratiquement tout type de projet, ces outils sont plutôt génériques, mais ils peuvent souvent vous aider à traquer un bogue ou au moins cerner où cela tourne mal.
|
866
|
+
|
867
|
+
### Fichier annoté ###
|
868
|
+
|
869
|
+
Si vous traquez un bogue dans votre code et que vous voulez savoir quand il est apparu et pourquoi, annoter les fichiers est souvent le meilleur moyen.
|
870
|
+
Cela vous montre le dernier *commit* qui a modifié chaque ligne de votre fichier.
|
871
|
+
Donc, si vous voyez une méthode dans votre code qui est boguée, vous pouvez visualiser le fichier annoté avec `git blame` pour voir quand chaque ligne de la méthode a été modifiée pour la dernière fois et par qui.
|
872
|
+
Cet exemple utilise l'option `-L` pour limiter la sortie des lignes 12 à 22 :
|
873
|
+
|
874
|
+
$ git blame -L 12,22 simplegit.rb
|
875
|
+
^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 12) def show(tree = 'master')
|
876
|
+
^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 13) command("git show #{tree}")
|
877
|
+
^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 14) end
|
878
|
+
^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 15)
|
879
|
+
9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 16) def log(tree = 'master')
|
880
|
+
79eaf55d (Scott Chacon 2008-04-06 10:15:08 -0700 17) command("git log #{tree}")
|
881
|
+
9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 18) end
|
882
|
+
9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 19)
|
883
|
+
42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 20) def blame(path)
|
884
|
+
42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 21) command("git blame #{path}")
|
885
|
+
42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 22) end
|
886
|
+
|
887
|
+
Remarquez que le premier champ est le SHA-1 partiel du dernier *commit* à avoir modifié la ligne.
|
888
|
+
Les deux champs suivants sont des valeurs extraites du *commit* : l'auteur et la date du *commit*, vous pouvez donc facilement voir qui a modifié la ligne et quand.
|
889
|
+
Ensuite arrive le numéro de ligne et son contenu.
|
890
|
+
Remarquez également les lignes dont le *commit* est `^4832fe2`, elles désignent les lignes qui étaient dans la version du fichier lors du premier *commit* de ce fichier.
|
891
|
+
Ce *commit* contient le premier ajout de ce fichier, et ces lignes n'ont pas été modifiées depuis.
|
892
|
+
Tout ça est un peu confus, parce que vous connaissez maintenant au moins trois façons différentes que Git interprète `^` pour modifier l'empreinte SHA, mais au moins, vous savez ce qu'il signifie ici.
|
893
|
+
|
894
|
+
Une autre chose sympa sur Git, c'est qu'il ne suit pas explicitement les renommages de fichier.
|
895
|
+
Il enregistre les contenus puis essaye de deviner ce qui a été renommé implicitement, après coup.
|
896
|
+
Ce qui nous permet d'utiliser cette fonctionnalité intéressante pour suivre toutes sortes de mouvements de code.
|
897
|
+
Si vous passez `-C` à `git blame`, Git analyse le fichier que vous voulez annoter et essaye de deviner d'où les bouts de code proviennent par copie ou déplacement.
|
898
|
+
Récemment, j'ai remanié un fichier nommé `GITServerHandler.m` en le divisant en plusieurs fichiers, dont le fichier `GITPackUpload.m`.
|
899
|
+
En annotant `GITPackUpload.m` avec l'option `-C`, je peux voir quelles sections de code en sont originaires :
|
900
|
+
|
901
|
+
$ git blame -C -L 141,153 GITPackUpload.m
|
902
|
+
f344f58d GITServerHandler.m (Scott 2009-01-04 141)
|
903
|
+
f344f58d GITServerHandler.m (Scott 2009-01-04 142) - (void) gatherObjectShasFromC
|
904
|
+
f344f58d GITServerHandler.m (Scott 2009-01-04 143) {
|
905
|
+
70befddd GITServerHandler.m (Scott 2009-03-22 144) //NSLog(@"GATHER COMMI
|
906
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 145)
|
907
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 146) NSString *parentSha;
|
908
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 147) GITCommit *commit = [g
|
909
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 148)
|
910
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 149) //NSLog(@"GATHER COMMI
|
911
|
+
ad11ac80 GITPackUpload.m (Scott 2009-03-24 150)
|
912
|
+
56ef2caf GITServerHandler.m (Scott 2009-01-05 151) if(commit) {
|
913
|
+
56ef2caf GITServerHandler.m (Scott 2009-01-05 152) [refDict setOb
|
914
|
+
56ef2caf GITServerHandler.m (Scott 2009-01-05 153)
|
915
|
+
|
916
|
+
C'est vraiment utile, non ?
|
917
|
+
Normalement, vous obtenez comme *commit* originel celui dont votre code a été copié, puisque ce fut la première fois que vous avez touché à ces lignes dans ce fichier.
|
918
|
+
Git vous montre le *commit* d'origine, celui où vous avez écrit ces lignes, même si c'était dans un autre fichier.
|
919
|
+
|
920
|
+
### La recherche dichotomique ###
|
921
|
+
|
922
|
+
Annoter un fichier peut aider si vous savez déjà où le problème se situe.
|
923
|
+
Si vous ne savez pas ce qui a cassé le code, il peut y avoir des douzaines, voire des centaines de *commits* depuis le dernier état où votre code fonctionnait et vous aimeriez certainement exécuter `git bisect` pour vous aider.
|
924
|
+
La commande `bisect` effectue une recherche par dichotomie dans votre historique pour vous aider à identifier aussi vite que possible quel *commit* a vu le bogue naître.
|
925
|
+
|
926
|
+
Disons que vous venez juste de pousser une version finale de votre code en production, vous récupérez un rapport de bogue à propos de quelque chose qui n'arrivait pas dans votre environnement de développement, et vous n'arrivez pas à trouver pourquoi votre code le fait.
|
927
|
+
Vous retournez sur votre code et il apparait que vous pouvez reproduire le bogue mais vous ne savez pas ce qui se passe mal.
|
928
|
+
Vous pouvez faire une recherche par dichotomie pour trouver ce qui ne va pas.
|
929
|
+
D'abord, exécutez `git bisect start` pour démarrer la procédure, puis utilisez la commande `git bisect bad` pour dire que le *commit* courant est bogué.
|
930
|
+
Ensuite, dites à `bisect` quand le code fonctionnait, en utilisant `git bisect good [bonne_version]` :
|
931
|
+
|
932
|
+
$ git bisect start
|
933
|
+
$ git bisect bad
|
934
|
+
$ git bisect good v1.0
|
935
|
+
Bisecting: 6 revisions left to test after this
|
936
|
+
[ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo
|
937
|
+
|
938
|
+
Git trouve qu'il y a environ 12 *commits* entre celui que vous avez marqué comme le dernier bon connu (v1.0) et la version courante qui n'est pas bonne, et il a récupéré le *commit* du milieu à votre place.
|
939
|
+
À ce moment, vous pouvez dérouler vos tests pour voir si le bogue existait dans ce *commit*.
|
940
|
+
Si c'est le cas, il a été introduit quelque part avant ce *commit* médian, sinon, il l'a été évidemment après.
|
941
|
+
Il apparait que le bogue ne se reproduit pas ici, vous le dites à Git en tapant `git bisect good` et continuez votre périple :
|
942
|
+
|
943
|
+
$ git bisect good
|
944
|
+
Bisecting: 3 revisions left to test after this
|
945
|
+
[b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing
|
946
|
+
|
947
|
+
Vous êtes maintenant sur un autre *commit*, à mi-chemin entre celui que vous venez de tester et votre *commit* bogué.
|
948
|
+
Vous exécutez une nouvelle fois votre test et trouvez que ce *commit* est bogué, vous le dites à Git avec `git bisect bad` :
|
949
|
+
|
950
|
+
$ git bisect bad
|
951
|
+
Bisecting: 1 revisions left to test after this
|
952
|
+
[f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table
|
953
|
+
|
954
|
+
Ce *commit*-ci est bon, et Git a maintenant toutes les informations dont il a besoin pour déterminer où le bogue a été créé.
|
955
|
+
Il vous affiche le SHA-1 du premier *commit* bogué, quelques informations du *commit* et quels fichiers ont été modifiés dans celui-ci, vous pouvez donc trouver ce qui s'est passé pour créer ce bogue :
|
956
|
+
|
957
|
+
$ git bisect good
|
958
|
+
b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit
|
959
|
+
commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04
|
960
|
+
Author: PJ Hyett <pjhyett@example.com>
|
961
|
+
Date: Tue Jan 27 14:48:32 2009 -0800
|
962
|
+
|
963
|
+
secure this thing
|
964
|
+
|
965
|
+
:040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730
|
966
|
+
f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config
|
967
|
+
|
968
|
+
Lorsque vous avez fini, vous devez exécuter `git bisect reset` pour réinitialiser votre HEAD où vous étiez avant de commencer, ou vous travaillerez dans un répertoire de travail non clairement défini :
|
969
|
+
|
970
|
+
$ git bisect reset
|
971
|
+
|
972
|
+
C'est un outil puissant qui vous aidera à vérifier des centaines de *commits* en quelques minutes.
|
973
|
+
En réalité, si vous avez un script qui sort avec une valeur 0 s'il est bon et autre chose sinon, vous pouvez même automatiser `git bisect`.
|
974
|
+
Premièrement vous lui spécifiez l'intervalle en lui fournissant les bon et mauvais *commits* connus.
|
975
|
+
Vous pouvez faire cela en une ligne en les entrant à la suite de la commande `bisect start`, le mauvais *commit* d'abord :
|
976
|
+
|
977
|
+
$ git bisect start HEAD v1.0
|
978
|
+
$ git bisect run test-error.sh
|
979
|
+
|
980
|
+
Cela exécute automatiquement `test-error.sh` sur chaque *commit* jusqu'à ce que Git trouve le premier *commit* bogué.
|
981
|
+
Vous pouvez également exécuter des commandes comme `make` ou `make tests` ou quoi que ce soit qui exécute des tests automatisés à votre place.
|
982
|
+
|
983
|
+
## Sous-modules ##
|
984
|
+
|
985
|
+
Il arrive souvent lorsque vous travaillez sur un projet que vous deviez utiliser un autre projet comme dépendance.
|
986
|
+
Cela peut être une bibliothèque qui est développée par une autre équipe ou que vous développez séparément pour l'utiliser dans plusieurs projets parents.
|
987
|
+
Ce scénario provoque un problème habituel : vous voulez être capable de gérer deux projets séparés tout en utilisant l'un dans l'autre.
|
988
|
+
|
989
|
+
Voici un exemple.
|
990
|
+
Supposons que vous développez un site web et que vous créez des flux Atom.
|
991
|
+
Plutôt que d'écrire votre propre code de génération Atom, vous décidez d'utiliser une bibliothèque.
|
992
|
+
Vous allez vraisemblablement devoir soit inclure ce code depuis un gestionnaire partagé comme CPAN ou Ruby gem, soit copier le code source dans votre propre arborescence de projet.
|
993
|
+
Le problème d'inclure la bibliothèque en tant que bibliothèque externe est qu'il est difficile de la personnaliser de quelque manière que ce soit et encore plus de la déployer, car vous devez vous assurer de la disponibilité de la bibliothèque chez chaque client.
|
994
|
+
Mais le problème d'inclure le code dans votre propre projet est que n'importe quelle personnalisation que vous faites est difficile à fusionner lorsque les modifications du développement principal arrivent.
|
995
|
+
|
996
|
+
Git gère ce problème avec les sous-modules.
|
997
|
+
Les sous-modules vous permettent de gérer un dépôt Git comme un sous-répertoire d'un autre dépôt Git.
|
998
|
+
Cela vous laisse la possibilité de cloner un dépôt dans votre projet et de garder isolés les *commits* de ce dépôt.
|
999
|
+
|
1000
|
+
### Démarrer un sous-module ###
|
1001
|
+
|
1002
|
+
Supposons que vous voulez ajouter la bibliothèque Rack (un serveur d'application web en Ruby) à votre projet, avec la possibilité de gérer vos propres changements à celle-ci mais en continuant de fusionner avec la branche principale.
|
1003
|
+
La première chose que vous devez faire est de cloner le dépôt externe dans votre sous-répertoire.
|
1004
|
+
Ajouter des projets externes comme sous-modules de votre projet se fait avec la commande `git submodule add` :
|
1005
|
+
|
1006
|
+
$ git submodule add git://github.com/chneukirchen/rack.git rack
|
1007
|
+
Initialized empty Git repository in /opt/subtest/rack/.git/
|
1008
|
+
remote: Counting objects: 3181, done.
|
1009
|
+
remote: Compressing objects: 100% (1534/1534), done.
|
1010
|
+
remote: Total 3181 (delta 1951), reused 2623 (delta 1603)
|
1011
|
+
Receiving objects: 100% (3181/3181), 675.42 KiB | 422 KiB/s, done.
|
1012
|
+
Resolving deltas: 100% (1951/1951), done.
|
1013
|
+
|
1014
|
+
Vous avez maintenant le projet Rack dans le sous-répertoire `rack` à l'intérieur de votre propre projet.
|
1015
|
+
Vous pouvez aller dans ce sous-répertoire, effectuer des modifications, ajouter votre propre dépôt distant pour y pousser vos modifications, récupérer et fusionner depuis le dépôt originel, et plus encore.
|
1016
|
+
Si vous exécutez `git status` juste après avoir ajouté le sous-module (donc dans le répertoire parent du répertoire `rack`), vous verrez deux choses :
|
1017
|
+
|
1018
|
+
$ git status
|
1019
|
+
# On branch master
|
1020
|
+
# Changes to be committed:
|
1021
|
+
# (use "git reset HEAD <file>..." to unstage)
|
1022
|
+
#
|
1023
|
+
# new file: .gitmodules
|
1024
|
+
# new file: rack
|
1025
|
+
#
|
1026
|
+
|
1027
|
+
Premièrement, vous remarquerez le fichier `.gitmodules`.
|
1028
|
+
C'est un fichier de configuration sauvegardant la liaison entre l'URL du projet et le sous-répertoire local où vous l'avez mis :
|
1029
|
+
|
1030
|
+
$ cat .gitmodules
|
1031
|
+
[submodule "rack"]
|
1032
|
+
path = rack
|
1033
|
+
url = git://github.com/chneukirchen/rack.git
|
1034
|
+
|
1035
|
+
Si vous avez plusieurs sous-modules, vous aurez plusieurs entrées dans ce fichier.
|
1036
|
+
Il est important de noter que ce fichier est en gestion de version comme vos autres fichiers, à l'instar de votre fichier `.gitignore`.
|
1037
|
+
Il est poussé et tiré comme le reste de votre projet.
|
1038
|
+
C'est également le moyen que les autres personnes qui clonent votre projet puissent savoir où récupérer le projet du sous-module.
|
1039
|
+
|
1040
|
+
L'autre information dans la sortie de `git status` est l'entrée `rack`.
|
1041
|
+
Si vous exécutez `git diff`, vous verrez quelque chose d'intéressant :
|
1042
|
+
|
1043
|
+
$ git diff --cached rack
|
1044
|
+
diff --git a/rack b/rack
|
1045
|
+
new file mode 160000
|
1046
|
+
index 0000000..08d709f
|
1047
|
+
--- /dev/null
|
1048
|
+
+++ b/rack
|
1049
|
+
@@ -0,0 +1 @@
|
1050
|
+
+Subproject commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
|
1051
|
+
|
1052
|
+
Même si `rack` est un sous-répertoire de votre répertoire de travail, Git le voit comme un sous-module et ne suit pas son contenu (si vous n'êtes pas dans ce répertoire).
|
1053
|
+
En échange, Git l'enregistre comme un *commit* particulier de ce dépôt.
|
1054
|
+
Lorsque vous faites des modifications et des validations dans ce sous-répertoire, le super-projet (le projet contenant le sous-module) remarque que la branche HEAD a changé et enregistre le *commit* exact dans lequel il se trouve à ce moment.
|
1055
|
+
De cette manière, lorsque d'autres clonent ce super-projet, ils peuvent recréer exactement le même environnement.
|
1056
|
+
|
1057
|
+
Un autre point important avec les sous-modules : Git enregistre le *commit* exact où ils se trouvent.
|
1058
|
+
Vous ne pouvez pas enregistrer un module comme étant en branche `master` ou n'importe quelle autre référence symbolique.
|
1059
|
+
|
1060
|
+
Au moment de valider, vous voyez quelque chose comme :
|
1061
|
+
|
1062
|
+
$ git commit -m 'first commit with submodule rack'
|
1063
|
+
[master 0550271] first commit with submodule rack
|
1064
|
+
2 files changed, 4 insertions(+), 0 deletions(-)
|
1065
|
+
create mode 100644 .gitmodules
|
1066
|
+
create mode 160000 rack
|
1067
|
+
|
1068
|
+
Remarquez le mode 160000 pour l'entrée `rack`.
|
1069
|
+
C'est un mode spécial de Git qui signifie globalement que vous êtes en train d'enregistrer un *commit* comme un répertoire plutôt qu'un sous-répertoire ou un fichier.
|
1070
|
+
|
1071
|
+
Vous pouvez traiter le répertoire `rack` comme un projet séparé et mettre à jour votre super-projet de temps en temps avec une référence au dernier *commit* de ce sous-projet.
|
1072
|
+
Toutes les commandes Git fonctionnent indépendamment dans les deux répertoires :
|
1073
|
+
|
1074
|
+
$ git log -1
|
1075
|
+
commit 0550271328a0038865aad6331e620cd7238601bb
|
1076
|
+
Author: Scott Chacon <schacon@gmail.com>
|
1077
|
+
Date: Thu Apr 9 09:03:56 2009 -0700
|
1078
|
+
|
1079
|
+
first commit with submodule rack
|
1080
|
+
$ cd rack/
|
1081
|
+
$ git log -1
|
1082
|
+
commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
|
1083
|
+
Author: Christian Neukirchen <chneukirchen@gmail.com>
|
1084
|
+
Date: Wed Mar 25 14:49:04 2009 +0100
|
1085
|
+
|
1086
|
+
Document version change
|
1087
|
+
|
1088
|
+
### Cloner un projet avec des sous-modules ###
|
1089
|
+
|
1090
|
+
Maintenant, vous allez apprendre à cloner un projet contenant des sous-modules.
|
1091
|
+
Quand vous récupérez un tel projet, vous obtenez les différents répertoires qui contiennent les sous-modules, mais encore aucun des fichiers :
|
1092
|
+
|
1093
|
+
$ git clone git://github.com/schacon/myproject.git
|
1094
|
+
Initialized empty Git repository in /opt/myproject/.git/
|
1095
|
+
remote: Counting objects: 6, done.
|
1096
|
+
remote: Compressing objects: 100% (4/4), done.
|
1097
|
+
remote: Total 6 (delta 0), reused 0 (delta 0)
|
1098
|
+
Receiving objects: 100% (6/6), done.
|
1099
|
+
$ cd myproject
|
1100
|
+
$ ls -l
|
1101
|
+
total 8
|
1102
|
+
-rw-r--r-- 1 schacon admin 3 Apr 9 09:11 README
|
1103
|
+
drwxr-xr-x 2 schacon admin 68 Apr 9 09:11 rack
|
1104
|
+
$ ls rack/
|
1105
|
+
$
|
1106
|
+
|
1107
|
+
Le répertoire `rack` est présent mais vide.
|
1108
|
+
Vous devez exécuter deux commandes : `git submodule init` pour initialiser votre fichier local de configuration, et `git submodule update` pour tirer toutes les données de ce projet et récupérer le *commit* approprié tel que listé dans votre super-projet :
|
1109
|
+
|
1110
|
+
$ git submodule init
|
1111
|
+
Submodule 'rack' (git://github.com/chneukirchen/rack.git) registered for path 'rack'
|
1112
|
+
$ git submodule update
|
1113
|
+
Initialized empty Git repository in /opt/myproject/rack/.git/
|
1114
|
+
remote: Counting objects: 3181, done.
|
1115
|
+
remote: Compressing objects: 100% (1534/1534), done.
|
1116
|
+
remote: Total 3181 (delta 1951), reused 2623 (delta 1603)
|
1117
|
+
Receiving objects: 100% (3181/3181), 675.42 KiB | 173 KiB/s, done.
|
1118
|
+
Resolving deltas: 100% (1951/1951), done.
|
1119
|
+
Submodule path 'rack': checked out '08d709f78b8c5b0fbeb7821e37fa53e69afcf433'
|
1120
|
+
|
1121
|
+
Votre répertoire `rack` est maintenant dans l'état exact dans lequel il était la dernière fois que vous avez validé.
|
1122
|
+
Si un autre développeur modifie le code de `rack` et valide, que vous tirez cette référence et que vous fusionnez, vous obtiendrez quelque chose d'un peu étrange :
|
1123
|
+
|
1124
|
+
$ git merge origin/master
|
1125
|
+
Updating 0550271..85a3eee
|
1126
|
+
Fast forward
|
1127
|
+
rack | 2 +-
|
1128
|
+
1 files changed, 1 insertions(+), 1 deletions(-)
|
1129
|
+
[master*]$ git status
|
1130
|
+
# On branch master
|
1131
|
+
# Changes not staged for commit:
|
1132
|
+
# (use "git add <file>..." to update what will be committed)
|
1133
|
+
# (use "git checkout -- <file>..." to discard changes in working directory)
|
1134
|
+
#
|
1135
|
+
# modified: rack
|
1136
|
+
#
|
1137
|
+
|
1138
|
+
En réalité, vous n'avez fusionné que la modification de la référence de votre sous-module, mais Git n'a pas mis à jour le code dans le répertoire du sous-module, de ce fait, cela ressemble à un état « en cours » dans votre répertoire de travail :
|
1139
|
+
|
1140
|
+
$ git diff
|
1141
|
+
diff --git a/rack b/rack
|
1142
|
+
index 6c5e70b..08d709f 160000
|
1143
|
+
--- a/rack
|
1144
|
+
+++ b/rack
|
1145
|
+
@@ -1 +1 @@
|
1146
|
+
-Subproject commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
|
1147
|
+
+Subproject commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
|
1148
|
+
|
1149
|
+
La cause de tout cela, c'est que la référence pour votre sous-module ne correspond pas à ce qu'il y a actuellement dans son répertoire.
|
1150
|
+
Pour corriger ça, vous devez exécuter une nouvelle fois `git submodule update` :
|
1151
|
+
|
1152
|
+
$ git submodule update
|
1153
|
+
remote: Counting objects: 5, done.
|
1154
|
+
remote: Compressing objects: 100% (3/3), done.
|
1155
|
+
remote: Total 3 (delta 1), reused 2 (delta 0)
|
1156
|
+
Unpacking objects: 100% (3/3), done.
|
1157
|
+
From git@github.com:schacon/rack
|
1158
|
+
08d709f..6c5e70b master -> origin/master
|
1159
|
+
Submodule path 'rack': checked out '6c5e70b984a60b3cecd395edd5b48a7575bf58e0'
|
1160
|
+
|
1161
|
+
Vous devez faire cela à chaque fois que vous récupérez une modification du sous-module dans le projet principal.
|
1162
|
+
C'est étrange, mais ça fonctionne.
|
1163
|
+
|
1164
|
+
Un problème habituel peut survenir lorsqu'un développeur modifie localement un sous-module, mais ne le pousse pas sur un serveur public.
|
1165
|
+
Puis, il valide une référence à cet état non public et pousse le super-projet.
|
1166
|
+
Lorsque les autres développeurs exécutent `git submodule update`, le système dans le sous-module ne trouve pas le *commit* qui est référencé, car il existe uniquement sur le système du premier développeur.
|
1167
|
+
Dans ce cas, vous verrez une erreur de ce style :
|
1168
|
+
|
1169
|
+
$ git submodule update
|
1170
|
+
fatal: reference isn’t a tree: 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
|
1171
|
+
Unable to checkout '6c5e70b984a60b3cecd395edd5ba7575bf58e0' in submodule path 'rack'
|
1172
|
+
|
1173
|
+
Vous devez regarder qui a modifié le sous-module en dernier :
|
1174
|
+
|
1175
|
+
$ git log -1 rack
|
1176
|
+
commit 85a3eee996800fcfa91e2119372dd4172bf76678
|
1177
|
+
Author: Scott Chacon <schacon@gmail.com>
|
1178
|
+
Date: Thu Apr 9 09:19:14 2009 -0700
|
1179
|
+
|
1180
|
+
added a submodule reference I will never make public. hahahahaha!
|
1181
|
+
|
1182
|
+
Envoyez-lui un mail pour lui crier dessus.
|
1183
|
+
|
1184
|
+
### Super-projets ###
|
1185
|
+
|
1186
|
+
Parfois, les développeurs désirent séparer un gros projet en sous-répertoires en fonction de l'équipe qui travaille dessus.
|
1187
|
+
C'est logique si vous venez de CVS ou de Subversion, où vous aviez l'habitude de définir un module ou un ensemble de sous-répertoires, et que vous voulez garder ce type de procédure de travail.
|
1188
|
+
|
1189
|
+
Une bonne manière de le faire avec Git est de créer un dépôt Git pour chaque sous-dossier, et de créer un super-projet contenant les différents modules.
|
1190
|
+
Le bénéfice de cette approche est de pouvoir spécifier les relations entre les projets avec des étiquettes et des branches depuis le super-projet.
|
1191
|
+
|
1192
|
+
### Les problèmes avec les sous-modules ###
|
1193
|
+
|
1194
|
+
Cependant, utiliser des sous-modules ne se déroule pas sans accroc.
|
1195
|
+
Premièrement, vous devez être relativement prudent lorsque vous travaillez dans le répertoire du sous-module.
|
1196
|
+
Lorsque vous exécutez `git submodule update`, cela récupère une version spécifique d'un projet, mais pas à l'intérieur d'une branche.
|
1197
|
+
Cela s'appelle avoir la tête en l'air (*detached head*), c'est-à-dire que votre HEAD référence directement un *commit*, pas une référence symbolique.
|
1198
|
+
Le problème est que vous ne voulez généralement pas travailler dans un environnement tête en l'air, car il est facile de perdre des modifications dans ces conditions.
|
1199
|
+
Si vous faites un premier `git submodule update`, que vous validez des modifications dans ce sous-module sans créer vous-même de branche pour y travailler, et que vous exécutez un nouveau `git submodule update` depuis le projet parent sans y avoir validé pendant ce temps, Git écrasera vos modifications sans vous le dire.
|
1200
|
+
Techniquement, vous ne perdrez pas votre travail, mais vous n'aurez aucune branche s'y référant, il sera donc assez difficile de le récupérer.
|
1201
|
+
|
1202
|
+
Pour éviter ce problème, créez toujours une branche lorsque vous travaillez dans un répertoire de sous-module avec `git checkout -b work` ou une autre commande équivalente.
|
1203
|
+
Lorsque vous mettrez à jour le sous-module une deuxième fois, Git réinitialisera toujours votre travail, mais vous aurez au moins une référence à votre travail pour y retourner.
|
1204
|
+
|
1205
|
+
Commuter des branches qui contiennent des sous-modules peut également s'avérer difficile.
|
1206
|
+
Si vous créez une nouvelle branche, y ajoutez un sous-module, et revenez ensuite à une branche dépourvue de ce sous-module, vous aurez toujours le répertoire de ce sous-module comme un répertoire non suivi :
|
1207
|
+
|
1208
|
+
$ git checkout -b rack
|
1209
|
+
Switched to a new branch "rack"
|
1210
|
+
$ git submodule add git@github.com:schacon/rack.git rack
|
1211
|
+
Initialized empty Git repository in /opt/myproj/rack/.git/
|
1212
|
+
...
|
1213
|
+
Receiving objects: 100% (3184/3184), 677.42 KiB | 34 KiB/s, done.
|
1214
|
+
Resolving deltas: 100% (1952/1952), done.
|
1215
|
+
$ git commit -am 'added rack submodule'
|
1216
|
+
[rack cc49a69] added rack submodule
|
1217
|
+
2 files changed, 4 insertions(+), 0 deletions(-)
|
1218
|
+
create mode 100644 .gitmodules
|
1219
|
+
create mode 160000 rack
|
1220
|
+
$ git checkout master
|
1221
|
+
Switched to branch "master"
|
1222
|
+
$ git status
|
1223
|
+
# On branch master
|
1224
|
+
# Untracked files:
|
1225
|
+
# (use "git add <file>..." to include in what will be committed)
|
1226
|
+
#
|
1227
|
+
# rack/
|
1228
|
+
|
1229
|
+
|
1230
|
+
Vous devez soit déplacer ce répertoire hors de votre dépôt local, soit le supprimer et dans ce dernier cas, vous devrez le cloner une nouvelle fois lorsque vous recommuterez et vous pouvez donc perdre des modifications ou des branches locales si vous ne les avez pas poussées.
|
1231
|
+
|
1232
|
+
La dernière difficulté présentée consiste à passer d'un sous-répertoire à un sous-module.
|
1233
|
+
Si vous suiviez des fichiers dans votre projet et que vous voulez les déplacer dans un sous-module, vous devez être très prudent ou Git sera inflexible.
|
1234
|
+
Présumons que vous avez les fichiers du projet `rack` dans un sous-répertoire de votre projet, et que vous voulez les transformer en un sous-module.
|
1235
|
+
Si vous supprimez le sous-répertoire et que vous exécutez `submodule add`, Git vous hurle dessus avec :
|
1236
|
+
|
1237
|
+
$ rm -Rf rack/
|
1238
|
+
$ git submodule add git@github.com:schacon/rack.git rack
|
1239
|
+
'rack' already exists in the index
|
1240
|
+
|
1241
|
+
Vous devez d'abord supprimer le répertoire `rack` de l'index.
|
1242
|
+
Vous pourrez ensuite ajouter le sous-module :
|
1243
|
+
|
1244
|
+
$ git rm -r rack
|
1245
|
+
$ git submodule add git@github.com:schacon/rack.git rack
|
1246
|
+
Initialized empty Git repository in /opt/testsub/rack/.git/
|
1247
|
+
remote: Counting objects: 3184, done.
|
1248
|
+
remote: Compressing objects: 100% (1465/1465), done.
|
1249
|
+
remote: Total 3184 (delta 1952), reused 2770 (delta 1675)
|
1250
|
+
Receiving objects: 100% (3184/3184), 677.42 KiB | 88 KiB/s, done.
|
1251
|
+
Resolving deltas: 100% (1952/1952), done.
|
1252
|
+
|
1253
|
+
Maintenant, supposons que vous avez fait cela dans une branche.
|
1254
|
+
Si vous essayez de basculer dans une ancienne branche où ces fichiers sont toujours dans l'arbre de projet plutôt que comme sous-module, vous aurez cette erreur :
|
1255
|
+
|
1256
|
+
$ git checkout master
|
1257
|
+
error: Untracked working tree file 'rack/AUTHORS' would be overwritten by merge.
|
1258
|
+
|
1259
|
+
Vous devez déplacer le répertoire du sous-module `rack` en dehors de votre dépôt local avant de pouvoir basculer vers une branche qui ne l'a pas :
|
1260
|
+
|
1261
|
+
$ mv rack /tmp/
|
1262
|
+
$ git checkout master
|
1263
|
+
Switched to branch "master"
|
1264
|
+
$ ls
|
1265
|
+
README rack
|
1266
|
+
|
1267
|
+
Puis, lorsque vous recommutez, vous aurez un répertoire `rack` vide.
|
1268
|
+
Vous pouvez soit exécuter `git submodule update` pour cloner une nouvelle fois, ou vous pouvez remettre votre répertoire `/tmp/rack` dans votre répertoire vide.
|
1269
|
+
|
1270
|
+
## Fusion de sous-arborescences ##
|
1271
|
+
|
1272
|
+
Maintenant que vous avez vu les difficultés qu'il peut y avoir avec le système de sous-module, voyons une alternative pour résoudre la même problématique.
|
1273
|
+
Lorsque Git fusionne, il regarde ce qu'il doit fusionner et choisit alors une stratégie de fusion appropriée.
|
1274
|
+
Si vous fusionnez deux branches, Git utilise une stratégie _récursive_ (_recursive_ strategy).
|
1275
|
+
Si vous fusionnez plus de deux branches, Git choisit la stratégie de la _pieuvre_ (_octopus_ strategy).
|
1276
|
+
Ces stratégies sont choisies automatiquement car la stratégie récursive peut gérer des problèmes complexes de fusions à trois entrées avec par exemple plus d'un ancêtre commun, mais il ne peut gérer que deux branches à fusionner.
|
1277
|
+
La fusion de la pieuvre peut gérer plusieurs branches mais elle est plus prudente afin d'éviter les conflits difficiles, elle est donc choisie comme stratégie par défaut si vous essayez de fusionner plus de deux branches.
|
1278
|
+
|
1279
|
+
Cependant, il existe d'autres stratégies que vous pouvez tout aussi bien choisir.
|
1280
|
+
L'une d'elles est la fusion de sous-arborescence que vous pouvez utiliser pour gérer la problématique du sous-projet.
|
1281
|
+
Nous allons donc voir comment gérer l'inclusion de `rack` comme dans la section précédente, mais en utilisant cette fois-ci les fusions de sous-arborescence.
|
1282
|
+
|
1283
|
+
La fusion de sous-arborescence suppose que vous ayez deux projets et que l'un s'identifie à un sous-répertoire de l'autre.
|
1284
|
+
Lorsque vous spécifiez une fusion de sous-arborescence, Git est assez intelligent pour deviner lequel est un sous-répertoire de l'autre et fusionne en conséquence — c'est assez bluffant.
|
1285
|
+
|
1286
|
+
Premièrement, vous ajoutez l'application Rack à votre projet.
|
1287
|
+
Vous ajoutez le projet Rack comme une référence distante dans votre propre projet et le récupérez dans sa propre branche :
|
1288
|
+
|
1289
|
+
$ git remote add rack_remote git@github.com:schacon/rack.git
|
1290
|
+
$ git fetch rack_remote
|
1291
|
+
warning: no common commits
|
1292
|
+
remote: Counting objects: 3184, done.
|
1293
|
+
remote: Compressing objects: 100% (1465/1465), done.
|
1294
|
+
remote: Total 3184 (delta 1952), reused 2770 (delta 1675)
|
1295
|
+
Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, done.
|
1296
|
+
Resolving deltas: 100% (1952/1952), done.
|
1297
|
+
From git@github.com:schacon/rack
|
1298
|
+
* [new branch] build -> rack_remote/build
|
1299
|
+
* [new branch] master -> rack_remote/master
|
1300
|
+
* [new branch] rack-0.4 -> rack_remote/rack-0.4
|
1301
|
+
* [new branch] rack-0.9 -> rack_remote/rack-0.9
|
1302
|
+
$ git checkout -b rack_branch rack_remote/master
|
1303
|
+
Branch rack_branch set up to track remote branch refs/remotes/rack_remote/master.
|
1304
|
+
Switched to a new branch "rack_branch"
|
1305
|
+
|
1306
|
+
Vous avez maintenant la racine du projet Rack dans votre branche `rack_branch` et votre propre projet dans la branche `master`.
|
1307
|
+
Si vous récupérez l'une puis l'autre branche, vous pouvez voir que vous avez différentes racines de projet :
|
1308
|
+
|
1309
|
+
$ ls
|
1310
|
+
AUTHORS KNOWN-ISSUES Rakefile contrib lib
|
1311
|
+
COPYING README bin example test
|
1312
|
+
$ git checkout master
|
1313
|
+
Switched to branch "master"
|
1314
|
+
$ ls
|
1315
|
+
README
|
1316
|
+
|
1317
|
+
Pour tirer le projet Rack dans votre projet `master` comme un sous-répertoire, vous pouvez utiliser la commande `git read-tree`.
|
1318
|
+
Vous apprendrez davantage sur `read-tree` et compagnie dans le chapitre 9, mais pour le moment, sachez qu'il lit la racine d'une de vos branches et l'inscrit dans votre index et votre répertoire de travail.
|
1319
|
+
Vous venez juste de commuter vers votre branche `master` et vous tirez la branche `rack_branch` vers le sous-répertoire `rack` de votre branche `master` de votre projet principal :
|
1320
|
+
|
1321
|
+
$ git read-tree --prefix=rack/ -u rack_branch
|
1322
|
+
|
1323
|
+
Au moment de valider, vous verrez tous les fichiers de Rack de ce sous-répertoire, comme si vous les aviez copiés depuis une archive.
|
1324
|
+
Ce qui est intéressant, c'est que vous pouvez assez facilement fusionner les changements d'une branche à l'autre.
|
1325
|
+
Par conséquence, s'il y a des mises à jour pour le projet Rack, vous pouvez les tirer depuis le dépôt principal en commutant dans cette branche et tirant les modifications :
|
1326
|
+
|
1327
|
+
$ git checkout rack_branch
|
1328
|
+
$ git pull
|
1329
|
+
|
1330
|
+
Puis, vous pouvez fusionner ces changements dans votre branche principale.
|
1331
|
+
Vous pouvez utiliser `git merge -s subtree` et cela fonctionnera, mais Git fusionnera également les historiques ensemble, ce que vous ne voulez probablement pas.
|
1332
|
+
Pour tirer les changements et préremplir le message de validation, utilisez les options `--squash` et `--no-commit` avec l'option de stratégie `-s subtree` :
|
1333
|
+
|
1334
|
+
$ git checkout master
|
1335
|
+
$ git merge --squash -s subtree --no-commit rack_branch
|
1336
|
+
Squash commit -- not updating HEAD
|
1337
|
+
Automatic merge went well; stopped before committing as requested
|
1338
|
+
|
1339
|
+
Toutes les modifications de votre projet Rack sont fusionnées et prêtes à être validées localement.
|
1340
|
+
Vous pouvez également faire le contraire, faire des modifications dans le sous-répertoire `rack` de votre branche principale et les fusionner plus tard dans votre branche `rack_branch` pour les envoyer aux mainteneurs du projet Rack ou les pousser dans le dépôt principal.
|
1341
|
+
|
1342
|
+
Pour voir les différences entre ce que vous avez dans le sous-répertoire `rack` et le code de la branche `rack_branch` (pour savoir si vous devez les fusionner), vous ne pouvez pas utiliser la commande `diff` habituelle.
|
1343
|
+
Vous devez plutôt exécuter `git diff-tree` en renseignant la branche avec laquelle vous voulez comparer :
|
1344
|
+
|
1345
|
+
$ git diff-tree -p rack_branch
|
1346
|
+
|
1347
|
+
Ou, pour comparer ce qu'il y a dans votre répertoire `rack` avec ce qu'il y avait sur le serveur la dernière fois que vous avez vérifié, vous pouvez exécuter :
|
1348
|
+
|
1349
|
+
$ git diff-tree -p rack_remote/master
|
1350
|
+
|
1351
|
+
## Résumé ##
|
1352
|
+
|
1353
|
+
Vous venez de voir certains des outils avancés vous permettant de manipuler vos *commits* et votre index plus précisément.
|
1354
|
+
Lorsque vous remarquez des bogues, vous devriez être capable de facilement trouver quelle validation les a introduits, quand et par qui.
|
1355
|
+
Si vous voulez utiliser des sous-projets dans votre projet, vous avez appris plusieurs façons de les gérer.
|
1356
|
+
À partir de maintenant, vous devez être capable de faire la plupart de ce dont vous avez besoin avec Git en ligne de commande et de vous y sentir à l'aise.
|