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,1163 @@
1
+ # Git distribué #
2
+
3
+ Avec un dépôt distant Git mis en place pour permettre à tous les développeurs de partager leur code, et la connaissance des commandes de base de Git pour une gestion locale, abordons les méthodes de gestion distribuée que Git nous offre.
4
+
5
+ Dans ce chapitre, vous découvrirez comment travailler dans un environnement distribué avec Git en tant que contributeur ou comme intégrateur.
6
+ Cela recouvre la manière de contribuer efficacement à un projet et de rendre la vie plus facile au mainteneur du projet ainsi qu'à vous-même, mais aussi en tant que mainteneur, de gérer un projet avec de nombreux contributeurs.
7
+
8
+ ## Développements distribués ##
9
+
10
+ À la différence des systèmes de gestion de version centralisés (CVCS), la nature distribuée de Git permet une bien plus grande flexibilité dans la manière dont les développeurs collaborent sur un projet.
11
+ Dans les systèmes centralisés, tout développeur est un nœud travaillant de manière plus ou moins égale sur un concentrateur central.
12
+ Dans Git par contre, tout développeur est potentiellement un nœud et un concentrateur, c'est-à-dire que chaque développeur peut à la fois contribuer du code vers les autres dépôts et maintenir un dépôt public sur lequel d'autres vont baser leur travail et auquel ils vont contribuer.
13
+ Cette capacité ouvre une perspective de modes de développement pour votre projet ou votre équipe dont certains archétypes tirant parti de cette flexibilité seront traités dans les sections qui suivent.
14
+ Les avantages et inconvénients éventuels de chaque mode seront traités.
15
+ Vous pouvez choisir d'en utiliser un seul ou de mélanger les fonctions de chacun.
16
+
17
+ ### Gestion centralisée ###
18
+
19
+ Dans les systèmes centralisés, il n'y a généralement qu'un seul modèle de collaboration, la gestion centralisée.
20
+ Un concentrateur ou dépôt central accepte le code et tout le monde doit synchroniser son travail avec.
21
+ Les développeurs sont des nœuds, des consommateurs du concentrateur, seul endroit où ils se synchronisent (voir figure 5-1).
22
+
23
+ Insert 18333fig0501.png
24
+ Figure 5-1. La gestion centralisée.
25
+
26
+ Cela signifie que si deux développeurs clonent depuis le concentrateur et qu'ils introduisent tous les deux des modifications, le premier à pousser ses modifications le fera sans encombre.
27
+ Le second développeur doit fusionner les modifications du premier dans son dépôt local avant de pousser ses modifications pour ne pas écraser les modifications du premier.
28
+ Ce concept reste aussi vrai avec Git qu'il l'est avec Subversion (ou tout autre CVCS) et le modèle fonctionne parfaitement dans Git.
29
+
30
+ Si votre équipe est petite et que vous êtes déjà habitués à une gestion centralisée dans votre société ou votre équipe, vous pouvez simplement continuer à utiliser cette méthode avec Git.
31
+ Mettez en place un dépôt unique et donnez à tous l'accès en poussée.
32
+ Git empêchera les utilisateurs d'écraser le travail des autres.
33
+ Si un développeur clone le dépôt central, fait des modifications et essaie de les pousser alors qu'un autre développeur à poussé ses modifications dans le même temps, le serveur rejettera les modifications du premier.
34
+ Il lui sera indiqué qu'il cherche à pousser des modifications sans mode avance rapide et qu'il ne pourra pas le faire tant qu'il n'aura pas récupéré et fusionné les nouvelles modifications depuis le serveur.
35
+ Cette méthode est très intéressante pour de nombreuses personnes car c'est un paradigme avec lequel beaucoup sont familiarisés et à l'aise.
36
+
37
+ ### Mode du gestionnaire d'intégration ###
38
+
39
+ Comme Git permet une multiplicité de dépôts distants, il est possible d'envisager un mode de fonctionnement où chaque développeur a un accès en écriture à son propre dépôt public et en lecture à tous ceux des autres.
40
+ Ce scénario inclut souvent un dépôt canonique qui représente le projet « officiel ».
41
+ Pour commencer à contribuer au projet, vous créez votre propre clone public du projet et poussez vos modifications dessus.
42
+ Après, il suffit d'envoyer une demande au mainteneur de projet pour qu'il tire vos modifications dans le dépôt canonique.
43
+ Il peut ajouter votre dépôt comme dépôt distant, tester vos modifications localement, les fusionner dans sa branche et les pousser vers le dépôt public.
44
+ Le processus se passe comme ceci (voir figure 5-2) :
45
+
46
+ 1. Le mainteneur du projet pousse vers son dépôt public.
47
+ 2. Un contributeur clone ce dépôt et introduit des modifications.
48
+ 3. Le contributeur pousse son travail sur son dépôt public.
49
+ 4. Le contributeur envoie au mainteneur un e-mail de demande pour tirer depuis son dépôt.
50
+ 5. Le mainteneur ajoute le dépôt du contributeur comme dépôt distant et fusionne localement.
51
+ 6. Le mainteneur pousse les modifications fusionnées sur le dépôt principal.
52
+
53
+ Insert 18333fig0502.png
54
+ Figure 5-2. Le mode du gestionnaire d'intégration.
55
+
56
+ C'est une gestion très commune sur des sites tels que GitHub où il est aisé de dupliquer un projet et de pousser ses modifications pour les rendre publiques.
57
+ Un avantage distinctif de cette approche est qu'il devient possible de continuer à travailler et que le mainteneur du dépôt principal peut tirer les modifications à tout moment.
58
+ Les contributeurs n'ont pas à attendre le bon vouloir du mainteneur pour incorporer leurs modifications.
59
+ Chaque acteur peut travailler à son rythme.
60
+
61
+ ### Mode dictateur et ses lieutenants ###
62
+
63
+ C'est une variante de la gestion multi-dépôt.
64
+ En général, ce mode est utilisé sur des projets immenses comprenant des centaines de collaborateurs.
65
+ Un exemple connu en est le noyau Linux.
66
+ Des gestionnaires d'intégration gèrent certaines parties du projet.
67
+ Ce sont les lieutenants.
68
+ Tous les lieutenants ont un unique gestionnaire d'intégration, le dictateur bienveillant.
69
+ Le dépôt du dictateur sert de dépôt de référence à partir duquel tous les collaborateurs doivent tirer.
70
+ Le processus se déroule comme suit (voir figure 5-3) :
71
+
72
+ 1. Les développeurs de base travaillent sur la branche thématique et rebasent leur travail sur master. La branche `master` est celle du dictateur.
73
+ 2. Les lieutenants fusionnent les branches thématiques des développeurs dans leur propre branche `master`.
74
+ 3. Le dictateur fusionne les branches master de ses lieutenants dans sa propre branche `master`.
75
+ 4. Le dictateur pousse sa branche `master` sur le dépôt de référence pour que les développeurs se rebasent dessus.
76
+
77
+ Insert 18333fig0503.png
78
+ Figure 5-3. Le processus du dictateur bienveillant.
79
+
80
+ Ce schéma de processus n'est pas très utilisé mais s'avère utile dans des projets très gros ou pour lesquels un ordre hiérarchique existe, car il permet au chef de projet (le dictateur) de déléguer une grande partie du travail et de collecter de grands sous-ensembles de codes à différents points avant de les intégrer.
81
+
82
+ Ce sont des schémas de processus rendus possibles et généralement utilisés avec des systèmes distribués tels que Git, mais de nombreuses variations restent possibles pour coller à un flux de modifications donné.
83
+ En espérant vous avoir aidé à choisir le meilleur mode de gestion pour votre cas, je vais traiter des exemples plus spécifiques de méthode de réalisation des rôles principaux constituant les différents flux.
84
+
85
+ ## Contribution à un projet ##
86
+
87
+ Vous savez ce que sont les différents modes de gestion et vous devriez connaître suffisamment l'utilisation de Git. Dans cette section, vous apprendrez les moyens les plus utilisés pour contribuer à un projet.
88
+
89
+ La principale difficulté à décrire ce processus réside dans l'extraordinaire quantité de variations dans sa réalisation.
90
+ Comme Git est très flexible, les gens peuvent collaborer de différentes façons et ils le font, et il devient problématique de décrire de manière unique comment devrait se réaliser la contribution à un projet.
91
+ Chaque projet est légèrement différent.
92
+ Les variables incluent la taille du corps des contributeurs, le choix du flux de gestion, les accès en validation et la méthode de contribution externe.
93
+
94
+ La première variable est la taille du corps de contributeurs.
95
+ Combien de personnes contribuent activement du code sur ce projet et à quelle vitesse ?
96
+ Dans de nombreux cas, vous aurez deux à trois développeurs avec quelques validations par jour, voire moins pour des projets endormis.
97
+ Pour des sociétés ou des projets particulièrement grands, le nombre de développeurs peut chiffrer à des milliers, avec des dizaines, voire des centaines de patchs ajoutés chaque jour.
98
+ Ce cas est important car avec de plus en plus de développeurs, les problèmes de fusion et d'application de patch deviennent de plus en plus courants.
99
+ Les modifications soumises par un développeur peuvent être obsolètes ou impossibles à appliquer à cause de changements qui ont eu lieu dans l'intervalle de leur développement, de leur approbation ou de leur application.
100
+ Comment dans ces conditions conserver son code en permanence synchronisé et ses patchs valides ?
101
+
102
+ La variable suivante est le mode de gestion utilisé pour le projet.
103
+ Est-il centralisé avec chaque développeur ayant un accès égal en écriture sur la ligne de développement principale ?
104
+ Le projet présente-t-il un mainteneur ou un gestionnaire d'intégration qui vérifie tous les patchs ?
105
+ Tous les patchs doivent-ils subir une revue de pair et une approbation ?
106
+ Faites-vous partie du processus ?
107
+ Un système à lieutenants est-il en place et doit-on leur soumettre les modifications en premier ?
108
+
109
+ La variable suivante est la gestion des accès en écriture.
110
+ Le mode de gestion nécessaire à la contribution au projet est très différent selon que vous avez ou non accès au dépôt en écriture.
111
+ Si vous n'avez pas accès en écriture, quelle est la méthode préférée pour la soumission de modifications ?
112
+ Y a-t-il seulement une politique en place ?
113
+ Quelle est la quantité de modifications fournie à chaque fois ?
114
+ Quelle est la périodicité de contribution ?
115
+
116
+ Toutes ces questions affectent la manière de contribuer efficacement à un projet et les modes de gestion disponibles ou préférables.
117
+ Je vais traiter ces sujets dans une série de cas d'utilisation allant des plus simples aux plus complexes.
118
+ Vous devriez pouvoir construire vos propres modes de gestion à partir de ces exemples.
119
+
120
+ ### Guides pour une validation ###
121
+
122
+ Avant de passer en revue les cas d'utilisation spécifiques, voici un point rapide sur les messages de validation.
123
+ La définition et l'utilisation d'une bonne ligne de conduite sur les messages de validation facilitent grandement l'utilisation de Git et la collaboration entre développeurs.
124
+ Le projet Git fournit un document qui décrit un certain nombre de bonnes pratiques pour créer des *commits* qui serviront à fournir des patchs — le document est accessible dans les sources de Git, dans le fichier `Documentation/SubmittingPatches`.
125
+
126
+ Premièrement, il ne faut pas soumettre de patchs comportant des erreurs d'espace (caractères espace inutiles en fin de ligne).
127
+ Git fournit un moyen simple de le vérifier — avant de valider, lancez la commande `git diff --check` qui identifiera et listera les erreurs d'espace.
128
+ Voici un exemple dans lequel les caractères en couleur rouge ont été remplacés par des `X` :
129
+
130
+ $ git diff --check
131
+ lib/simplegit.rb:5: trailing whitespace.
132
+ + @git_dir = File.expand_path(git_dir)XX
133
+ lib/simplegit.rb:7: trailing whitespace.
134
+ + XXXXXXXXXXX
135
+ lib/simplegit.rb:26: trailing whitespace.
136
+ + def command(git_cmd)XXXX
137
+
138
+ En lançant cette commande avant chaque validation, vous pouvez vérifier que vous ne commettez pas d'erreurs d'espace qui pourraient ennuyer les autres développeurs.
139
+
140
+ Ensuite, assurez-vous de faire de chaque validation une modification logiquement atomique. Si possible, rendez chaque modification digeste — ne codez pas pendant un week-end entier sur cinq sujets différents pour enfin les soumettre tous dans une énorme validation le lundi suivant.
141
+ Même si vous ne validez pas du week-end, utilisez la zone d'index le lundi pour découper votre travail en au moins une validation par problème, avec un message utile par validation.
142
+ Si certaines modifications touchent au même fichier, essayez d'utiliser `git add --patch` pour indexer partiellement des fichiers (cette fonctionnalité est traitée au chapitre 6).
143
+ L'instantané final sera identique, que vous utilisiez une validation unique ou cinq petites validations, à condition que toutes les modifications soient intégrées à un moment, donc n'hésitez pas à rendre la vie plus simple à vos compagnons développeurs lorsqu'ils auront à vérifier vos modifications.
144
+ Cette approche simplifie aussi le retrait ou l'inversion ultérieurs d'une modification en cas de besoin.
145
+ Le chapitre 6 décrit justement quelques trucs et astuces de Git pour réécrire l'historique et indexer interactivement les fichiers — utilisez ces outils pour fabriquer un historique propre et compréhensible.
146
+
147
+ Le dernier point à soigner est le message de validation.
148
+ S'habituer à écrire des messages de validation de qualité facilite grandement l'emploi et la collaboration avec Git.
149
+ En règle générale, les messages doivent débuter par une ligne unique d'au plus 50 caractères décrivant concisément la modification, suivie d'une ligne vide, suivie d'une explication plus détaillée.
150
+ Le projet Git exige que l'explication détaillée inclue la motivation de la modification en contrastant le nouveau comportement par rapport à l'ancien — c'est une bonne règle de rédaction.
151
+ Une bonne règle consiste aussi à utiliser le présent de l'impératif ou des verbes substantivés dans le message.
152
+ En d'autres termes, utilisez des ordres.
153
+ Au lieu d'écrire « J'ai ajouté des tests pour » ou « En train d'ajouter des tests pour », utilisez juste « Ajoute des tests pour » ou « Ajout de tests pour ».
154
+
155
+ Voici ci-dessous un modèle écrit par Tim Pope at tpope.net :
156
+
157
+
158
+ Court résumé des modifications (50 caractères ou moins)
159
+
160
+ Explication plus détaillée, si nécessaire. Retour à la ligne vers 72
161
+ caractères. Dans certains contextes, la première ligne est traitée
162
+ comme le sujet d'un e-mail et le reste comme le corps. La ligne
163
+ vide qui sépare le titre du corps est importante (à moins d'omettre
164
+ totalement le corps). Des outils tels que rebase peuvent être gênés
165
+ si vous les laissez collés.
166
+
167
+ Paragraphes supplémentaires après des lignes vides.
168
+
169
+ - Les listes à puce sont aussi acceptées
170
+
171
+ - Typiquement, un tiret ou un astérisque précédés d'un espace unique
172
+ séparés par des lignes vides mais les conventions peuvent varier
173
+
174
+ Si tous vos messages de validation ressemblent à ceci, les choses seront beaucoup plus simples pour vous et les développeurs avec qui vous travaillez.
175
+ Le projet Git montre des messages de *commit* bien formatés — je vous encourage à y lancer un `git log --no-merges` pour pouvoir voir comment rend un historique de messages bien formatés.
176
+
177
+ Dans les exemples suivants et à travers tout ce livre, par souci de simplification, je ne formaterai pas les messages aussi proprement.
178
+ J'utiliserai plutôt l'option `-m` de `git commit`.
179
+ Faites ce que je dis, pas ce que je fais.
180
+
181
+ ### Cas d'une petite équipe privée ###
182
+
183
+ Le cas le plus probable que vous rencontrerez est celui du projet privé avec un ou deux autres développeurs.
184
+ Par privé, j'entends code source fermé non accessible au public en lecture.
185
+ Vous et les autres développeurs aurez accès en poussée au dépôt.
186
+
187
+ Dans cet environnement, vous pouvez suivre une méthode similaire à ce que vous feriez en utilisant Subversion ou tout autre système centralisé.
188
+ Vous bénéficiez toujours d'avantages tels que la validation hors-ligne et la gestion de branche et de fusion grandement simplifiée mais les étapes restent similaires.
189
+ La différence principale reste que les fusions ont lieu du côté client plutôt que sur le serveur au moment de valider.
190
+ Voyons à quoi pourrait ressembler la collaboration de deux développeurs sur un dépôt partagé.
191
+ Le premier développeur, John, clone le dépôt, fait une modification et valide localement.
192
+ Dans les exemples qui suivent, les messages de protocole sont remplacés par `...` pour les raccourcir.
193
+
194
+ # Ordinateur de John
195
+ $ git clone john@githost:simplegit.git
196
+ Initialized empty Git repository in /home/john/simplegit/.git/
197
+ ...
198
+ $ cd simplegit/
199
+ $ vim lib/simplegit.rb
200
+ $ git commit -am 'Eliminer une valeur par defaut invalide'
201
+ [master 738ee87] Eliminer une valeur par defaut invalide
202
+ 1 files changed, 1 insertions(+), 1 deletions(-)
203
+
204
+ La deuxième développeuse, Jessica, fait la même chose.
205
+ Elle clone le dépôt et valide une modification :
206
+
207
+ # Ordinateur de Jessica
208
+ $ git clone jessica@githost:simplegit.git
209
+ Initialized empty Git repository in /home/jessica/simplegit/.git/
210
+ ...
211
+ $ cd simplegit/
212
+ $ vim TODO
213
+ $ git commit -am 'Ajouter une tache reset'
214
+ [master fbff5bc] Ajouter une tache reset
215
+ 1 files changed, 1 insertions(+), 0 deletions(-)
216
+
217
+ À présent, Jessica pousse son travail sur le serveur :
218
+
219
+ # Ordinateur de Jessica
220
+ $ git push origin master
221
+ ...
222
+ To jessica@githost:simplegit.git
223
+ 1edee6b..fbff5bc master -> master
224
+
225
+ John tente aussi de pousser ses modifications :
226
+
227
+ # Ordinateur de John
228
+ $ git push origin master
229
+ To john@githost:simplegit.git
230
+ ! [rejected] master -> master (non-fast forward)
231
+ error: failed to push some refs to 'john@githost:simplegit.git'
232
+
233
+ John n'a pas le droit de pousser parce que Jessica a déjà poussé dans l'intervalle.
234
+ Il est très important de comprendre ceci si vous avez déjà utilisé Subversion, parce qu'il faut remarquer que les deux développeurs n'ont pas modifié le même fichier.
235
+ Quand des fichiers différents ont été modifiés, Subversion réalise cette fusion automatiquement sur le serveur alors que Git nécessite une fusion des modifications locale.
236
+ John doit récupérer les modifications de Jessica et les fusionner avant d'être autorisé à pousser :
237
+
238
+ $ git fetch origin
239
+ ...
240
+ From john@githost:simplegit
241
+ + 049d078...fbff5bc master -> origin/master
242
+
243
+ À présent, le dépôt local de John ressemble à la figure 5-4.
244
+
245
+ Insert 18333fig0504.png
246
+ Figure 5-4. État initial du dépôt de John.
247
+
248
+ John a une référence aux modifications que Jessica a poussées, mais il doit les fusionner dans sa propre branche avant de pouvoir pousser :
249
+
250
+ $ git merge origin/master
251
+ Merge made by recursive.
252
+ TODO | 1 +
253
+ 1 files changed, 1 insertions(+), 0 deletions(-)
254
+
255
+ Cette fusion se passe sans problème — l'historique de *commits* de John ressemble à présent à la figure 5-5.
256
+
257
+ Insert 18333fig0505.png
258
+ Figure 5-5. Le dépôt local de John après la fusion d'`origin/master`.
259
+
260
+ Maintenant, John peut tester son code pour s'assurer qu'il fonctionne encore correctement et peut pousser son travail nouvellement fusionné sur le serveur :
261
+
262
+ $ git push origin master
263
+ ...
264
+ To john@githost:simplegit.git
265
+ fbff5bc..72bbc59 master -> master
266
+
267
+ À la fin, l'historique des *commits* de John ressemble à la figure 5-6.
268
+
269
+ Insert 18333fig0506.png
270
+ Figure 5-6. L'historique de John après avoir poussé sur le serveur origin.
271
+
272
+ Dans l'intervalle, Jessica a travaillé sur une branche thématique.
273
+ Elle a créé une branche thématique nommée `prob54` et réalisé trois validations sur cette branche.
274
+ Elle n'a pas encore récupéré les modifications de John, ce qui donne un historique semblable à la figure 5-7.
275
+
276
+ Insert 18333fig0507.png
277
+ Figure 5-7. L'historique initial des *commits* de Jessica.
278
+
279
+ Jessica souhaite se synchroniser sur le travail de John.
280
+ Elle récupère donc ses modifications :
281
+
282
+ # Ordinateur de Jessica
283
+ $ git fetch origin
284
+ ...
285
+ From jessica@githost:simplegit
286
+ fbff5bc..72bbc59 master -> origin/master
287
+
288
+ Cette commande tire le travail que John avait poussé dans l'intervalle.
289
+ L'historique de Jessica ressemble maintenant à la figure 5-8.
290
+
291
+ Insert 18333fig0508.png
292
+ Figure 5-8. L'historique de Jessica après avoir récupéré les modifications de John.
293
+
294
+ Jessica pense que sa branche thématique est prête mais elle souhaite savoir si elle doit fusionner son travail avant de pouvoir pousser.
295
+ Elle lance `git log` pour s'en assurer :
296
+
297
+ $ git log --no-merges origin/master ^issue54
298
+ commit 738ee872852dfaa9d6634e0dea7a324040193016
299
+ Author: John Smith <jsmith@example.com>
300
+ Date: Fri May 29 16:01:27 2009 -0700
301
+
302
+ Eliminer une valeur par defaut invalide
303
+
304
+ Maintenant, Jessica peut fusionner sa branche thématique dans sa branche `master`, fusionner le travail de John (`origin/master`)dans sa branche `master`, puis pousser le résultat sur le serveur.
305
+ Premièrement, elle rebascule sur sa branche `master` pour intégrer son travail :
306
+
307
+ $ git checkout master
308
+ Switched to branch "master"
309
+ Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
310
+
311
+ Elle peut fusionner soit `origin/master` soit `prob54` en premier — les deux sont en avance, mais l'ordre n'importe pas.
312
+ L'instantané final devrait être identique quel que soit l'ordre de fusion qu'elle choisit.
313
+ Seul l'historique sera légèrement différent.
314
+ Elle choisit de fusionner en premier `prob54` :
315
+
316
+ $ git merge prob54
317
+ Updating fbff5bc..4af4298
318
+ Fast forward
319
+ LISEZMOI | 1 +
320
+ lib/simplegit.rb | 6 +++++-
321
+ 2 files changed, 6 insertions(+), 1 deletions(-)
322
+
323
+ Aucun problème n'apparaît.
324
+ Comme vous pouvez le voir, c'est une simple avance rapide.
325
+ Maintenant, Jessica fusionne le travail de John (`origin/master`) :
326
+
327
+ $ git merge origin/master
328
+ Auto-merging lib/simplegit.rb
329
+ Merge made by recursive.
330
+ lib/simplegit.rb | 2 +-
331
+ 1 files changed, 1 insertions(+), 1 deletions(-)
332
+
333
+ Tout a fusionné proprement et l'historique de Jessica ressemble à la figure 5-9.
334
+
335
+ Insert 18333fig0509.png
336
+ Figure 5-9. L'historique de Jessica après avoir fusionné les modifications de John.
337
+
338
+ Maintenant `origin/master` est accessible depuis la branche `master` de Jessica, donc elle devrait être capable de pousser (en considérant que John n'a pas encore poussé dans l'intervalle) :
339
+
340
+ $ git push origin master
341
+ ...
342
+ To jessica@githost:simplegit.git
343
+ 72bbc59..8059c15 master -> master
344
+
345
+ Chaque développeur a validé quelques fois et fusionné les travaux de l'autre avec succès (voir figure 5-10).
346
+
347
+ Insert 18333fig0510.png
348
+ Figure 5-10. L'historique de Jessica après avoir poussé toutes ses modifications sur le serveur.
349
+
350
+ C'est un des schémas les plus simples.
351
+ Vous travaillez pendant quelque temps, généralement sur une branche thématique, et fusionnez dans votre branche `master` quand elle est prête à être intégrée.
352
+ Quand vous souhaitez partager votre travail, vous récupérez `origin/master` et la fusionnez si elle a changé, puis finalement vous poussez le résultat sur la branche `master` du serveur.
353
+ La séquence est illustrée par la figure 5-11.
354
+
355
+ Insert 18333fig0511.png
356
+ Figure 5-11. Séquence générale des évènements pour une utilisation simple multi-développeur de Git.
357
+
358
+ ### Équipe privée importante ###
359
+
360
+ Dans le scénario suivant, nous aborderons les rôles de contributeur dans un groupe privé plus grand.
361
+ Vous apprendrez comment travailler dans un environnement où des petits groupes collaborent sur des fonctionnalités, puis les contributions de chaque équipe sont intégrées par une autre entité.
362
+
363
+ Supposons que John et Jessica travaillent ensemble sur une première fonctionnalité, tandis que Jessica et Josie travaillent sur une autre.
364
+ Dans ce cas, l'entreprise utilise un mode d'opération de type « gestionnaire d'intégration » où le travail des groupes est intégré par certains ingénieurs, et la branche `master` du dépôt principal ne peut être mise à jour que par ces ingénieurs.
365
+ Dans ce scénario, tout le travail est validé dans des branches orientées équipe, et tiré plus tard par les intégrateurs.
366
+
367
+ Suivons le cheminement de Jessica tandis qu'elle travaille sur les deux nouvelles fonctionnalités, collaborant en parallèle avec deux développeurs différents dans cet environnement.
368
+ En supposant qu'elle ait cloné son dépôt, elle décide de travailler sur la `fonctionA` en premier.
369
+ Elle crée une nouvelle branche pour cette fonction et travaille un peu dessus :
370
+
371
+ # Ordinateur de Jessica
372
+ $ git checkout -b fonctionA
373
+ Switched to a new branch "fonctionA"
374
+ $ vim lib/simplegit.rb
375
+ $ git commit -am 'Ajouter une limite à la fonction de log'
376
+ [fonctionA 3300904] Ajouter une limite à la fonction de log
377
+ 1 files changed, 1 insertions(+), 1 deletions(-)
378
+
379
+ À ce moment, elle a besoin de partager son travail avec John, donc elle pousse les *commits* de sa branche `fonctionA` sur le serveur.
380
+ Jessica n'a pas le droit de pousser sur la branche `master` — seuls les intégrateurs l'ont — et elle doit donc pousser sur une autre branche pour collaborer avec John :
381
+
382
+ $ git push origin fonctionA
383
+ ...
384
+ To jessica@githost:simplegit.git
385
+ * [new branch] fonctionA -> fonctionA
386
+
387
+ Jessica envoie un e-mail à John pour lui indiquer qu'elle a poussé son travail dans la branche appelée `fonctionA` et qu'il peut l'inspecter.
388
+ Pendant qu'elle attend le retour de John, Jessica décide de commencer à travailler sur la `fonctionB` avec Josie.
389
+ Pour commencer, elle crée une nouvelle branche thématique, à partir de la base `master` du serveur :
390
+
391
+ # Ordinateur de Jessica
392
+ $ git fetch origin
393
+ $ git checkout -b fonctionB origin/master
394
+ Switched to a new branch "fonctionB"
395
+
396
+ À présent, Jessica réalise quelques validations sur la branche `fonctionB` :
397
+
398
+ $ vim lib/simplegit.rb
399
+ $ git commit -am 'Rendre la fonction ls-tree recursive'
400
+ [fonctionB e5b0fdc] Rendre la fonction ls-tree recursive
401
+ 1 files changed, 1 insertions(+), 1 deletions(-)
402
+ $ vim lib/simplegit.rb
403
+ $ git commit -am 'Ajout de ls-files'
404
+ [fonctionB 8512791] Ajout ls-files
405
+ 1 files changed, 5 insertions(+), 0 deletions(-)
406
+
407
+ Le dépôt de Jessica ressemble à la figure 5-12.
408
+
409
+ Insert 18333fig0512.png
410
+ Figure 5-12. L'historique initial de Jessica.
411
+
412
+ Elle est prête à pousser son travail, mais elle reçoit un mail de Josie indiquant qu'une branche avec un premier travail a déjà été poussé sur le serveur en tant que `fonctionBee`.
413
+ Jessica doit d'abord fusionner ces modifications avec les siennes avant de pouvoir pousser sur le serveur.
414
+ Elle peut récupérer les modifications de Josie avec `git fetch` :
415
+
416
+ $ git fetch origin
417
+ ...
418
+ From jessica@githost:simplegit
419
+ * [new branch] fonctionBee -> origin/fonctionBee
420
+
421
+ Jessica peut à présent fusionner ceci dans le travail qu'elle a réalisé grâce à `git merge` :
422
+
423
+ $ git merge origin/fonctionBee
424
+ Auto-merging lib/simplegit.rb
425
+ Merge made by recursive.
426
+ lib/simplegit.rb | 4 ++++
427
+ 1 files changed, 4 insertions(+), 0 deletions(-)
428
+
429
+ Mais il y a un petit problème — elle doit pousser son travail fusionné dans sa branche `fonctionB` sur la branche `fonctionBee` du serveur.
430
+ Elle peut le faire en spécifiant la branche locale suivie de deux points (:) suivi de la branche distante à la commande `git push` :
431
+
432
+ $ git push origin fonctionB:fonctionBee
433
+ ...
434
+ To jessica@githost:simplegit.git
435
+ fba9af8..cd685d1 fonctionB -> fonctionBee
436
+
437
+ Cela s'appelle une _refspec_. Référez-vous au chapitre 9 pour une explication plus détaillée des refspecs Git et des possibilités qu'elles offrent.
438
+
439
+ Ensuite, John envoie un e-mail à Jessica pour lui indiquer qu'il a poussé des modifications sur la branche `fonctionA` et lui demander de les vérifier.
440
+ Elle lance `git fetch` pour tirer toutes ces modifications :
441
+
442
+ $ git fetch origin
443
+ ...
444
+ From jessica@githost:simplegit
445
+ 3300904..aad881d fonctionA -> origin/fonctionA
446
+
447
+ Elle peut alors voir ce qui a été modifié avec `git log` :
448
+
449
+ $ git log origin/fonctionA ^fonctionA
450
+ commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6
451
+ Author: John Smith <jsmith@example.com>
452
+ Date: Fri May 29 19:57:33 2009 -0700
453
+
454
+ largeur du log passee de 25 a 30
455
+
456
+ Finalement, elle fusionne le travail de John dans sa propre branche `fonctionA` :
457
+
458
+ $ git checkout fonctionA
459
+ Switched to branch "fonctionA"
460
+ $ git merge origin/fonctionA
461
+ Updating 3300904..aad881d
462
+ Fast forward
463
+ lib/simplegit.rb | 10 +++++++++-
464
+ 1 files changed, 9 insertions(+), 1 deletions(-)
465
+
466
+ Jessica veut régler quelques détails.
467
+ Elle valide donc encore et pousse ses changements sur le serveur :
468
+
469
+ $ git commit -am 'details regles'
470
+ [fonctionA 774b3ed] details regles
471
+ 1 files changed, 1 insertions(+), 1 deletions(-)
472
+ $ git push origin fonctionA
473
+ ...
474
+ To jessica@githost:simplegit.git
475
+ 3300904..774b3ed fonctionA -> fonctionA
476
+
477
+ L'historique des *commits* de Jessica ressemble à présent à la figure 5-13.
478
+
479
+ Insert 18333fig0513.png
480
+ Figure 5-13. L'historique de Jessica après la validation dans la branche thématique.
481
+
482
+ Jessica, Josie et John informent les intégrateurs que les branches `fonctionA` et `fonctionB` du serveur sont prêtes pour une intégration dans la branche principale.
483
+ Après cette intégration, une synchronisation apportera les *commits* de fusion, ce qui donnera un historique comme celui de la figure 5-14.
484
+
485
+ Insert 18333fig0514.png
486
+ Figure 5-14. L'historique de Jessica après la fusion de ses deux branches thématiques.
487
+
488
+ De nombreuses équipes basculent vers Git du fait de cette capacité à gérer plusieurs équipes travaillant en parallèle, fusionnant plusieurs lignes de développement très tard dans le processus de livraison.
489
+ La capacité donnée à plusieurs sous-groupes d'équipes de collaborer au moyen de branches distantes sans nécessairement impacter le reste de l'équipe est un grand bénéfice apporté par Git.
490
+ La séquence de travail qui vous a été décrite ressemble à la figure 5-15.
491
+
492
+
493
+ Insert 18333fig0515.png
494
+ Figure 5-15. Une séquence simple de gestion orientée équipe.
495
+
496
+ ### Petit projet public ###
497
+
498
+ Contribuer à un projet public est assez différent.
499
+ Il faut présenter le travail au mainteneur d'une autre manière parce que vous n'avez pas la possibilité de mettre à jour directement des branches du projet.
500
+ Ce premier exemple décrit un mode de contribution via des serveurs Git qui proposent facilement la duplication de dépôt.
501
+ Les sites repo.or.cz ou GitHub proposent cette méthode, et de nombreux mainteneurs s'attendent à ce style de contribution.
502
+ Le chapitre suivant traite des projets qui préfèrent accepter les contributions sous forme de patch via e-mail.
503
+
504
+ Premièrement, vous souhaiterez probablement cloner le dépôt principal, créer une nouvelle branche thématique pour le patch ou la série de patchs que seront votre contribution, et commencer à travailler.
505
+ La séquence ressemble globalement à ceci :
506
+
507
+ $ git clone (url)
508
+ $ cd projet
509
+ $ git checkout -b fonctionA
510
+ $ (travail)
511
+ $ git commit
512
+ $ (travail)
513
+ $ git commit
514
+
515
+ Vous pouvez utiliser `rebase -i` pour réduire votre travail à une seule validation ou pour réarranger les modifications dans des *commits* qui rendront les patchs plus faciles à relire pour le mainteneur — référez-vous au chapitre 6 pour plus d'information sur comment rebaser de manière interactive.
516
+
517
+ Lorsque votre branche de travail est prête et que vous êtes prêt à la fournir au mainteneur, rendez-vous sur la page du projet et cliquez sur le bouton « Fork » pour créer votre propre projet dupliqué sur lequel vous aurez les droits en écriture.
518
+ Vous devez alors ajouter l'URL de ce nouveau dépôt en tant que second dépôt distant, dans notre cas nommé `macopie` :
519
+
520
+ $ git remote add macopie (url)
521
+
522
+ Vous devez pousser votre travail sur ce dépôt distant.
523
+ C'est beaucoup plus facile de pousser la branche sur laquelle vous travaillez sur une branche distante que de fusionner et de pousser le résultat sur le serveur.
524
+ La raison principale en est que si le travail n'est pas accepté ou s'il est picoré, vous n'aurez pas à faire marche arrière sur votre branche `master`.
525
+ Si le mainteneur fusionne, rebase ou picore votre travail, vous le saurez en tirant depuis son dépôt :
526
+
527
+ $ git push macopie fonctionA
528
+
529
+ Une fois votre travail poussé sur votre copie du dépôt, vous devez notifier le mainteneur.
530
+ Ce processus est souvent appelé une demande de tirage (*pull request*) et vous pouvez la générer soit via le site web — GitHub propose un bouton « pull request » qui envoie automatiquement un message au mainteneur — soit lancer la commande `git request-pull` et envoyer manuellement par e-mail le résultat au mainteneur de projet.
531
+
532
+ La commande `request-pull` prend en paramètres la branche de base dans laquelle vous souhaitez que votre branche thématique soit fusionnée et l'URL du dépôt Git depuis lequel vous souhaitez qu'elle soit tirée, et génère un résumé des modifications que vous demandez à faire tirer.
533
+ Par exemple, si Jessica envoie à John une demande de tirage et qu'elle a fait deux validations dans la branche thématique qu'elle vient de pousser, elle peut lancer ceci :
534
+
535
+ $ git request-pull origin/master macopie
536
+ The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40:
537
+ John Smith (1):
538
+ ajout d'une nouvelle fonction
539
+
540
+ are available in the git repository at:
541
+
542
+ git://githost/simplegit.git fonctionA
543
+
544
+ Jessica Smith (2):
545
+ Ajout d'une limite à la fonction de log
546
+ change la largeur du log de 25 a 30
547
+
548
+ lib/simplegit.rb | 10 +++++++++-
549
+ 1 files changed, 9 insertions(+), 1 deletions(-)
550
+
551
+ Le résultat peut être envoyé au mainteneur — cela lui indique d'où la modification a été branchée, le résumé des validations et d'où tirer ce travail.
552
+
553
+ Pour un projet dont vous n'êtes pas le mainteneur, il est généralement plus aisé de toujours laisser la branche `master` suivre `origin/master` et de réaliser vos travaux sur des branches thématiques que vous pourrez facilement effacer si elles sont rejetées.
554
+ Garder les thèmes de travaux isolés sur des branches thématiques facilite aussi leur rebasage si le sommet du dépôt principal a avancé dans l'intervalle et que vos modifications ne s'appliquent plus proprement.
555
+ Par exemple, si vous souhaitez soumettre un second sujet de travail au projet, ne continuez pas à travailler sur la branche thématique que vous venez de pousser mais démarrez en plutôt une depuis la branche `master` du dépôt principal :
556
+
557
+ $ git checkout -b fonctionB origin/master
558
+ $ (travail)
559
+ $ git commit
560
+ $ git push macopie fonctionB
561
+ $ (email au mainteneur)
562
+ $ git fetch origin
563
+
564
+ À présent, chaque sujet est contenu dans son propre silo — similaire à une file de patchs — que vous pouvez réécrire, rebaser et modifier sans que les sujets n'interfèrent ou ne dépendent les uns des autres, comme sur la figure 5-16.
565
+
566
+ Insert 18333fig0516.png
567
+ Figure 5-16. Historique initial des *commits* avec les modifications de fonctionB.
568
+
569
+ Supposons que le mainteneur du projet a tiré une poignée d'autres patchs et essayé par la suite votre première branche, mais celle-ci ne s'applique plus proprement.
570
+ Dans ce cas, vous pouvez rebaser cette branche au sommet de `origin/master`, résoudre les conflits pour le mainteneur et soumettre de nouveau vos modifications :
571
+
572
+ $ git checkout fonctionA
573
+ $ git rebase origin/master
574
+ $ git push –f macopie fonctionA
575
+
576
+ Cette action réécrit votre historique pour qu'il ressemble à la figure 5-17.
577
+
578
+ Insert 18333fig0517.png
579
+ Figure 5-17. Historique des validations après le travail sur fonctionA.
580
+
581
+ Comme vous avez rebasé votre branche, vous devez spécifier l'option `-f` à votre commande pour pousser, pour forcer le remplacement de la branche `fonctionA` sur le serveur par la suite de *commits* qui n'en est pas descendante.
582
+ Une solution alternative serait de pousser ce nouveau travail dans une branche différente du serveur (appelée par exemple `fonctionAv2`).
583
+
584
+ Examinons un autre scénario possible : le mainteneur a revu les modifications dans votre seconde branche et apprécie le concept, mais il souhaiterait que vous changiez des détails d'implémentation.
585
+ Vous en profiterez pour rebaser ce travail sur le sommet actuel de la branche `master` du projet.
586
+ Vous démarrez une nouvelle branche à partir de la branche `origin/master` courante, y collez les modifications de `fonctionB` en résolvant les conflits, changez l'implémentation et poussez le tout en tant que nouvelle branche :
587
+
588
+ $ git checkout -b fonctionBv2 origin/master
589
+ $ git merge --no-commit --squash fonctionB
590
+ $ (changement d'implémentation)
591
+ $ git commit
592
+ $ git push macopie fonctionBv2
593
+
594
+ L'option `--squash` prend tout le travail de la branche à fusionner et le colle dans un *commit* sans fusion au sommet de la branche extraite.
595
+ L'option `--no-commit` indique à Git de ne pas enregistrer automatiquement une validation.
596
+ Cela permet de reporter toutes les modifications d'une autre branche, puis de réaliser d'autres modifications avant de réaliser une nouvelle validation.
597
+
598
+ À présent, vous pouvez envoyer au mainteneur un message indiquant que vous avez réalisé les modifications demandées et qu'il peut trouver cette nouvelle mouture sur votre branche `fonctionBv2` (voir figure 5-18).
599
+
600
+
601
+ Insert 18333fig0518.png
602
+ Figure 5-18. Historique des validations après le travail sur fonctionBv2.
603
+
604
+ ### Grand projet public ###
605
+
606
+ De nombreux grands projets ont des procédures établies pour accepter des patchs — il faut vérifier les règles spécifiques à chaque projet qui peuvent varier.
607
+ Néanmoins, ils sont nombreux à accepter les patchs via une liste de diffusion de développement, ce que nous allons éclairer d'un exemple.
608
+
609
+ La méthode est similaire au cas précédent — vous créez une branche thématique par série de patchs sur laquelle vous travaillez.
610
+ La différence réside dans la manière de les soumettre au projet.
611
+ Au lieu de dupliquer le projet et de pousser vos soumissions sur votre dépôt, il faut générer des versions e-mail de chaque série de *commits* et les envoyer à la liste de diffusion de développement.
612
+
613
+ $ git checkout -b sujetA
614
+ $ (travail)
615
+ $ git commit
616
+ $ (travail)
617
+ $ git commit
618
+
619
+ Vous avez à présent deux *commits* que vous souhaitez envoyer à la liste de diffusion.
620
+ Vous utilisez `git format-patch` pour générer des fichiers au format mbox que vous pourrez envoyer à la liste.
621
+ Cette commande transforme chaque *commit* en un message e-mail dont le sujet est la première ligne du message de validation et le corps contient le reste du message plus le patch correspondant.
622
+ Un point intéressant de cette commande est qu'appliquer le patch à partir d'un e-mail formaté avec `format-patch` préserve toute l'information de validation comme nous le verrons dans le chapitre suivant lorsqu'il s'agira de l'appliquer.
623
+
624
+ $ git format-patch -M origin/master
625
+ 0001-Ajout-d-une-limite-la-fonction-de-log.patch
626
+ 0002-change-la-largeur-du-log-de-25-a-30.patch
627
+
628
+ La commande `format-patch` affiche les noms de fichiers de patch créés.
629
+ L'option `-M` indique à Git de suivre les renommages.
630
+ Le contenu des fichiers ressemble à ceci :
631
+
632
+ $ cat 0001-Ajout-d-une-limite-la-fonction-de-log.patch
633
+ From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
634
+ From: Jessica Smith <jessica@example.com>
635
+ Date: Sun, 6 Apr 2008 10:17:23 -0700
636
+ Subject: [PATCH 1/2] Ajout d'une limite à la fonction de log
637
+
638
+ Limite la fonctionnalité de log aux 20 premières lignes
639
+
640
+ ---
641
+ lib/simplegit.rb | 2 +-
642
+ 1 files changed, 1 insertions(+), 1 deletions(-)
643
+
644
+ diff --git a/lib/simplegit.rb b/lib/simplegit.rb
645
+ index 76f47bc..f9815f1 100644
646
+ --- a/lib/simplegit.rb
647
+ +++ b/lib/simplegit.rb
648
+ @@ -14,7 +14,7 @@ class SimpleGit
649
+ end
650
+
651
+ def log(treeish = 'master')
652
+ - command("git log #{treeish}")
653
+ + command("git log -n 20 #{treeish}")
654
+ end
655
+
656
+ def ls_tree(treeish = 'master')
657
+ --
658
+ 1.6.2.rc1.20.g8c5b.dirty
659
+
660
+ Vous pouvez maintenant éditer ces fichiers de patch pour ajouter plus d'informations à destination de la liste de diffusion mais que vous ne souhaitez pas voir apparaître dans le message de validation.
661
+ Si vous ajoutez du texte entre la ligne `---` et le début du patch (la ligne `lib/simplegit.rb`), les développeurs peuvent le lire mais l'application du patch ne le prend pas en compte.
662
+
663
+ Pour envoyer par e-mail ces fichiers, vous pouvez soit copier leur contenu dans votre application d'e-mail, soit l'envoyer via une ligne de commande.
664
+ Le copier-coller cause souvent des problèmes de formatage, spécialement avec les applications « intelligentes » qui ne préservent pas les retours à la ligne et les types d'espace.
665
+ Heureusement, Git fournit un outil pour envoyer correctement les patchs formatés via IMAP, la méthode la plus facile.
666
+ Je démontrerai comment envoyer un patch via Gmail qui s'avère être la boîte mail que j'utilise ; vous pourrez trouver des instructions détaillées pour de nombreuses applications de mail à la fin du fichier susmentionné `Documentation/SubmittingPatches` du code source de Git.
667
+
668
+ Premièrement, il est nécessaire de paramétrer la section `imap` de votre fichier `~/.gitconfig`.
669
+ Vous pouvez positionner ces valeurs séparément avec une série de commandes `git config`, ou vous pouvez les ajouter manuellement.
670
+ À la fin, le fichier de configuration doit ressembler à ceci :
671
+
672
+ [imap]
673
+ folder = "[Gmail]/Drafts"
674
+ host = imaps://imap.gmail.com
675
+ user = user@gmail.com
676
+ pass = p4ssw0rd
677
+ port = 993
678
+ sslverify = false
679
+
680
+ Si votre serveur IMAP n'utilise pas SSL, les deux dernières lignes ne sont probablement pas nécessaires et le paramètre `host` commencera par `imap://` au lieu de `imaps://`.
681
+ Quand c'est fait, vous pouvez utiliser la commande `git imap-send` pour placer la série de patchs dans le répertoire *Drafts* du serveur IMAP spécifié :
682
+
683
+ $ cat *.patch |git imap-send
684
+ Resolving imap.gmail.com... ok
685
+ Connecting to [74.125.142.109]:993... ok
686
+ Logging in...
687
+ sending 2 messages
688
+ 100% (2/2) done
689
+
690
+ À présent, vous devriez pouvoir vous rendre dans le répertoire *Drafts*, changer le champ destinataire pour celui de la liste de diffusion, y ajouter optionnellement en copie le mainteneur du projet ou le responsable et l'envoyer.
691
+
692
+ Une autre méthode consiste à envoyer vos patchs par un serveur SMTP.
693
+ Comme précédemment, vous pouvez régler chaque paramètre séparément avec une série de commandes `git config` ou vous pouvez les ajouter directement dans la section `sendemail` de votre fichier `~/.gitconfig` :
694
+
695
+ [sendemail]
696
+ smtpencryption = tls
697
+ smtpserver = smtp.gmail.com
698
+ smtpuser = user@gmail.com
699
+ smtpserverport = 587
700
+
701
+ Après ceci, vous pouvez utiliser la commande `git send-email` pour envoyer vos patchs :
702
+
703
+ $ git send-email *.patch
704
+ 0001-added-limit-to-log-function.patch
705
+ 0002-changed-log-output-to-30-from-25.patch
706
+ Who should the emails appear to be from? [Jessica Smith <jessica@example.com>]
707
+ Emails will be sent from: Jessica Smith <jessica@example.com>
708
+ Who should the emails be sent to? jessica@example.com
709
+ Message-ID to be used as In-Reply-To for the first email? y
710
+
711
+ La première question demande l'adresse e-mail d'origine (avec par défaut celle saisie en config), tandis que la seconde demande les destinataires.
712
+ Enfin la dernière question sert à indiquer que l'on souhaite poster la série de patchs comme une réponse au premier patch de la série, créant ainsi un fil de discussion unique pour cette série.
713
+ Ensuite, Git crache un certain nombre d'informations qui ressemblent à ceci pour chaque patch à envoyer :
714
+
715
+ (mbox) Adding cc: Jessica Smith <jessica@example.com> from
716
+ \line 'From: Jessica Smith <jessica@example.com>'
717
+ OK. Log says:
718
+ Sendmail: /usr/sbin/sendmail -i jessica@example.com
719
+ From: Jessica Smith <jessica@example.com>
720
+ To: jessica@example.com
721
+ Subject: [PATCH 1/2] Ajout d'une limite à la-fonction de log
722
+ Date: Sat, 30 May 2009 13:29:15 -0700
723
+ Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com>
724
+ X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty
725
+ In-Reply-To: <y>
726
+ References: <y>
727
+
728
+ Result: OK
729
+
730
+ ### Résumé ###
731
+
732
+ Ce chapitre a traité quelques-unes des méthodes communes de gestion de types différents de projets Git que vous pourrez rencontrer et a introduit un certain nombre de nouveaux outils pour vous aider à gérer ces processus.
733
+ Dans la section suivante, nous allons voir comment travailler de l'autre côté de la barrière : en tant que mainteneur de projet Git.
734
+ Vous apprendrez comment travailler comme dictateur bienveillant ou gestionnaire d'intégration.
735
+
736
+ ## Maintenance d'un projet ##
737
+
738
+ En plus de savoir comment contribuer efficacement à un projet, vous aurez probablement besoin de savoir comment en maintenir un.
739
+ Cela peut consister à accepter et appliquer les patchs générés via `format-patch` et envoyés par e-mail, ou à intégrer des modifications dans des branches distantes de dépôts distants.
740
+ Que vous mainteniez le dépôt de référence ou que vous souhaitiez aider en vérifiant et approuvant les patchs, vous devez savoir comment accepter les contributions d'une manière limpide pour vos contributeurs et soutenable à long terme pour vous.
741
+
742
+ ### Travail dans des branches thématiques ###
743
+
744
+ Quand vous vous apprêtez à intégrer des contributions, une bonne idée consiste à les essayer d'abord dans une branche thématique, une branche temporaire spécifiquement créée pour essayer cette nouveauté.
745
+ De cette manière, il est plus facile de rectifier un patch à part et de le laisser s'il ne fonctionne pas jusqu'à ce que vous disposiez de temps pour y travailler.
746
+ Si vous créez une simple branche nommée d'après le thème de la modification que vous allez essayer, telle que `ruby_client` ou quelque chose d'aussi descriptif, vous pouvez vous en souvenir simplement plus tard.
747
+ Le mainteneur du projet Git a l'habitude d'utiliser des espaces de nommage pour ses branches, tels que `sc/ruby_client`, où `sc` représente les initiales de la personne qui a contribué les modifications.
748
+ Comme vous devez vous en souvenir, on crée une branche à part du master de la manière suivante :
749
+
750
+ $ git branch sc/ruby_client master
751
+
752
+ Ou bien, si vous voulez aussi basculer immédiatement dessus, vous pouvez utiliser l'option `checkout -b` :
753
+
754
+ $ git checkout -b sc/ruby_client master
755
+
756
+ Vous voilà maintenant prêt à ajouter les modifications sur cette branche thématique et à déterminer si c'est prêt à être fusionné dans les branches au long cours.
757
+
758
+ ### Application des patchs à partir d'e-mail ###
759
+
760
+ Si vous recevez par e-mail un patch que vous devez intégrer à votre projet, vous avez besoin d'appliquer le patch dans une branche thématique pour l'évaluer.
761
+ Il existe deux méthodes pour appliquer un patch envoyé par e-mail : `git apply` et `git am`.
762
+
763
+ #### Application d'un patch avec `apply` ####
764
+
765
+ Si vous avez reçu le patch de quelqu'un qui l'a généré avec la commande `git diff` ou `diff` Unix, vous pouvez l'appliquer avec la commande `git apply`.
766
+ Si le patch a été sauvé comme fichier `/tmp/patch-ruby-client.patch`, vous pouvez l'appliquer comme ceci :
767
+
768
+ $ git apply /tmp/patch-ruby-client.patch
769
+
770
+ Les fichiers dans votre copie de travail sont modifiés.
771
+ C'est quasiment identique à la commande `patch -p1` qui applique directement les patchs mais en plus paranoïaque et moins tolérant sur les concordances approximatives.
772
+ Les ajouts, effacements et renommages de fichiers sont aussi gérés s'ils sont décrits dans le format `git diff`, ce que `patch` ne supporte pas.
773
+ Enfin, `git apply` fonctionne en mode « applique tout ou refuse tout » dans lequel toutes les modifications proposées sont appliquées si elles le peuvent, sinon rien n'est modifié, là où `patch` peut n'appliquer que partiellement les patchs, laissant le répertoire de travail dans un état intermédiaire.
774
+ `git apply` est par dessus tout plus paranoïaque que `patch`.
775
+ Il ne créera pas une validation à votre place : après l'avoir lancé, vous devrez indexer et valider les modifications manuellement.
776
+
777
+ Vous pouvez aussi utiliser `git apply` pour voir si un patch s'applique proprement avant de réellement l'appliquer — vous pouvez lancer `git apply --check` avec le patch :
778
+
779
+ $ git apply --check 0001-seeing-if-this-helps-the-gem.patch
780
+ error: patch failed: ticgit.gemspec:1
781
+ error: ticgit.gemspec: patch does not apply
782
+
783
+ S'il n'y pas de message, le patch devrait s'appliquer proprement.
784
+ Cette commande se termine avec un statut non-nul si la vérification échoue et vous pouvez donc l'utiliser dans des scripts.
785
+
786
+ #### Application d'un patch avec `am` ####
787
+
788
+ Si le contributeur est un utilisateur de Git qui a été assez gentil d'utiliser la commande `format-patch` pour générer ses patchs, votre travail sera facilité car le patch contient alors déjà l'information d'auteur et le message de validation.
789
+ Si possible, encouragez vos contributeurs à utiliser `format-patch` au lieu de `patch` pour générer les patchs qu'ils vous adressent.
790
+ Vous ne devriez avoir à n'utiliser `git apply` que pour les vrais patchs.
791
+
792
+ Pour appliquer un patch généré par `format-patch`, vous utilisez `git am`.
793
+ Techniquement, `git am` s'attend à lire un fichier au format mbox, qui est un format texte simple permettant de stocker un ou plusieurs messages e-mail dans un unique fichier texte.
794
+ Un fichier ressemble à ceci :
795
+
796
+ From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
797
+ From: Jessica Smith <jessica@example.com>
798
+ Date: Sun, 6 Apr 2008 10:17:23 -0700
799
+ Subject: [PATCH 1/2] Ajout d'une limite à la fonction de log
800
+
801
+ Limite la fonctionnalité de log aux 20 premières lignes
802
+
803
+ C'est le début de ce que la commande `format-patch` affiche, comme vous avez vu dans la section précédente.
804
+ C'est aussi un format e-mail mbox parfaitement valide.
805
+ Si quelqu'un vous a envoyé par e-mail un patch correctement formaté en utilisant `git send-mail` et que vous le téléchargez en format mbox, vous pouvez pointer `git am` sur ce fichier mbox et il commencera à appliquer tous les patchs contenus.
806
+ Si vous utilisez un client e-mail qui sait sauver plusieurs messages au format mbox, vous pouvez sauver la totalité de la série de patchs dans un fichier et utiliser `git am` pour les appliquer tous en une fois.
807
+
808
+ Néanmoins, si quelqu'un a déposé un fichier de patch généré via `format-patch` sur un système de suivi de faits techniques ou quelque chose de similaire, vous pouvez toujours sauvegarder le fichier localement et le passer à `git am` pour l'appliquer :
809
+
810
+ $ git am 0001-limite-la-fonction-de-log.patch
811
+ Applying: Ajout d'une limite à la fonction de log
812
+
813
+ Vous remarquez qu'il s'est appliqué proprement et a créé une nouvelle validation pour vous.
814
+ L'information d'auteur est extraite des en-têtes `From` et `Date` tandis que le message de validation est repris du champ `Subject` et du corps (avant le patch) du message.
815
+ Par exemple, si le patch est appliqué depuis le fichier mbox ci-dessus, la validation générée ressemblerait à ceci :
816
+
817
+ $ git log --pretty=fuller -1
818
+ commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
819
+ Author: Jessica Smith <jessica@example.com>
820
+ AuthorDate: Sun Apr 6 10:17:23 2008 -0700
821
+ Commit: Scott Chacon <schacon@gmail.com>
822
+ CommitDate: Thu Apr 9 09:19:06 2009 -0700
823
+
824
+ Ajout d'une limite à la fonction de log
825
+
826
+ Limite la fonctionnalité de log aux 20 premières lignes
827
+
828
+ L'information `Commit` indique la personne qui a appliqué le patch et la date d'application.
829
+ L'information `Author` indique la personne qui a créé le patch et la date de création.
830
+
831
+ Il reste la possibilité que le patch ne s'applique pas proprement.
832
+ Peut-être votre branche principale a déjà trop divergé de la branche sur laquelle le patch a été construit, ou le patch dépend d'un autre patch qui n'a pas encore été appliqué.
833
+ Dans ce cas, le processus de `git am` échouera et vous demandera ce que vous souhaitez faire :
834
+
835
+ $ git am 0001-seeing-if-this-helps-the-gem.patch
836
+ Applying: seeing if this helps the gem
837
+ error: patch failed: ticgit.gemspec:1
838
+ error: ticgit.gemspec: patch does not apply
839
+ Patch failed at 0001.
840
+ When you have resolved this problem run "git am --resolved".
841
+ If you would prefer to skip this patch, instead run "git am --skip".
842
+ To restore the original branch and stop patching run "git am --abort".
843
+
844
+ Cette commande introduit des marqueurs de conflit dans tous les fichiers qui ont généré un problème, de la même manière qu'un conflit de fusion ou de rebasage.
845
+ Vous pouvez résoudre les problèmes de manière identique — éditez le fichier pour résoudre les conflits, indexez le nouveau fichier, puis lancez `git am --resolved` pour continuer avec le patch suivant :
846
+
847
+ $ (correction du fichier)
848
+ $ git add ticgit.gemspec
849
+ $ git am --resolved
850
+ Applying: seeing if this helps the gem
851
+
852
+ Si vous souhaitez que Git essaie de résoudre les conflits avec plus d'intelligence, vous pouvez passer l'option `-3` qui demande à Git de tenter une fusion à trois sources.
853
+ Cette option n'est pas active par défaut parce qu'elle ne fonctionne pas si le *commit* sur lequel le patch indique être basé n'existe pas dans votre dépôt.
854
+ Si par contre, le patch est basé sur un *commit* public, l'option `-3` est généralement beaucoup plus fine pour appliquer des patchs conflictuels :
855
+
856
+ $ git am -3 0001-seeing-if-this-helps-the-gem.patch
857
+ Applying: seeing if this helps the gem
858
+ error: patch failed: ticgit.gemspec:1
859
+ error: ticgit.gemspec: patch does not apply
860
+ Using index info to reconstruct a base tree...
861
+ Falling back to patching base and 3-way merge...
862
+ No changes -- Patch already applied.
863
+
864
+ Dans ce cas, je cherchais à appliquer un patch qui avait déjà été intégré.
865
+ Sans l'option `-3`, cela aurait ressemblé à un conflit.
866
+
867
+ Si vous appliquez des patchs à partir d'un fichier mbox, vous pouvez aussi lancer la commande `am` en mode interactif qui s'arrête à chaque patch trouvé et vous demande si vous souhaitez l'appliquer :
868
+
869
+ $ git am -3 -i mbox
870
+ Commit Body is:
871
+ --------------------------
872
+ seeing if this helps the gem
873
+ --------------------------
874
+ Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all
875
+
876
+ C'est agréable si vous avez un certain nombre de patchs sauvegardés parce que vous pouvez voir les patchs pour vous rafraîchir la mémoire et ne pas les appliquer s'ils ont déjà été intégrés.
877
+
878
+ Quand tous les patchs pour votre sujet ont été appliqués et validés dans votre branche, vous pouvez choisir si et comment vous souhaitez les intégrer dans une branche au long cours.
879
+
880
+ ### Vérification des branches distantes ###
881
+
882
+ Si votre contribution a été fournie par un utilisateur de Git qui a mis en place son propre dépôt public sur lequel il a poussé ses modifications et vous a envoyé l'URL du dépôt et le nom de la branche distante, vous pouvez les ajouter en tant que dépôt distant et réaliser les fusions localement.
883
+
884
+ Par exemple, si Jessica vous envoie un e-mail indiquant qu'elle a une nouvelle fonctionnalité géniale dans la branche `ruby-client` de son dépôt, vous pouvez la tester en ajoutant le dépôt distant et en tirant la branche localement :
885
+
886
+ $ git remote add jessica git://github.com/jessica/monprojet.git
887
+ $ git fetch jessica
888
+ $ git checkout -b rubyclient jessica/ruby-client
889
+
890
+ Si elle vous envoie un autre mail indiquant une autre branche contenant une autre fonctionnalité géniale, vous pouvez la récupérer et la tester simplement à partir de votre référence distante.
891
+
892
+ C'est d'autant plus utile si vous travaillez en continu avec une personne.
893
+ Si quelqu'un n'a qu'un seul patch à contribuer de temps en temps, l'accepter via e-mail peut s'avérer moins consommateur en temps de préparation du serveur public, d'ajout et retrait de branches distantes juste pour tirer quelques patchs.
894
+ Vous ne souhaiteriez sûrement pas devoir gérer des centaines de dépôts distants pour intégrer à chaque fois un ou deux patchs.
895
+ Néanmoins, des scripts et des services hébergés peuvent rendre cette tâche moins ardue.
896
+ Cela dépend largement de votre manière de développer et de celle de vos contributeurs.
897
+
898
+ Cette approche a aussi l'avantage de vous fournir l'historique des validations.
899
+ Même si vous pouvez rencontrer des problèmes de fusion légitimes, vous avez l'information dans votre historique de la base ayant servi pour les modifications contribuées.
900
+ La fusion à trois sources est choisie par défaut plutôt que d'avoir à spécifier l'option `-3` en espérant que le patch a été généré à partir d'un instantané public auquel vous auriez accès.
901
+
902
+ Si vous ne travaillez pas en continu avec une personne mais souhaitez tout de même tirer les modifications de cette manière, vous pouvez fournir l'URL du dépôt distant à la commande `git pull`.
903
+ Cela permet de réaliser un tirage unique sans sauver l'URL comme référence distante :
904
+
905
+ $ git pull git://github.com/typeunique/projet.git
906
+ From git://github.com/typeunique/projet
907
+ * branch HEAD -> FETCH_HEAD
908
+ Merge made by recursive.
909
+
910
+ ### Déterminer les modifications introduites ###
911
+
912
+ Vous avez maintenant une branche thématique qui contient les contributions.
913
+ De ce point, vous pouvez déterminer ce que vous souhaitez en faire.
914
+ Cette section revisite quelques commandes qui vont vous permettre de faire une revue de ce que vous allez exactement introduire si vous fusionnez dans la branche principale.
915
+
916
+ Faire une revue de tous les *commits* dans cette branche s'avère souvent d'une grande aide.
917
+ Vous pouvez exclure les *commits* de la branche `master` en ajoutant l'option `--not` devant le nom de la branche.
918
+ Par exemple, si votre contributeur vous envoie deux patchs et que vous créez une branche appelée `contrib` et y appliquez ces patchs, vous pouvez lancer ceci :
919
+
920
+ $ git log contrib --not master
921
+ commit 5b6235bd297351589efc4d73316f0a68d484f118
922
+ Author: Scott Chacon <schacon@gmail.com>
923
+ Date: Fri Oct 24 09:53:59 2008 -0700
924
+
925
+ seeing if this helps the gem
926
+
927
+ commit 7482e0d16d04bea79d0dba8988cc78df655f16a0
928
+ Author: Scott Chacon <schacon@gmail.com>
929
+ Date: Mon Oct 22 19:38:36 2008 -0700
930
+
931
+ updated the gemspec to hopefully work better
932
+
933
+ Pour visualiser les modifications que chaque *commit* introduit, souvenez-vous que vous pouvez passer l'option `-p` à `git log` et elle ajoutera le diff introduit à chaque *commit*.
934
+
935
+ Pour visualiser un diff complet de ce qui arriverait si vous fusionniez cette branche thématique avec une autre branche, vous pouvez utiliser un truc bizarre pour obtenir les résultats corrects.
936
+ Vous pourriez penser à lancer ceci :
937
+
938
+ $ git diff master
939
+
940
+ Cette commande affiche un diff mais elle peut être trompeuse.
941
+ Si votre branche `master` a avancé depuis que vous en avez créé la branche thématique, vous obtiendrez des résultats apparemment étranges.
942
+ Cela arrive parce que Git compare directement l'instantané de la dernière validation sur la branche thématique et celui de la dernière validation sur la branche `master`.
943
+ Par exemple, si vous avez ajouté une ligne dans un fichier sur la branche `master`, une comparaison directe donnera l'impression que la branche thématique va retirer cette ligne.
944
+
945
+ Si `master` est un ancêtre directe de la branche thématique, ce n'est pas un problème.
946
+ Si les deux historiques ont divergé, le diff donnera l'impression que vous ajoutez toutes les nouveautés de la branche thématique et retirez tout ce qui a été fait depuis dans la branche `master`.
947
+
948
+ Ce que vous souhaitez voir en fait, ce sont les modifications ajoutées sur la branche thématique — le travail que vous introduirez si vous fusionnez cette branche dans `master`.
949
+ Vous obtenez ce résultat en demandant à Git de comparer le dernier instantané de la branche thématique avec son ancêtre commun à la branche `master` le plus récent.
950
+
951
+ Techniquement, c'est réalisable en déterminant exactement l'ancêtre commun et en lançant la commande `diff` dessus :
952
+
953
+ $ git merge-base contrib master
954
+ 36c7dba2c95e6bbb78dfa822519ecfec6e1ca649
955
+ $ git diff 36c7db
956
+
957
+ Néanmoins, comme ce n'est pas très commode, Git fournit un raccourci pour réaliser la même chose : la syntaxe à trois points.
958
+ Dans le contexte de la commande `diff`, vous pouvez placer trois points après une autre branche pour réaliser un `diff` entre le dernier instantané de la branche sur laquelle vous vous trouvez et son ancêtre commun avec une autre branche :
959
+
960
+ $ git diff master...contrib
961
+
962
+ Cette commande ne vous montre que les modifications que votre branche thématique a introduites depuis son ancêtre commun avec master.
963
+ C'est une syntaxe très simple à retenir.
964
+
965
+ ### Intégration des contributions ###
966
+
967
+ Lorsque tout le travail de votre branche thématique est prêt à être intégré dans la branche principale, il reste à savoir comment le faire.
968
+ De plus, il faut connaître le mode de gestion que vous souhaitez pour votre projet.
969
+ Vous avez de nombreux choix et je vais en traiter quelques-uns.
970
+
971
+ #### Modes de fusion ####
972
+
973
+ Un mode simple fusionne votre travail dans la branche `master`.
974
+ Dans ce scénario, vous avez une branche `master` qui contient le code stable.
975
+ Quand vous avez des modifications prêtes dans une branche thématique, vous la fusionnez dans votre branche `master` puis effacez la branche thématique, et ainsi de suite.
976
+ Si vous avez un dépôt contenant deux branches nommées `ruby_client` et `php_client` qui ressemble à la figure 5-19 et que vous fusionnez `ruby_client` en premier, suivi de `php_client`, alors votre historique ressemblera à la fin à la figure 5-20.
977
+
978
+ Insert 18333fig0519.png
979
+ Figure 5-19. Historique avec quelques branches thématiques.
980
+
981
+ Insert 18333fig0520.png
982
+ Figure 5-20. Après fusion d'une branche thématique.
983
+
984
+ C'est probablement le mode le plus simple mais cela peut s'avérer problématique si vous avez à gérer des dépôts ou des projets plus gros.
985
+
986
+ Si vous avez plus de développeurs ou un projet plus important, vous souhaiterez probablement utiliser un cycle de fusion à au moins deux étapes.
987
+ Dans ce scénario, vous avez deux branches au long cours, `master` et `develop`, dans lequel vous déterminez que `master` est mis à jour seulement lors d'une version vraiment stable et tout le nouveau code est intégré dans la branche `develop`.
988
+ Vous poussez régulièrement ces deux branches sur le dépôt public.
989
+ Chaque fois que vous avez une nouvelle branche thématique à fusionner (figure 5-21), vous la fusionnez dans `develop` (figure 5-22).
990
+ Puis, lorsque vous étiquetez une version majeure, vous mettez `master` à niveau avec l'état stable de `develop` en avance rapide (figure 5-23).
991
+
992
+ Insert 18333fig0521.png
993
+ Figure 5-21. Avant la fusion d'une branche thématique.
994
+
995
+ Insert 18333fig0522.png
996
+ Figure 5-22. Après la fusion d'une branche thématique.
997
+
998
+ Insert 18333fig0523.png
999
+ Figure 5-23. Après une publication d'une branche thématique.
1000
+
1001
+ Ainsi, lorsque l'on clone le dépôt de votre projet, on peut soit extraire la branche `master` pour construire la dernière version stable et mettre à jour facilement ou on peut extraire la branche `develop` qui représente le nec plus ultra du développement.
1002
+
1003
+ Vous pouvez aussi continuer ce concept avec une branche d'intégration où tout le travail est fusionné.
1004
+ Alors, quand la base de code sur cette branche est stable et que les tests passent, vous la fusionnez dans la branche `develop`.
1005
+ Quand cela s'est avéré stable pendant un certain temps, vous mettez à jour la branche `master` en avance rapide.
1006
+
1007
+ #### Gestions avec nombreuses fusions ####
1008
+
1009
+ Le projet Git dispose de quatre branches au long cours : `master`, `next`, `pu` (*proposed updates* : propositions) pour les nouveaux travaux et `maint` pour les backports de maintenance.
1010
+ Quand une nouvelle contribution est proposée, elle est collectée dans des branches thématiques dans le dépôt du mainteneur d'une manière similaire à ce que j'ai décrit (voir figure 5-24).
1011
+ À ce point, les fonctionnalités sont évaluées pour déterminer si elles sont stables et prêtes à être consommées ou si elles nécessitent un peaufinage.
1012
+ Si elles sont stables, elles sont fusionnées dans `next` et cette branche est poussée sur le serveur public pour que tout le monde puisse essayer les fonctionnalités intégrées ensemble.
1013
+
1014
+ Insert 18333fig0524.png
1015
+ Figure 5-24. Série complexe de branches thématiques contribuées en parallèle.
1016
+
1017
+ Si les fonctionnalités nécessitent encore du travail, elles sont fusionnées plutôt dans `pu`.
1018
+ Quand elles sont considérées comme totalement stables, elles sont re-fusionnées dans `master` et sont alors reconstruites à partir des fonctionnalités qui résidaient dans `next` mais n'ont pu intégrer `master`.
1019
+ Cela signifie que `master` évolue quasiment toujours en mode avance rapide, tandis que `next` est rebasé assez souvent et `pu` est rebasé encore plus souvent (voir figure 5-25).
1020
+
1021
+ Insert 18333fig0525.png
1022
+ Figure 5-25. Fusion des branches thématiques dans les branches à long terme.
1023
+
1024
+ Quand une branche thématique a finalement été fusionnée dans `master`, elle est effacée du dépôt.
1025
+ Le projet Git a aussi une branche `maint` qui est créée à partir de la dernière version pour fournir des patchs correctifs en cas de besoin de version de maintenance.
1026
+ Ainsi, quand vous clonez le dépôt de Git, vous avez quatre branches disponibles pour évaluer le projet à différentes étapes de développement, selon le niveau de développement que vous souhaitez utiliser ou pour lequel vous souhaitez contribuer.
1027
+ Le mainteneur a une gestion structurée qui lui permet d'évaluer et sélectionner les nouvelles contributions.
1028
+
1029
+ #### Gestion par rebasage et sélection de *commit* ####
1030
+
1031
+ D'autres mainteneurs préfèrent rebaser ou sélectionner les contributions sur le sommet de la branche `master`, plutôt que les fusionner, de manière à conserver un historique à peu près linéaire.
1032
+ Lorsque plusieurs modifications sont présentes dans une branche thématique et que vous souhaitez les intégrer, vous vous placez sur cette branche et vous lancer la commande `rebase` pour reconstruire les modifications à partir du sommet courant de la branche `master` (ou `develop`, ou autre).
1033
+ Si cela fonctionne correctement, vous pouvez faire une avance rapide sur votre branche `master` et vous obtenez au final un historique de projet linéaire.
1034
+
1035
+ L'autre moyen de déplacer des modifications introduites dans une branche vers une autre consiste à les sélectionner (`cherry-pick`).
1036
+ Une sélection dans Git ressemble à un rebasage appliqué à un *commit* unique.
1037
+ Cela consiste à prendre le patch qui a été introduit lors d'une validation et à essayer de l'appliquer sur la branche sur laquelle on se trouve.
1038
+ C'est très utile si on a un certain nombre de *commits* sur une branche thématique et que l'on veut n'en intégrer qu'un seul, ou si on n'a qu'un *commit* sur une branche thématique et qu'on préfère le sélectionner plutôt que de lancer `rebase`.
1039
+ Par exemple, supposons que vous ayez un projet ressemblant à la figure 5-26.
1040
+
1041
+ Insert 18333fig0526.png
1042
+ Figure 5-26. Historique d'exemple avant une sélection.
1043
+
1044
+ Si vous souhaitez tirer le *commit* `e43a6` dans votre branche `master`, vous pouvez lancer :
1045
+
1046
+ $ git cherry-pick e43a6fd3e94888d76779ad79fb568ed180e5fcdf
1047
+ Finished one cherry-pick.
1048
+ [master]: created a0a41a9: "More friendly message when locking the index fails."
1049
+ 3 files changed, 17 insertions(+), 3 deletions(-)
1050
+
1051
+ La même modification que celle introduite en `e43a6` est tirée mais vous obtenez une nouvelle valeur de SHA-1 car les dates d'application sont différentes.
1052
+ À présent, votre historique ressemble à la figure 5-27.
1053
+
1054
+ Insert 18333fig0527.png
1055
+ Figure 5-27. Historique après sélection d'un *commit* dans une branche thématique.
1056
+
1057
+ Maintenant, vous pouvez effacer votre branche thématique et abandonner les *commits* que vous n'avez pas tirés dans `master`.
1058
+
1059
+ ### Étiquetage de vos publications ###
1060
+
1061
+ Quand vous décidez de créer une publication de votre projet, vous souhaiterez probablement étiqueter le projet pour pouvoir recréer cette version dans le futur.
1062
+ Vous pouvez créer une nouvelle étiquette telle que décrite au chapitre 2.
1063
+ Si vous décidez de signer l'étiquette en tant que mainteneur, la commande ressemblera à ceci :
1064
+
1065
+ $ git tag -s v1.5 -m 'my signed 1.5 tag'
1066
+ You need a passphrase to unlock the secret key for
1067
+ user: "Scott Chacon <schacon@gmail.com>"
1068
+ 1024-bit DSA key, ID F721C45A, created 2009-02-09
1069
+
1070
+ Si vous signez vos étiquettes, vous rencontrerez le problème de la distribution de votre clé publique PGP permettant de vérifier la signature.
1071
+ Le mainteneur du projet Git a résolu le problème en incluant la clé publique comme blob dans le dépôt et en ajoutant une étiquette qui pointe directement sur ce contenu.
1072
+ Pour faire de même, vous déterminez la clé de votre trousseau que vous voulez publier en lançant `gpg --list-keys` :
1073
+
1074
+ $ gpg --list-keys
1075
+ /Users/schacon/.gnupg/pubring.gpg
1076
+ ---------------------------------
1077
+ pub 1024D/F721C45A 2009-02-09 [expires: 2010-02-09]
1078
+ uid Scott Chacon <schacon@gmail.com>
1079
+ sub 2048g/45D02282 2009-02-09 [expires: 2010-02-09]
1080
+
1081
+ Ensuite, vous pouvez importer la clé directement dans la base de données Git en l'exportant de votre trousseau et en la redirigeant dans `git hash-object` qui écrit un nouveau blob avec son contenu dans Git et vous donne en sortie le SHA-1 du blob :
1082
+
1083
+ $ gpg -a --export F721C45A | git hash-object -w --stdin
1084
+ 659ef797d181633c87ec71ac3f9ba29fe5775b92
1085
+
1086
+ À présent, vous avez le contenu de votre clé dans Git et vous pouvez créer une étiquette qui pointe directement dessus en spécifiant la valeur SHA-1 que la commande `hash-object` vous a fournie :
1087
+
1088
+ $ git tag -a maintainer-pgp-pub 659ef797d181633c87ec71ac3f9ba29fe5775b92
1089
+
1090
+ Si vous lancez `git push --tags`, l'étiquette `maintainer-pgp-pub` sera partagée publiquement.
1091
+ Un tiers pourra vérifier une étiquette après import direct de votre clé publique PGP, en extrayant le blob de la base de donnée et en l'important dans GPG :
1092
+
1093
+ $ git show maintainer-pgp-pub | gpg --import
1094
+
1095
+ Il pourra alors utiliser cette clé pour vérifier vos étiquettes signées.
1096
+ Si de plus, vous incluez des instructions d'utilisation pour la vérification de signature dans le message d'étiquetage, l'utilisateur aura accès à ces informations en lançant la commande `git show <étiquette>`.
1097
+
1098
+ ### Génération d'un nom de révision ###
1099
+
1100
+ Comme Git ne fournit pas par nature de nombres croissants tels que « r123 » à chaque validation, la commande `git describe` permet de générer un nom humainement lisible pour chaque *commit*.
1101
+ Git concatène le nom de l'étiquette la plus proche, le nombre de validations depuis cette étiquette et un code SHA-1 partiel du *commit* que l'on cherche à définir :
1102
+
1103
+ $ git describe master
1104
+ v1.6.2-rc1-20-g8c5b85c
1105
+
1106
+ De cette manière, vous pouvez exporter un instantané ou le construire et le nommer de manière intelligible.
1107
+ En fait, si Git est construit à partir du source cloné depuis le dépôt Git, `git --version` vous donne exactement cette valeur.
1108
+ Si vous demandez la description d'un instantané qui a été étiqueté, le nom de l'étiquette est retourné.
1109
+
1110
+ La commande `git describe` repose sur les étiquettes annotées (étiquettes créées avec les options `-a` ou `-s`).
1111
+ Les étiquettes de publication doivent donc être créées de cette manière si vous souhaitez utiliser `git describe` pour garantir que les *commits* seront décrits correctement.
1112
+ Vous pouvez aussi utiliser ces noms comme cible lors d'une extraction ou d'une commande `show`, bien qu'ils reposent sur le SHA-1 abrégé et pourraient ne pas rester valide indéfiniment.
1113
+ Par exemple, le noyau Linux a sauté dernièrement de 8 à 10 caractères pour assurer l'unicité des objets SHA-1 et les anciens noms `git describe` sont par conséquent devenus invalides.
1114
+
1115
+ ### Préparation d'une publication ###
1116
+
1117
+ Maintenant, vous voulez publier une version.
1118
+ Une des étapes consiste à créer une archive du dernier instantané de votre code pour les pauvres hères qui n'utilisent pas Git.
1119
+ La commande dédiée à cette action est `git archive` :
1120
+
1121
+ $ git archive master --prefix='projet/' | gzip > `git describe master`.tar.gz
1122
+ $ ls *.tar.gz
1123
+ v1.6.2-rc1-20-g8c5b85c.tar.gz
1124
+
1125
+ Lorsqu'on ouvre l'archive, on obtient le dernier instantané du projet sous un répertoire `projet`.
1126
+ On peut aussi créer une archive au format zip de manière similaire en passant l'option `--format=zip` à la commande `git archive` :
1127
+
1128
+ $ git archive master --prefix='projet/' --format=zip > `git describe master`.zip
1129
+
1130
+ Voilà deux belles archives tar.gz et zip de votre projet prêtes à être téléchargées sur un site web ou envoyées par e-mail.
1131
+
1132
+ ### Shortlog ###
1133
+
1134
+ Il est temps d'envoyer une annonce à la liste de diffusion des annonces relatives à votre projet.
1135
+ Une manière simple d'obtenir rapidement une sorte de liste des modifications depuis votre dernière version ou e-mail est d'utiliser la commande `git shortlog`.
1136
+ Elle résume toutes les validations dans l'intervalle que vous lui spécifiez.
1137
+ Par exemple, ce qui suit vous donne un résumé de toutes les validations depuis votre dernière version si celle-ci se nomme v1.0.1 :
1138
+
1139
+ $ git shortlog --no-merges master --not v1.0.1
1140
+ Chris Wanstrath (8):
1141
+ Add support for annotated tags to Grit::Tag
1142
+ Add packed-refs annotated tag support.
1143
+ Add Grit::Commit#to_patch
1144
+ Update version and History.txt
1145
+ Remove stray `puts`
1146
+ Make ls_tree ignore nils
1147
+
1148
+ Tom Preston-Werner (4):
1149
+ fix dates in history
1150
+ dynamic version method
1151
+ Version bump to 1.0.2
1152
+ Regenerated gemspec for version 1.0.2
1153
+
1154
+ Vous obtenez ainsi un résumé clair de toutes les validations depuis v1.0.1, regroupées par auteur, prêt à être envoyé sur la liste de diffusion.
1155
+
1156
+ ## Résumé ##
1157
+
1158
+ Vous devriez à présent vous sentir à l'aise pour contribuer à un projet avec Git, mais aussi pour maintenir votre propre projet et intégrer les contributions externes.
1159
+ Félicitations, vous êtes un développeur Git efficace !
1160
+ Au prochain chapitre, vous découvrirez des outils plus puissants pour gérer des situations complexes, qui feront de vous un maître de Git.
1161
+
1162
+ <!-- LocalWords: png CVCS multi-dépôt master commits git diff
1163
+ -->