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.

Files changed (501) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -2
  3. data/README.md +67 -42
  4. data/Rakefile +22 -2
  5. data/commonmarker.gemspec +13 -9
  6. data/ext/commonmarker/cmark/api_test/main.c +35 -0
  7. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeError.log +12 -12
  8. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeOutput.log +141 -141
  9. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/main.c.o +0 -0
  10. data/ext/commonmarker/cmark/build/api_test/api_test +0 -0
  11. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/houdini_html_u.c.o +0 -0
  12. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/iterator.c.o +0 -0
  13. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/houdini_html_u.c.o +0 -0
  14. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/iterator.c.o +0 -0
  15. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_u.c.o +0 -0
  16. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/iterator.c.o +0 -0
  17. data/ext/commonmarker/cmark/build/src/cmark +0 -0
  18. data/ext/commonmarker/cmark/build/src/libcmark.0.19.0.dylib +0 -0
  19. data/ext/commonmarker/cmark/build/src/libcmark.a +0 -0
  20. data/ext/commonmarker/cmark/build/src/libcmark.dylib +0 -0
  21. data/ext/commonmarker/cmark/src/houdini_html_u.c +26 -13
  22. data/ext/commonmarker/cmark/src/iterator.c +2 -2
  23. data/ext/commonmarker/cmark/test/__pycache__/cmark.cpython-34.pyc +0 -0
  24. data/ext/commonmarker/cmark/test/__pycache__/normalize.cpython-34.pyc +0 -0
  25. data/ext/commonmarker/cmark/test/cmark.pyc +0 -0
  26. data/ext/commonmarker/cmark/test/normalize.pyc +0 -0
  27. data/ext/commonmarker/commonmarker.c +276 -3
  28. data/ext/commonmarker/extconf.rb +3 -1
  29. data/lib/commonmarker.rb +70 -360
  30. data/lib/commonmarker/config.rb +1 -1
  31. data/lib/commonmarker/renderer.rb +91 -0
  32. data/lib/commonmarker/renderer/html_renderer.rb +149 -0
  33. data/lib/commonmarker/version.rb +1 -1
  34. data/test/benchinput.md +148414 -0
  35. data/test/benchmark.rb +13 -9
  36. data/test/progit/Gemfile +5 -0
  37. data/test/progit/README.md +9 -0
  38. data/test/progit/README.original.md +70 -0
  39. data/test/progit/Rakefile +285 -0
  40. data/test/progit/ar/01-introduction/01-chapter1.markdown +264 -0
  41. data/test/progit/ar/02-git-basics/01-chapter2.markdown +1124 -0
  42. data/test/progit/ar/NOTES +18 -0
  43. data/test/progit/ar/README +14 -0
  44. data/test/progit/az/01-introduction/01-chapter1.markdown +257 -0
  45. data/test/progit/az/02-git-basics/01-chapter2.markdown +1127 -0
  46. data/test/progit/az/03-git-branching/01-chapter3.markdown +598 -0
  47. data/test/progit/az/04-git-server/01-chapter4.markdown +861 -0
  48. data/test/progit/az/05-distributed-git/01-chapter5.markdown +897 -0
  49. data/test/progit/az/06-git-tools/01-chapter6.markdown +1126 -0
  50. data/test/progit/az/07-customizing-git/01-chapter7.markdown +937 -0
  51. data/test/progit/az/08-git-and-other-scms/01-chapter8.markdown +690 -0
  52. data/test/progit/az/09-git-internals/01-chapter9.markdown +977 -0
  53. data/test/progit/be/01-introduction/01-chapter1.markdown +257 -0
  54. data/test/progit/be/02-git-basics/01-chapter2.markdown +1126 -0
  55. data/test/progit/ca/01-introduction/01-chapter1.markdown +257 -0
  56. data/test/progit/ca/README.txt +1 -0
  57. data/test/progit/couchapp/Makefile +41 -0
  58. data/test/progit/couchapp/Readme.md +17 -0
  59. data/test/progit/couchapp/_id +1 -0
  60. data/test/progit/couchapp/shows/chapter.js +14 -0
  61. data/test/progit/couchapp/templates/foot.html +7 -0
  62. data/test/progit/couchapp/templates/head.html +51 -0
  63. data/test/progit/couchapp/vendor/markdown/showdown.js +420 -0
  64. data/test/progit/couchapp/vendor/mustache.js/mustache.js +302 -0
  65. data/test/progit/cs/01-introduction/01-chapter1.markdown +259 -0
  66. data/test/progit/cs/02-git-basics/01-chapter2.markdown +1225 -0
  67. data/test/progit/cs/03-git-branching/01-chapter3.markdown +606 -0
  68. data/test/progit/cs/04-git-server/01-chapter4.markdown +871 -0
  69. data/test/progit/cs/05-distributed-git/01-chapter5.markdown +914 -0
  70. data/test/progit/cs/06-git-tools/01-chapter6.markdown +1167 -0
  71. data/test/progit/cs/07-customizing-git/01-chapter7.markdown +940 -0
  72. data/test/progit/cs/08-git-and-other-scms/01-chapter8.markdown +700 -0
  73. data/test/progit/cs/09-git-internals/01-chapter9.markdown +1014 -0
  74. data/test/progit/de/01-introduction/01-chapter1.markdown +445 -0
  75. data/test/progit/de/02-git-basics/01-chapter2.markdown +1589 -0
  76. data/test/progit/de/03-git-branching/01-chapter3.markdown +964 -0
  77. data/test/progit/de/04-git-server/01-chapter4.markdown +1337 -0
  78. data/test/progit/de/05-distributed-git/01-chapter5.markdown +1329 -0
  79. data/test/progit/de/06-git-tools/01-chapter6.markdown +1502 -0
  80. data/test/progit/de/07-customizing-git/01-chapter7.markdown +1361 -0
  81. data/test/progit/de/08-git-and-other-scms/01-chapter8.markdown +919 -0
  82. data/test/progit/de/09-git-internals/01-chapter9.markdown +1361 -0
  83. data/test/progit/de/README.md +626 -0
  84. data/test/progit/ebooks/cover.png +0 -0
  85. data/test/progit/en/01-introduction/01-chapter1.markdown +263 -0
  86. data/test/progit/en/02-git-basics/01-chapter2.markdown +1228 -0
  87. data/test/progit/en/03-git-branching/01-chapter3.markdown +606 -0
  88. data/test/progit/en/04-git-server/01-chapter4.markdown +871 -0
  89. data/test/progit/en/05-distributed-git/01-chapter5.markdown +914 -0
  90. data/test/progit/en/06-git-tools/01-chapter6.markdown +1150 -0
  91. data/test/progit/en/07-customizing-git/01-chapter7.markdown +940 -0
  92. data/test/progit/en/08-git-and-other-scms/01-chapter8.markdown +700 -0
  93. data/test/progit/en/09-git-internals/01-chapter9.markdown +983 -0
  94. data/test/progit/eo/01-introduction/01-chapter1.markdown +257 -0
  95. data/test/progit/eo/02-git-basics/01-chapter2.markdown +1171 -0
  96. data/test/progit/epub/ProGit.css +28 -0
  97. data/test/progit/epub/title.png +0 -0
  98. data/test/progit/es-ni/01-introduction/01-chapter1.markdown +257 -0
  99. data/test/progit/es-ni/02-git-basics/01-chapter2.markdown +1127 -0
  100. data/test/progit/es/01-introduction/01-chapter1.markdown +262 -0
  101. data/test/progit/es/02-git-basics/01-chapter2.markdown +1165 -0
  102. data/test/progit/es/03-git-branching/01-chapter3.markdown +598 -0
  103. data/test/progit/es/04-git-server/01-chapter4.markdown +707 -0
  104. data/test/progit/es/05-distributed-git/01-chapter5.markdown +890 -0
  105. data/test/progit/es/06-git-tools/01-chapter6.markdown +1113 -0
  106. data/test/progit/es/07-customizing-git/01-chapter7.markdown +875 -0
  107. data/test/progit/es/08-git-and-other-scms/01-chapter8.markdown +686 -0
  108. data/test/progit/es/09-git-internals/01-chapter9.markdown +976 -0
  109. data/test/progit/es/NOTES +29 -0
  110. data/test/progit/es/README +3 -0
  111. data/test/progit/es/glosario-Benzirpi.txt +27 -0
  112. data/test/progit/es/omegat-Benzirpi.tmx +29075 -0
  113. data/test/progit/fa/01-introduction/01-chapter1.markdown +262 -0
  114. data/test/progit/fa/03-git-branching/01-chapter3.markdown +608 -0
  115. data/test/progit/fa/04-git-server/01-chapter4.markdown +872 -0
  116. data/test/progit/fa/NOTES.en-fa.md +143 -0
  117. data/test/progit/fa/README.md +7 -0
  118. data/test/progit/fi/01-introduction/01-chapter1.markdown +259 -0
  119. data/test/progit/fi/02-git-basics/01-chapter2.markdown +1171 -0
  120. data/test/progit/fi/NOTES +5 -0
  121. data/test/progit/figures-dia/fig0101.dia +617 -0
  122. data/test/progit/figures-dia/fig0102.dia +921 -0
  123. data/test/progit/figures-dia/fig0103.dia +1468 -0
  124. data/test/progit/figures-dia/fig0104.dia +1432 -0
  125. data/test/progit/figures-dia/fig0105.dia +1924 -0
  126. data/test/progit/figures-dia/fig0106.dia +562 -0
  127. data/test/progit/figures-dia/fig0201.dia +774 -0
  128. data/test/progit/figures-dia/fig0301.dia +2006 -0
  129. data/test/progit/figures-dia/fig0302.dia +2148 -0
  130. data/test/progit/figures-dia/fig0303.dia +719 -0
  131. data/test/progit/figures-dia/fig0304.dia +525 -0
  132. data/test/progit/figures-dia/fig0305.dia +622 -0
  133. data/test/progit/figures-dia/fig0306.dia +622 -0
  134. data/test/progit/figures-dia/fig0307.dia +719 -0
  135. data/test/progit/figures-dia/fig0308.dia +734 -0
  136. data/test/progit/figures-dia/fig0309.dia +831 -0
  137. data/test/progit/figures-dia/fig0310.dia +412 -0
  138. data/test/progit/figures-dia/fig0311.dia +493 -0
  139. data/test/progit/figures-dia/fig0312.dia +596 -0
  140. data/test/progit/figures-dia/fig0313.dia +774 -0
  141. data/test/progit/figures-dia/fig0314.dia +846 -0
  142. data/test/progit/figures-dia/fig0315.dia +787 -0
  143. data/test/progit/figures-dia/fig0316.dia +1078 -0
  144. data/test/progit/figures-dia/fig0317.dia +881 -0
  145. data/test/progit/figures-dia/fig0318.dia +968 -0
  146. data/test/progit/figures-dia/fig0319.dia +957 -0
  147. data/test/progit/figures-dia/fig0320.dia +1637 -0
  148. data/test/progit/figures-dia/fig0321.dia +1494 -0
  149. data/test/progit/figures-dia/fig0322.dia +1142 -0
  150. data/test/progit/figures-dia/fig0323.dia +1377 -0
  151. data/test/progit/figures-dia/fig0324.dia +1603 -0
  152. data/test/progit/figures-dia/fig0325.dia +2003 -0
  153. data/test/progit/figures-dia/fig0326.dia +2013 -0
  154. data/test/progit/figures-dia/fig0327.dia +687 -0
  155. data/test/progit/figures-dia/fig0328.dia +814 -0
  156. data/test/progit/figures-dia/fig0329.dia +793 -0
  157. data/test/progit/figures-dia/fig0330.dia +693 -0
  158. data/test/progit/figures-dia/fig0331.dia +1159 -0
  159. data/test/progit/figures-dia/fig0332.dia +1362 -0
  160. data/test/progit/figures-dia/fig0333.dia +1165 -0
  161. data/test/progit/figures-dia/fig0334.dia +1450 -0
  162. data/test/progit/figures-dia/fig0335.dia +994 -0
  163. data/test/progit/figures-dia/fig0336.dia +786 -0
  164. data/test/progit/figures-dia/fig0337.dia +1546 -0
  165. data/test/progit/figures-dia/fig0338.dia +1755 -0
  166. data/test/progit/figures-dia/fig0339.dia +1882 -0
  167. data/test/progit/figures-dia/fig0501.dia +456 -0
  168. data/test/progit/figures-dia/fig0502.dia +956 -0
  169. data/test/progit/figures-dia/fig0503.dia +915 -0
  170. data/test/progit/figures-dia/fig0504.dia +620 -0
  171. data/test/progit/figures-dia/fig0505.dia +744 -0
  172. data/test/progit/figures-dia/fig0506.dia +747 -0
  173. data/test/progit/figures-dia/fig0507.dia +895 -0
  174. data/test/progit/figures-dia/fig0508.dia +1122 -0
  175. data/test/progit/figures-dia/fig0509.dia +1243 -0
  176. data/test/progit/figures-dia/fig0510.dia +1240 -0
  177. data/test/progit/figures-dia/fig0511.dia +1201 -0
  178. data/test/progit/figures-dia/fig0512.dia +801 -0
  179. data/test/progit/figures-dia/fig0513.dia +1387 -0
  180. data/test/progit/figures-dia/fig0514.dia +1568 -0
  181. data/test/progit/figures-dia/fig0515.dia +1721 -0
  182. data/test/progit/figures-dia/fig0516.dia +997 -0
  183. data/test/progit/figures-dia/fig0517.dia +994 -0
  184. data/test/progit/figures-dia/fig0518.dia +1145 -0
  185. data/test/progit/figures-dia/fig0519.dia +992 -0
  186. data/test/progit/figures-dia/fig0520.dia +1240 -0
  187. data/test/progit/figures-dia/fig0521.dia +801 -0
  188. data/test/progit/figures-dia/fig0522.dia +922 -0
  189. data/test/progit/figures-dia/fig0523.dia +922 -0
  190. data/test/progit/figures-dia/fig0524.dia +1828 -0
  191. data/test/progit/figures-dia/fig0525.dia +2685 -0
  192. data/test/progit/figures-dia/fig0526.dia +717 -0
  193. data/test/progit/figures-dia/fig0527.dia +856 -0
  194. data/test/progit/figures-dia/fig0601.dia +790 -0
  195. data/test/progit/figures-dia/fig0702.dia +795 -0
  196. data/test/progit/figures-dia/fig0703.dia +795 -0
  197. data/test/progit/figures-dia/fig0901.dia +669 -0
  198. data/test/progit/figures-dia/fig0902.dia +834 -0
  199. data/test/progit/figures-dia/fig0903.dia +1483 -0
  200. data/test/progit/figures-dia/fig0904.dia +1728 -0
  201. data/test/progit/figures-dia/makeimages +25 -0
  202. data/test/progit/figures-source/progit.graffle +123108 -0
  203. data/test/progit/figures/18333fig0101-tn.png +0 -0
  204. data/test/progit/figures/18333fig0102-tn.png +0 -0
  205. data/test/progit/figures/18333fig0103-tn.png +0 -0
  206. data/test/progit/figures/18333fig0104-tn.png +0 -0
  207. data/test/progit/figures/18333fig0105-tn.png +0 -0
  208. data/test/progit/figures/18333fig0106-tn.png +0 -0
  209. data/test/progit/figures/18333fig0107-tn.png +0 -0
  210. data/test/progit/figures/18333fig0201-tn.png +0 -0
  211. data/test/progit/figures/18333fig0202-tn.png +0 -0
  212. data/test/progit/figures/18333fig0301-tn.png +0 -0
  213. data/test/progit/figures/18333fig0302-tn.png +0 -0
  214. data/test/progit/figures/18333fig0303-tn.png +0 -0
  215. data/test/progit/figures/18333fig0304-tn.png +0 -0
  216. data/test/progit/figures/18333fig0305-tn.png +0 -0
  217. data/test/progit/figures/18333fig0306-tn.png +0 -0
  218. data/test/progit/figures/18333fig0307-tn.png +0 -0
  219. data/test/progit/figures/18333fig0308-tn.png +0 -0
  220. data/test/progit/figures/18333fig0309-tn.png +0 -0
  221. data/test/progit/figures/18333fig0310-tn.png +0 -0
  222. data/test/progit/figures/18333fig0311-tn.png +0 -0
  223. data/test/progit/figures/18333fig0312-tn.png +0 -0
  224. data/test/progit/figures/18333fig0313-tn.png +0 -0
  225. data/test/progit/figures/18333fig0314-tn.png +0 -0
  226. data/test/progit/figures/18333fig0315-tn.png +0 -0
  227. data/test/progit/figures/18333fig0316-tn.png +0 -0
  228. data/test/progit/figures/18333fig0317-tn.png +0 -0
  229. data/test/progit/figures/18333fig0318-tn.png +0 -0
  230. data/test/progit/figures/18333fig0319-tn.png +0 -0
  231. data/test/progit/figures/18333fig0320-tn.png +0 -0
  232. data/test/progit/figures/18333fig0321-tn.png +0 -0
  233. data/test/progit/figures/18333fig0322-tn.png +0 -0
  234. data/test/progit/figures/18333fig0323-tn.png +0 -0
  235. data/test/progit/figures/18333fig0324-tn.png +0 -0
  236. data/test/progit/figures/18333fig0325-tn.png +0 -0
  237. data/test/progit/figures/18333fig0326-tn.png +0 -0
  238. data/test/progit/figures/18333fig0327-tn.png +0 -0
  239. data/test/progit/figures/18333fig0328-tn.png +0 -0
  240. data/test/progit/figures/18333fig0329-tn.png +0 -0
  241. data/test/progit/figures/18333fig0330-tn.png +0 -0
  242. data/test/progit/figures/18333fig0331-tn.png +0 -0
  243. data/test/progit/figures/18333fig0332-tn.png +0 -0
  244. data/test/progit/figures/18333fig0333-tn.png +0 -0
  245. data/test/progit/figures/18333fig0334-tn.png +0 -0
  246. data/test/progit/figures/18333fig0335-tn.png +0 -0
  247. data/test/progit/figures/18333fig0336-tn.png +0 -0
  248. data/test/progit/figures/18333fig0337-tn.png +0 -0
  249. data/test/progit/figures/18333fig0338-tn.png +0 -0
  250. data/test/progit/figures/18333fig0339-tn.png +0 -0
  251. data/test/progit/figures/18333fig0401-tn.png +0 -0
  252. data/test/progit/figures/18333fig0402-tn.png +0 -0
  253. data/test/progit/figures/18333fig0403-tn.png +0 -0
  254. data/test/progit/figures/18333fig0404-tn.png +0 -0
  255. data/test/progit/figures/18333fig0405-tn.png +0 -0
  256. data/test/progit/figures/18333fig0406-tn.png +0 -0
  257. data/test/progit/figures/18333fig0407-tn.png +0 -0
  258. data/test/progit/figures/18333fig0408-tn.png +0 -0
  259. data/test/progit/figures/18333fig0409-tn.png +0 -0
  260. data/test/progit/figures/18333fig0410-tn.png +0 -0
  261. data/test/progit/figures/18333fig0411-tn.png +0 -0
  262. data/test/progit/figures/18333fig0412-tn.png +0 -0
  263. data/test/progit/figures/18333fig0413-tn.png +0 -0
  264. data/test/progit/figures/18333fig0414-tn.png +0 -0
  265. data/test/progit/figures/18333fig0415-tn.png +0 -0
  266. data/test/progit/figures/18333fig0501-tn.png +0 -0
  267. data/test/progit/figures/18333fig0502-tn.png +0 -0
  268. data/test/progit/figures/18333fig0503-tn.png +0 -0
  269. data/test/progit/figures/18333fig0504-tn.png +0 -0
  270. data/test/progit/figures/18333fig0505-tn.png +0 -0
  271. data/test/progit/figures/18333fig0506-tn.png +0 -0
  272. data/test/progit/figures/18333fig0507-tn.png +0 -0
  273. data/test/progit/figures/18333fig0508-tn.png +0 -0
  274. data/test/progit/figures/18333fig0509-tn.png +0 -0
  275. data/test/progit/figures/18333fig0510-tn.png +0 -0
  276. data/test/progit/figures/18333fig0511-tn.png +0 -0
  277. data/test/progit/figures/18333fig0512-tn.png +0 -0
  278. data/test/progit/figures/18333fig0513-tn.png +0 -0
  279. data/test/progit/figures/18333fig0514-tn.png +0 -0
  280. data/test/progit/figures/18333fig0515-tn.png +0 -0
  281. data/test/progit/figures/18333fig0516-tn.png +0 -0
  282. data/test/progit/figures/18333fig0517-tn.png +0 -0
  283. data/test/progit/figures/18333fig0518-tn.png +0 -0
  284. data/test/progit/figures/18333fig0519-tn.png +0 -0
  285. data/test/progit/figures/18333fig0520-tn.png +0 -0
  286. data/test/progit/figures/18333fig0521-tn.png +0 -0
  287. data/test/progit/figures/18333fig0522-tn.png +0 -0
  288. data/test/progit/figures/18333fig0523-tn.png +0 -0
  289. data/test/progit/figures/18333fig0524-tn.png +0 -0
  290. data/test/progit/figures/18333fig0525-tn.png +0 -0
  291. data/test/progit/figures/18333fig0526-tn.png +0 -0
  292. data/test/progit/figures/18333fig0527-tn.png +0 -0
  293. data/test/progit/figures/18333fig0601-tn.png +0 -0
  294. data/test/progit/figures/18333fig0701-tn.png +0 -0
  295. data/test/progit/figures/18333fig0702-tn.png +0 -0
  296. data/test/progit/figures/18333fig0703-tn.png +0 -0
  297. data/test/progit/figures/18333fig0901-tn.png +0 -0
  298. data/test/progit/figures/18333fig0902-tn.png +0 -0
  299. data/test/progit/figures/18333fig0903-tn.png +0 -0
  300. data/test/progit/figures/18333fig0904-tn.png +0 -0
  301. data/test/progit/fr/01-introduction/01-chapter1.markdown +371 -0
  302. data/test/progit/fr/02-git-basics/01-chapter2.markdown +1378 -0
  303. data/test/progit/fr/03-git-branching/01-chapter3.markdown +781 -0
  304. data/test/progit/fr/04-git-server/01-chapter4.markdown +1141 -0
  305. data/test/progit/fr/05-distributed-git/01-chapter5.markdown +1163 -0
  306. data/test/progit/fr/06-git-tools/01-chapter6.markdown +1356 -0
  307. data/test/progit/fr/07-customizing-git/01-chapter7.markdown +1200 -0
  308. data/test/progit/fr/08-git-and-other-scms/01-chapter8.markdown +832 -0
  309. data/test/progit/fr/09-git-internals/01-chapter9.markdown +1228 -0
  310. data/test/progit/fr/NOTES.fr-fr.markdown +1 -0
  311. data/test/progit/fr/NOTES.fr-fr.md +127 -0
  312. data/test/progit/fr/README.md +43 -0
  313. data/test/progit/fr/glossaire-git.adoc +108 -0
  314. data/test/progit/hi/01-introduction/01-chapter1.markdown +7 -0
  315. data/test/progit/hu/01-introduction/01-chapter1.markdown +257 -0
  316. data/test/progit/id/01-introduction/01-chapter1.markdown +257 -0
  317. data/test/progit/id/02-git-basics/01-chapter2.markdown +1127 -0
  318. data/test/progit/id/03-git-branching/01-chapter3.markdown +598 -0
  319. data/test/progit/it/01-introduction/01-chapter1.markdown +263 -0
  320. data/test/progit/it/02-git-basics/01-chapter2.markdown +1227 -0
  321. data/test/progit/it/03-git-branching/01-chapter3.markdown +598 -0
  322. data/test/progit/it/04-git-server/01-chapter4.markdown +864 -0
  323. data/test/progit/it/05-distributed-git/01-chapter5.markdown +897 -0
  324. data/test/progit/it/06-git-tools/01-chapter6.markdown +1144 -0
  325. data/test/progit/it/07-customizing-git/01-chapter7.markdown +606 -0
  326. data/test/progit/it/08-git-and-other-scms/01-chapter8.markdown +707 -0
  327. data/test/progit/it/09-git-internals/01-chapter9.markdown +1000 -0
  328. data/test/progit/ja/01-introduction/01-chapter1.markdown +260 -0
  329. data/test/progit/ja/02-git-basics/01-chapter2.markdown +1221 -0
  330. data/test/progit/ja/03-git-branching/01-chapter3.markdown +604 -0
  331. data/test/progit/ja/04-git-server/01-chapter4.markdown +863 -0
  332. data/test/progit/ja/05-distributed-git/01-chapter5.markdown +908 -0
  333. data/test/progit/ja/06-git-tools/01-chapter6.markdown +1133 -0
  334. data/test/progit/ja/07-customizing-git/01-chapter7.markdown +936 -0
  335. data/test/progit/ja/08-git-and-other-scms/01-chapter8.markdown +690 -0
  336. data/test/progit/ja/09-git-internals/01-chapter9.markdown +984 -0
  337. data/test/progit/ja/README.md +58 -0
  338. data/test/progit/ja/translation glossaries.txt +33 -0
  339. data/test/progit/ko/01-introduction/01-chapter1.markdown +258 -0
  340. data/test/progit/ko/02-git-basics/01-chapter2.markdown +1181 -0
  341. data/test/progit/ko/03-git-branching/01-chapter3.markdown +612 -0
  342. data/test/progit/ko/04-git-server/01-chapter4.markdown +867 -0
  343. data/test/progit/ko/05-distributed-git/01-chapter5.markdown +913 -0
  344. data/test/progit/ko/06-git-tools/01-chapter6.markdown +1142 -0
  345. data/test/progit/ko/07-customizing-git/01-chapter7.markdown +935 -0
  346. data/test/progit/ko/08-git-and-other-scms/01-chapter8.markdown +688 -0
  347. data/test/progit/ko/09-git-internals/01-chapter9.markdown +976 -0
  348. data/test/progit/ko/README.md +75 -0
  349. data/test/progit/ko/translation_guide.txt +65 -0
  350. data/test/progit/latex/README +27 -0
  351. data/test/progit/latex/config.yml +144 -0
  352. data/test/progit/latex/makepdf +207 -0
  353. data/test/progit/latex/template.tex +155 -0
  354. data/test/progit/makeebooks +125 -0
  355. data/test/progit/makepdfs +47 -0
  356. data/test/progit/mk/01-introduction/01-chapter1.markdown +258 -0
  357. data/test/progit/mk/02-git-basics/01-chapter2.markdown +1125 -0
  358. data/test/progit/mk/03-git-branching/01-chapter3.markdown +598 -0
  359. data/test/progit/mk/05-distributed-git/01-chapter5.markdown +897 -0
  360. data/test/progit/nl/01-introduction/01-chapter1.markdown +296 -0
  361. data/test/progit/nl/02-git-basics/01-chapter2.markdown +1253 -0
  362. data/test/progit/nl/03-git-branching/01-chapter3.markdown +642 -0
  363. data/test/progit/nl/04-git-server/01-chapter4.markdown +902 -0
  364. data/test/progit/nl/05-distributed-git/01-chapter5.markdown +953 -0
  365. data/test/progit/nl/06-git-tools/01-chapter6.markdown +1177 -0
  366. data/test/progit/nl/07-customizing-git/01-chapter7.markdown +974 -0
  367. data/test/progit/nl/08-git-and-other-scms/01-chapter8.markdown +725 -0
  368. data/test/progit/nl/09-git-internals/01-chapter9.markdown +1013 -0
  369. data/test/progit/no-nb/01-introduction/01-chapter1.markdown +261 -0
  370. data/test/progit/no-nb/02-git-basics/01-chapter2.markdown +1225 -0
  371. data/test/progit/no-nb/03-git-branching/01-chapter3.markdown +606 -0
  372. data/test/progit/no-nb/04-git-server/01-chapter4.markdown +867 -0
  373. data/test/progit/no-nb/05-distributed-git/01-chapter5.markdown +914 -0
  374. data/test/progit/no-nb/06-git-tools/01-chapter6.markdown +1144 -0
  375. data/test/progit/no-nb/07-customizing-git/01-chapter7.markdown +936 -0
  376. data/test/progit/no-nb/08-git-and-other-scms/01-chapter8.markdown +689 -0
  377. data/test/progit/no-nb/09-git-internals/01-chapter9.markdown +977 -0
  378. data/test/progit/no-nb/README +2 -0
  379. data/test/progit/pl/01-introduction/01-chapter1.markdown +257 -0
  380. data/test/progit/pl/02-git-basics/02-chapter2.markdown +1128 -0
  381. data/test/progit/pl/03-git-branching/01-chapter3.markdown +598 -0
  382. data/test/progit/pl/04-git-server/01-chapter4.markdown +897 -0
  383. data/test/progit/pl/05-distributed-git/01-chapter5.markdown +1278 -0
  384. data/test/progit/pl/06-git-tools/01-chapter6.markdown +1550 -0
  385. data/test/progit/pl/07-customizing-git/01-chapter7.markdown +1058 -0
  386. data/test/progit/pl/08-git-and-other-scms/01-chapter8.markdown +948 -0
  387. data/test/progit/pl/09-git-internals/01-chapter9.markdown +1382 -0
  388. data/test/progit/pl/translation-guidelines.txt +70 -0
  389. data/test/progit/pt-br/01-introduction/01-chapter1.markdown +256 -0
  390. data/test/progit/pt-br/02-git-basics/01-chapter2.markdown +1127 -0
  391. data/test/progit/pt-br/03-git-branching/01-chapter3.markdown +596 -0
  392. data/test/progit/pt-br/04-git-server/01-chapter4.markdown +888 -0
  393. data/test/progit/pt-br/05-distributed-git/01-chapter5.markdown +896 -0
  394. data/test/progit/pt-br/06-git-tools/01-chapter6.markdown +1122 -0
  395. data/test/progit/pt-br/07-customizing-git/01-chapter7.markdown +932 -0
  396. data/test/progit/pt-br/08-git-and-other-scms/01-chapter8.markdown +691 -0
  397. data/test/progit/pt-br/09-git-internals/01-chapter9.markdown +978 -0
  398. data/test/progit/pt-br/figures-dia/fig0101.dia +617 -0
  399. data/test/progit/pt-br/figures-dia/fig0102.dia +921 -0
  400. data/test/progit/pt-br/figures-dia/fig0103.dia +1468 -0
  401. data/test/progit/pt-br/figures-dia/fig0104.dia +1432 -0
  402. data/test/progit/pt-br/figures-dia/fig0105.dia +1924 -0
  403. data/test/progit/pt-br/figures-dia/fig0106.dia +562 -0
  404. data/test/progit/pt-br/figures-dia/fig0201.dia +776 -0
  405. data/test/progit/pt-br/figures-dia/fig0301.dia +2006 -0
  406. data/test/progit/pt-br/figures-dia/fig0302.dia +2148 -0
  407. data/test/progit/pt-br/figures-dia/fig0316.dia +1079 -0
  408. data/test/progit/pt-br/figures-dia/fig0322.dia +1142 -0
  409. data/test/progit/pt-br/figures-dia/fig0323.dia +1407 -0
  410. data/test/progit/pt-br/figures-dia/fig0324.dia +1603 -0
  411. data/test/progit/pt-br/figures-dia/fig0325.dia +2003 -0
  412. data/test/progit/pt-br/figures-dia/fig0326.dia +2013 -0
  413. data/test/progit/pt-br/figures-dia/fig0336.dia +786 -0
  414. data/test/progit/pt-br/figures-dia/fig0337.dia +1546 -0
  415. data/test/progit/pt-br/figures-dia/fig0338.dia +1755 -0
  416. data/test/progit/pt-br/figures-dia/fig0339.dia +1882 -0
  417. data/test/progit/pt-br/figures-dia/fig0501.dia +456 -0
  418. data/test/progit/pt-br/figures-dia/fig0502.dia +965 -0
  419. data/test/progit/pt-br/figures-dia/fig0503.dia +914 -0
  420. data/test/progit/pt-br/figures-dia/fig0511.dia +1201 -0
  421. data/test/progit/pt-br/figures-dia/fig0515.dia +1721 -0
  422. data/test/progit/pt-br/figures-dia/fig0702.dia +795 -0
  423. data/test/progit/pt-br/figures-dia/fig0703.dia +795 -0
  424. data/test/progit/pt-br/figures-dia/fig0901.dia +669 -0
  425. data/test/progit/pt-br/figures-dia/fig0902.dia +834 -0
  426. data/test/progit/pt-br/figures-dia/fig0903.dia +1483 -0
  427. data/test/progit/pt-br/figures-dia/fig0904.dia +1728 -0
  428. data/test/progit/ro/01-introduction/01-chapter1.markdown +257 -0
  429. data/test/progit/ru/01-introduction/01-chapter1.markdown +259 -0
  430. data/test/progit/ru/02-git-basics/01-chapter2.markdown +1155 -0
  431. data/test/progit/ru/03-git-branching/01-chapter3.markdown +598 -0
  432. data/test/progit/ru/04-git-server/01-chapter4.markdown +854 -0
  433. data/test/progit/ru/05-distributed-git/01-chapter5.markdown +897 -0
  434. data/test/progit/ru/06-git-tools/01-chapter6.markdown +1126 -0
  435. data/test/progit/ru/07-customizing-git/01-chapter7.markdown +938 -0
  436. data/test/progit/ru/08-git-and-other-scms/01-chapter8.markdown +691 -0
  437. data/test/progit/ru/09-git-internals/01-chapter9.markdown +977 -0
  438. data/test/progit/ru/Glossary +38 -0
  439. data/test/progit/ru/README +12 -0
  440. data/test/progit/ru/figures-dia/fig0101.dia +647 -0
  441. data/test/progit/ru/figures-dia/fig0102.dia +1009 -0
  442. data/test/progit/ru/figures-dia/fig0103.dia +1468 -0
  443. data/test/progit/ru/figures-dia/fig0104.dia +1432 -0
  444. data/test/progit/ru/figures-dia/fig0105.dia +1924 -0
  445. data/test/progit/ru/figures-dia/fig0106.dia +561 -0
  446. data/test/progit/ru/figures-dia/fig0201.dia +774 -0
  447. data/test/progit/ru/figures-dia/fig0322.dia +1182 -0
  448. data/test/progit/ru/figures-dia/fig0323.dia +1457 -0
  449. data/test/progit/ru/figures-dia/fig0324.dia +1698 -0
  450. data/test/progit/ru/figures-dia/fig0325.dia +2101 -0
  451. data/test/progit/ru/figures-dia/fig0326.dia +2111 -0
  452. data/test/progit/ru/figures-dia/fig0336.dia +786 -0
  453. data/test/progit/ru/figures-dia/fig0337.dia +1546 -0
  454. data/test/progit/ru/figures-dia/fig0338.dia +1755 -0
  455. data/test/progit/ru/figures-dia/fig0339.dia +1882 -0
  456. data/test/progit/ru/figures-dia/fig0501.dia +477 -0
  457. data/test/progit/ru/figures-dia/fig0502.dia +1063 -0
  458. data/test/progit/ru/figures-dia/fig0503.dia +915 -0
  459. data/test/progit/ru/figures-dia/fig0511.dia +1201 -0
  460. data/test/progit/ru/figures-dia/fig0515.dia +1741 -0
  461. data/test/progit/ru/figures-dia/fig0702.dia +851 -0
  462. data/test/progit/ru/figures-dia/fig0703.dia +851 -0
  463. data/test/progit/sr/01-introduction/01-chapter1.markdown +257 -0
  464. data/test/progit/summary.rb +29 -0
  465. data/test/progit/th/01-introduction/01-chapter1.markdown +257 -0
  466. data/test/progit/th/02-git-basics/01-chapter2.markdown +1126 -0
  467. data/test/progit/th/README.md +47 -0
  468. data/test/progit/tr/01-introduction/01-chapter1.markdown +258 -0
  469. data/test/progit/tr/02-git-basics/01-chapter2.markdown +1129 -0
  470. data/test/progit/tr/03-git-branching/01-chapter3.markdown +598 -0
  471. data/test/progit/tr/04-git-server/01-chapter4.markdown +73 -0
  472. data/test/progit/tr/05-distributed-git/01-chapter5.markdown +215 -0
  473. data/test/progit/uk/01-introduction/01-chapter1.markdown +522 -0
  474. data/test/progit/vi/01-introduction/01-chapter1.markdown +259 -0
  475. data/test/progit/vi/02-git-basics/01-chapter2.markdown +1172 -0
  476. data/test/progit/vi/03-git-branching/01-chapter3.markdown +598 -0
  477. data/test/progit/zh-tw/01-introduction/01-chapter1.markdown +259 -0
  478. data/test/progit/zh-tw/02-git-basics/01-chapter2.markdown +1183 -0
  479. data/test/progit/zh-tw/03-git-branching/01-chapter3.markdown +604 -0
  480. data/test/progit/zh-tw/04-git-server/01-chapter4.markdown +866 -0
  481. data/test/progit/zh-tw/05-distributed-git/01-chapter5.markdown +912 -0
  482. data/test/progit/zh-tw/06-git-tools/01-chapter6.markdown +1139 -0
  483. data/test/progit/zh-tw/07-customizing-git/01-chapter7.markdown +932 -0
  484. data/test/progit/zh-tw/08-git-and-other-scms/01-chapter8.markdown +689 -0
  485. data/test/progit/zh-tw/09-git-internals/01-chapter9.markdown +977 -0
  486. data/test/progit/zh/01-introduction/01-chapter1.markdown +259 -0
  487. data/test/progit/zh/02-git-basics/01-chapter2.markdown +1177 -0
  488. data/test/progit/zh/03-git-branching/01-chapter3.markdown +604 -0
  489. data/test/progit/zh/04-git-server/01-chapter4.markdown +866 -0
  490. data/test/progit/zh/05-distributed-git/01-chapter5.markdown +912 -0
  491. data/test/progit/zh/06-git-tools/01-chapter6.markdown +1125 -0
  492. data/test/progit/zh/07-customizing-git/01-chapter7.markdown +935 -0
  493. data/test/progit/zh/08-git-and-other-scms/01-chapter8.markdown +689 -0
  494. data/test/progit/zh/09-git-internals/01-chapter9.markdown +976 -0
  495. data/test/spec_tests.json +4382 -4070
  496. data/test/test_basics.rb +1 -1
  497. data/test/test_helper.rb +1 -0
  498. data/test/test_maliciousness.rb +4 -2
  499. data/test/test_pathological_inputs.rb +31 -30
  500. data/test/test_spec.rb +5 -4
  501. 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.