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,953 @@
1
+ <!-- Attentie heren en dames vertalers.
2
+ Ik zou het volgende willen voorstellen:
3
+ Er zijn bepaalde termen die voor de gemiddelde Nederlandse computer gebruiker
4
+ veel beter klinken (of bekender voorkomen) als de orginele Engelse term. In het
5
+ begin zullen deze termen niet vaak voorkomen, maar in de meer diepgaandere
6
+ hoofdstukken komen deze steeds meer voor. Termen als "Committen", "Mergen"
7
+ en "Applyen" klinken beter dan "Plegen" of "Toepassen", "Samenvoegen" en
8
+ "Toepassen" (wat bovendien slecht valt te onderscheiden van de
9
+ commit-toepassing). De mensen die dit boek lezen zijn, naar mijn bescheiden
10
+ inschatting, al redelijk op de hoogte van versiebeheer en passen (zie ik in
11
+ de praktijk) deze termen al toe. Een nieuwe terminologie introduceren lijkt
12
+ me dan ook niet noodzakelijk.
13
+ Verder blijven er altijd kreten over als "directory", wat vertaald zou kunnen
14
+ worden als "map", maar bij het Engelse werkwoord to map krijgen we dan weer het
15
+ probleem: hoe dit weer te vertalen? Daarom zou ik willen voorstellen om deze
16
+ basis-termen toch onvertaald te laten.
17
+
18
+ Twijfelgevallen zullen altijd blijven zoals de term "file", daarvan wordt in de
19
+ praktijk zowel de term file als bestand gebruikt. Ik denk dat we hier moeten
20
+ kijken hoe het in de context past.
21
+ Maar ook een term als "tool" en (ik zit zelf nog op een mooie Nederlandse term
22
+ te broeden) "plumbing", hierbij stel ik voor om eenmalig een Nederlandse
23
+ vertaling te geven, tussen haakjes de Engelse term te geven en in het vervolg
24
+ de Engelse term te gebruiken. Wederom is de context hier belangrijk.
25
+
26
+ Verder stel ik ook voor om de regels op https://onzetaal.nl/taaladvies zoveel
27
+ mogelijk te volgen. Bijvoorbeeld de regels omtrent het spellen van Engelse
28
+ werkwoorden die in het Nederlands gebruikt worden.
29
+
30
+ Let wel: ik wil niemand tot iets verplichten, maar ik denk dat we moeten
31
+ streven naar een zo duidelijk mogelijke en best bij de praktijk aansluitende
32
+ vertaling moeten proberen te maken.
33
+
34
+ Veel succes en plezier bij het vertalen...
35
+ -->
36
+ <!-- SHA-1 of last checked en-version: 4cefec -->
37
+ # Gedistribueerd Git #
38
+
39
+ Nu je een remote Git repository hebt ingesteld als een plaats waar alle ontwikkelaars hun code kunnen delen, en je bekend bent met fundamentele Git commando's in een lokale workflow, zul je hier zien hoe je een paar gedistribueerde workflows kunt gebruiken die je met Git kunt bereiken.
40
+
41
+ In dit hoofdstuk zul je zien hoe je met Git kunt werken in een gedistribueerde omgeving als een bijdrager (contributor) en als een integrator. Dat wil zeggen, je zult leren hoe je succesvol code kunt bijdragen aan een project en hoe je het zo makkelijk mogelijk maakt voor jou en de onderhouder van het project, en ook hoe je een project succesvol kunt onderhouden waarbij een aantal ontwikkelaars bijdragen.
42
+
43
+ ## Gedistribueerde workflows ##
44
+
45
+ In tegenstelling tot gecentraliseerde versiebeheersystemen (CVCSen), stelt de gedistribueerde aard van Git je in staat om veel flexibeler te zijn in de manier waarop ontwikkelaars samenwerken in projecten. Bij gecentraliseerde systemen is iedere ontwikkelaar een knooppunt dat min of meer gelijkwaardig werkt op een centraal punt. In Git is iedere ontwikkelaar zowel een knooppunt als een spil - dat wil zeggen, iedere ontwikkelaar kan zowel code bijdragen aan andere repositories, als ook een publiek repository beheren waarop andere ontwikkelaars hun werk baseren en waaraan zij kunnen bijdragen. Dit stelt je project en/of je team in staat om een enorm aantal workflows er op na te houden, dus ik zal een aantal veel voorkomende manieren behandelen die gebruik maken van deze flexibiliteit. Ik zal de sterke en mogelijke zwakke punten van ieder ontwerp behandelen; je kunt er een kiezen om te gebruiken, of je kunt van iedere wijze een paar eigenschappen overnemen en mengen.
46
+
47
+ ### Gecentraliseerde workflow ###
48
+
49
+ In gecentraliseerde systemen is er over het algemeen een enkel samenwerkingsmodel - de gecentraliseerde workflow. Één centraal punt, of repository, kan code aanvaarden, en iedereen synchroniseert zijn werk daarmee. Een aantal ontwikkelaars zijn knopen - gebruikers van dat centrale punt - en synchroniseren met die plaats (zie Figuur 5-1).
50
+
51
+ Insert 18333fig0501.png
52
+ Figuur 5-1. Gecentraliseerde workflow.
53
+
54
+ Dit betekent dat als twee ontwikkelaars clonen van het gecentraliseerde punt en beiden wijzigingen doen, de eerste ontwikkelaar zijn wijzigingen zonder problemen kan pushen. De tweede ontwikkelaar zal het werk van de eerste in het zijne moeten mergen voordat hij het zijne kan pushen, om zo niet het werk van de eerste te overschrijven. Dit concept werkt in Git zoals het ook werkt in Subversion (of ieder ander CVCS), en dit model werkt prima in Git.
55
+
56
+ Als je een klein team hebt, of al vertrouwd bent met een gecentraliseerde workflow in je bedrijf of team, dan kun je eenvoudig doorgaan met het gebruiken van die workflow met Git. Stel eenvoudigweg een enkele repository in, en geef iedereen in je team push-toegang; Git zal gebruikers niet toestaan om elkaars wijzigingen te overschrijven. Als een ontwikkelaar cloned, wijzigingen maakt, en dan probeert zijn wijzigingen te pushen terwijl een andere ontwikkelaar de zijne in de tussentijd heeft gepusht, dan zal de server de wijzigingen van die ontwikkelaar weigeren. Ze zullen verteld worden dat ze een "non-fast-forward-wijziging" proberen te pushen en dat ze dat niet wordt toegestaan totdat ze hebben gefetched en gemerged.
57
+ Deze workflow is voor een hoop mensen aantrekkelijk omdat het er een is waarmee veel mensen bekend zijn en zich op hun gemak bij voelen.
58
+
59
+ ### Integratie-manager workflow ###
60
+
61
+ Omdat Git je toestaat om meerdere remote repositories te hebben, is het mogelijk om een workflow te hebben waarbij iedere ontwikkelaar schrijftoegang heeft tot zijn eigen publieke repository en leestoegang op de andere. Dit scenario heeft vaak een gezagdragend (canonical) repository dat het "officiële" project voorstelt. Om bij te kunnen dragen tot dat project, maak je je eigen publieke clone van het project en pusht je wijzigingen daarin terug. Daarna stuur je een verzoek naar de eigenaar van het hoofdproject om jouw wijzigingen binnen te halen (pull request). Hij kan je repository toevoegen als een remote, je wijzigingen lokaal testen, ze in zijn branch mergen, en dan naar zijn repository pushen. Het proces werkt als volgt (zie Figuur 5-2):
62
+
63
+ 1. De projecteigenaar pusht naar de publieke repository.
64
+ 2. Een bijdrager cloned die repository en maakt wijzigingen.
65
+ 3. De bijdrager pusht naar zijn eigen publieke kopie.
66
+ 4. De bijdrager stuurt de eigenaar een e-mail met de vraag om de wijzigingen binnen te halen (pull request).
67
+ 5. De eigenaar voegt de repo van de bijdrager toe als een remote en merged lokaal.
68
+ 6. De eigenaar pusht de gemergde wijzigingen terug in de hoofdrepository.
69
+
70
+ Insert 18333fig0502.png
71
+ Figuur 5-2. Integratie-manager workflow.
72
+
73
+ Dit is een veel voorkomende workflow bij websites zoals GitHub, waarbij het eenvoudig is om een project af te splitsen (fork) en je wijzigingen te pushen in jouw afgesplitste project waar iedereen ze kan zien. Een van de grote voordelen van deze aanpak is dat je door kunt gaan met werken, en de eigenaar van de hoofdrepository jouw wijzigingen op ieder moment kan pullen. Bijdragers hoeven niet te wachten tot het project hun bijdragen invoegt - iedere partij kan op zijn eigen tempo werken.
74
+
75
+ ### Dictator en luitenanten workflow ###
76
+
77
+ Dit is een variant op de multi-repository workflow. Het wordt over het algemeen gebruikt bij enorme grote projecten met honderden bijdragers; een bekend voorbeeld is de Linux-kernel. Een aantal integrators geven de leiding over bepaalde delen van de repository, zij worden luitenanten genoemd. Alle luitenanten hebben één integrator die bekend staat als de welwillende dictator. De repository van de welwillende dictator dient als het referentierepository vanwaar alle bijdragers dienen binnen te halen. Het proces werkt als volgt (zie Figuur 5-3):
78
+
79
+ 1. Reguliere ontwikkelaars werken op hun eigen onderwerp (topic) branch en rebasen hun werk op de master. De masterbranch is die van de dictator.
80
+ 2. Luitenanten mergen de topic branches van de ontwikkelaars in hun masterbranch.
81
+ 3. De dictator merged de masterbranches van de luitenanten in de masterbranch van de dictator.
82
+ 4. De dictator pusht zijn masterbranch terug naar het referentierepository zodat de andere ontwikkelaars kunnen rebasen.
83
+
84
+ Insert 18333fig0503.png
85
+ Figuur 5-3. Welwillende-dictatorwerkwijze.
86
+
87
+ Deze manier van werken is niet gewoon, maar kan handig zijn in hele grote projecten of in zeer hiërarchische omgevingen, omdat het de projectleider (de dictator) in staat stelt om het meeste werk te delegeren en grote subsets van code te verzamelen op meerdere punten alvorens ze te integreren.
88
+
89
+ Dit zijn veel voorkomende workflows die mogelijk zijn met een gedistribueerd systeem als Git, maar je kunt zien dat er veel variaties mogelijk zijn om ze te laten passen bij jouw specifieke workflow. Nu dat je (naar ik hoop) in staat bent om te bepalen welke combinatie van workflows voor jou werkt, zal ik wat specifiekere voorbeelden behandelen hoe je de belangrijkste rollen kunt vervullen die in de verschillende workflows voorkomen.
90
+
91
+ ## Bijdragen aan een project ##
92
+
93
+ Je weet wat de verschillende workflows zijn, en je zou het fundamentele gebruik van Git in de vingers moeten hebben. In dit gedeelte zul je leren over een aantal voorkomende patronen voor het bijdragen aan een project.
94
+
95
+ De grote moeilijkheid bij het beschrijven van dit proces is dat er een enorm aantal variaties mogelijk zijn in hoe het gebeurt. Om dat Git erg flexibel is, kunnen en zullen mensen op vele manieren samenwerken, en het is lastig om te beschrijven hoe je zou moeten bijdragen aan een project - ieder project is een beetje anders. Een aantal van de betrokken variabelen zijn de grote van actieve bijdragen, gekozen workflow, je commit toegang, en mogelijk de manier waarop externe bijdragen worden gedaan.
96
+
97
+ De eerste variabele is de grootte van actieve bijdrage. Hoeveel gebruikers dragen actief code bij aan dit project, en hoe vaak? In veel gevallen zal je twee of drie ontwikkelaars met een paar commits per dag hebben, of misschien minder voor wat meer slapende projecten. Voor zeer grote bedrijven of projecten kan het aantal ontwikkelaars in de duizenden lopen, met tientallen of zelfs honderden patches die iedere dag binnenkomen. Dit is belangrijk omdat met meer en meer ontwikkelaars, je meer en meer problemen tegenkomt bij het je verzekeren dat code netjes gepatched of eenvoudig gemerged kan worden. Wijzigingen die je indient kunnen verouderd of zwaar beschadigd raken door werk dat gemerged is terwijl je ermee aan het werken was, of terwijl je wijzigingen in de wacht stonden voor goedkeuring of toepassing. Hoe kun je jouw code consequent bij de tijd en je patches geldig houden?
98
+
99
+ De volgende variabele is de gebruikte workflow in het project. Is het gecentraliseerd, waarbij iedere ontwikkelaar gelijkwaardige schrijftoegang heeft tot de hoofd codebasis? Heeft het project een eigenaar of integrator die alle patches controleert? Worden alle patches gereviewed en goedgekeurd? Ben jij betrokken bij dat proces? Is er een luitenanten systeem neergezet, en moet je je werk eerst bij hen inleveren?
100
+
101
+ Het volgende probleem is je commit toegang. De benodigde workflow om bij te dragen aan een project is heel verschillend als je schrijftoegang hebt tot het project dan wanneer je dat niet hebt. Als je geen schrijftoegang hebt, wat is de voorkeur van het project om bijdragen te ontvangen? Is er überhaupt een beleid? Hoeveel werk draag je per keer bij? Hoe vaak draag je bij?
102
+
103
+ Al deze vragen kunnen van invloed zijn op hoe je effectief bijdraagt aan een project en welke workflows de voorkeur hebben of die beschikbaar zijn voor je. Ik zal een aantal van deze aspecten behandelen in een aantal voorbeelden, waarbij ik van eenvoudig tot complex zal gaan. Je zou in staat moeten zijn om de specifieke workflows die je in jouw praktijk nodig hebt te kunnen herleiden vanuit deze voorbeelden.
104
+
105
+ ### Commit richtlijnen ###
106
+
107
+ Voordat je gaat kijken naar de specifieke gebruiksscenario's, volgt hier een kort stukje over commit berichten. Het hebben van een goede richtlijn voor het maken commits en je daar aan houden maakt het werken met Git en samenwerken met anderen een stuk makkelijker. Het Git project levert een document waarin een aantal goede tips staan voor het maken van commits waaruit je patches kunt indienen - je kunt het lezen in de Git broncode in het `Documentation/SubmittingPatches` bestand.
108
+
109
+ Als eerste wil je geen witruimte fouten indienen. Git geeft je een eenvoudige manier om hierop te controleren - voordat je commit, voer `git diff --check` uit, wat mogelijke witruimte fouten identificeert en ze voor je afdrukt. Hier is een voorbeeld, waarbij ik een rode terminal kleur hebt vervangen door `X`en:
110
+
111
+ $ git diff --check
112
+ lib/simplegit.rb:5: trailing whitespace.
113
+ + @git_dir = File.expand_path(git_dir)XX
114
+ lib/simplegit.rb:7: trailing whitespace.
115
+ + XXXXXXXXXXX
116
+ lib/simplegit.rb:26: trailing whitespace.
117
+ + def command(git_cmd)XXXX
118
+
119
+ Als je dat commando uitvoert alvorens te committen, kun je al zien of je op het punt staat witruimte problemen te committen waaraan andere ontwikkelaars zich zullen ergeren.
120
+
121
+ Probeer vervolgens om van elke commit een logische set wijzigingen te maken. Probeer, als het je lukt, om je wijzigingen verteerbaar te maken - ga niet het hele weekend zitten coderen op vijf verschillende problemen om dat vervolgens op maandag als een gigantische commit in te dienen. Zelfs als je gedurende het weekend niet commit, gebruik dan het staging gebied op maandag om je werk in ten minste één commit per probleem op te splitsen, met een bruikbaar bericht per commit. Als een paar van de wijzigingen één bestand veranderen, probeer dan `git add --patch` te gebruiken om bestanden gedeeltelijk te stagen (wordt in detail behandeld in Hoofdstuk 6). De snapshot aan de kop van het project is gelijk of je nu één commit doet of vijf, zolang alle wijzigingen op een gegeven moment maar toegevoegd zijn, dus probeer om het je mede-ontwikkelaars makkelijk te maken als ze je wijzigingen moeten bekijken. Deze aanpak maakt het ook makkelijker om één wijziging eruit te selecteren of terug te draaien, mocht dat later nodig zijn. Hoofdstuk 6 beschrijft een aantal handige Git trucs om geschiedenis te herschrijven en bestanden interactief te stagen - gebruik deze gereedschappen als hulp om een schone en begrijpelijke historie op te bouwen.
122
+
123
+ Het laatste om in gedachten te houden is het commit bericht. Als je er een gewoonte van maakt om een goede kwaliteit commit berichten aan te maken, dan maakt dat het gebruik van en samenwerken in Git een stuk eenvoudiger. In het algemeen zouden je berichten moeten beginnen met een enkele regel die niet langer is dan 50 karakters en die de wijzigingen beknopt omschrijft, gevolgd door een lege regel en daarna een meer gedetailleerde uitleg. Het Git project vereist dat de meer gedetailleerde omschrijving ook je motivatie voor de verandering bevat, en de nieuwe implementatie tegen het oude gedrag afzet. Dit is een goede richtlijn om te volgen. Het is ook een goed idee om de gebiedende wijs te gebruiken in deze berichten. Met andere woorden, gebruik commando's. In plaats van "Ik heb testen toegevoegd voor" of "Testen toegevoegd voor" gebruik je "Voeg testen toe voor".
124
+ Hier is een sjabloon dat origineel geschreven is door Tim Pope op tpope.net:
125
+
126
+ Kort (50 karakters of minder) samenvatting van wijzigingen
127
+
128
+ Gedetailleerdere beschrijvende tekst, indien nodig. Laat het na
129
+ ongeveer 72 karakters afbreken. In sommige contexten, wordt de
130
+ eerste regel behandeld als het onderwerp van een email en de rest
131
+ als inhoud. De lege regel die de samenvatting scheidt van de
132
+ inhoud is essentieel (tenzij je de inhoud helemaal weglaat);
133
+ applicaties zoals rebase kunnen in de war raken als je ze
134
+ samenvoegt.
135
+
136
+ Vervolg paragrafen komen na lege regels.
137
+
138
+ - Aandachtspunten zijn ook goed.
139
+
140
+ - Typisch wordt een streepje of sterretje gebruikt als "bullet",
141
+ voorafgegaan door een enkele spatie, met ertussen lege regels,
142
+ maar de conventies variëren hierin.
143
+
144
+ Als al je commit berichten er zo uit zien, dan zullen de dingen een stuk eenvoudiger zijn voor jou en de ontwikkelaars waar je mee samenwerkt. Het Git project heeft goed geformatteerde commit berichten - ik raad je aan om `git log --no-merges` uit te voeren om te zien hoe een goed geformatteerde project-commit historie eruit ziet.
145
+
146
+ In de volgende voorbeelden, en verder door de rest van dit boek, zal ik omwille van bondigheid de berichten niet zo netjes als dit formatteren; in plaats daarvan gebruik ik de `-m` optie voor `git commit`. Doe wat ik zeg, niet wat ik doe.
147
+
148
+ ### Besloten klein team ###
149
+
150
+ De eenvoudigste opzet die je waarschijnlijk zult tegenkomen is een besloten project met één of twee andere ontwikkelaars. Met besloten bedoel ik gesloten broncode - zonder leestoegang voor de buitenwereld. Jij en de andere ontwikkelaars hebben allemaal push toegang op de repository.
151
+
152
+ In deze omgeving kan je een workflow aanhouden die vergelijkbaar is met wat je zou doen als je Subversion of een andere gecentraliseerd systeem zou gebruiken. Je hebt nog steeds de voordelen van zaken als offline committen en veel eenvoudiger branchen en mergen, maar de workflow kan erg vergelijkbaar zijn. Het grootste verschil is dat het mergen aan de client-kant gebeurt tijdens het committen in plaats van aan de server-kant.
153
+ Laten we eens kijken hoe het er uit zou kunnen zien als twee ontwikkelaars samen beginnen te werken met een gedeelde repository. De eerste ontwikkelaar, John, cloned de repository, maakt een wijziging, en commit lokaal. (Ik vervang de protocol berichten met `...` in deze voorbeelden om ze iets in te korten.)
154
+
155
+ # John's Machine
156
+ $ git clone john@githost:simplegit.git
157
+ Initialized empty Git repository in /home/john/simplegit/.git/
158
+ ...
159
+ $ cd simplegit/
160
+ $ vim lib/simplegit.rb
161
+ $ git commit -am 'removed invalid default value'
162
+ [master 738ee87] removed invalid default value
163
+ 1 files changed, 1 insertions(+), 1 deletions(-)
164
+
165
+ De tweede ontwikkelaar, Jessica, doet hetzelfde - cloned de repository en commit een wijziging:
166
+
167
+ # Jessica's Machine
168
+ $ git clone jessica@githost:simplegit.git
169
+ Initialized empty Git repository in /home/jessica/simplegit/.git/
170
+ ...
171
+ $ cd simplegit/
172
+ $ vim TODO
173
+ $ git commit -am 'add reset task'
174
+ [master fbff5bc] add reset task
175
+ 1 files changed, 1 insertions(+), 0 deletions(-)
176
+
177
+ Nu pusht Jessica haar werk naar de server:
178
+
179
+ # Jessica's Machine
180
+ $ git push origin master
181
+ ...
182
+ To jessica@githost:simplegit.git
183
+ 1edee6b..fbff5bc master -> master
184
+
185
+ John probeert ook zijn werk te pushen:
186
+
187
+ # John's Machine
188
+ $ git push origin master
189
+ To john@githost:simplegit.git
190
+ ! [rejected] master -> master (non-fast forward)
191
+ error: failed to push some refs to 'john@githost:simplegit.git'
192
+
193
+ John mag niet pushen omdat Jessica in de tussentijd gepusht heeft. Dit is belangrijk om te begrijpen als je gewend bent aan Subversion, omdat het je zal opvallen dat de twee ontwikkelaars niet hetzelfde bestand hebben aangepast. Waar Subversion automatisch zo'n merge op de server doet als verschillende bestanden zijn aangepast, moet je in Git de commits lokaal mergen. John moet Jessica's wijzigingen ophalen (fetch) en ze mergen voor hij mag pushen:
194
+
195
+ $ git fetch origin
196
+ ...
197
+ From john@githost:simplegit
198
+ + 049d078...fbff5bc master -> origin/master
199
+
200
+ Hierna ziet John's lokale repository er ongeveer uit zoals Figuur 5-4.
201
+
202
+ Insert 18333fig0504.png
203
+ Figuur 5-4. John's initiële repository.
204
+
205
+ John heeft een referentie naar de wijzigingen die Jessica gepusht heeft, maar hij moet ze mergen met zijn eigen werk voordat hij het mag pushen:
206
+
207
+ $ git merge origin/master
208
+ Merge made by recursive.
209
+ TODO | 1 +
210
+ 1 files changed, 1 insertions(+), 0 deletions(-)
211
+
212
+ Het mergen gaat soepeltjes - de commit historie van John ziet er nu uit als Figuur 5-5.
213
+
214
+ Insert 18333fig0505.png
215
+ Figuur 5-5. John's repository na het mergen van `origin/master`.
216
+
217
+ Nu kan John zijn code testen om er zeker van te zijn dat alles nog steeds goed werkt, en dan kan hij zijn nieuwe gemergede werk pushen naar de server:
218
+
219
+ $ git push origin master
220
+ ...
221
+ To john@githost:simplegit.git
222
+ fbff5bc..72bbc59 master -> master
223
+
224
+ Tenslotte ziet John's commit historie eruit als Figuur 5-6.
225
+
226
+ Insert 18333fig0506.png
227
+ Figuur 5-6. John's historie na gepusht te hebben naar de origin server.
228
+
229
+ In de tussentijd heeft Jessica gewerkt op een topic branch. Ze heeft een topic branch genaamd `issue54` aangemaakt en daar drie commits op gedaan. Ze heeft John's wijzigingen nog niet opgehaald, dus haar commit historie ziet er uit als Figuur 5-7.
230
+
231
+ Insert 18333fig0507.png
232
+ Figuur 5-7. Jessica's initiële commit historie.
233
+
234
+ Jessica wil met John synchroniseren, dus ze haalt de wijzigingen op:
235
+
236
+ # Jessica's Machine
237
+ $ git fetch origin
238
+ ...
239
+ From jessica@githost:simplegit
240
+ fbff5bc..72bbc59 master -> origin/master
241
+
242
+ Dit haalt het werk op dat John in de tussentijd gepusht heeft. Jessica's historie ziet er nu uit als Figuur 5-8.
243
+
244
+ Insert 18333fig0508.png
245
+ Figuur 5-8. Jessica's historie na het fetchen van John's wijzigingen.
246
+
247
+ Jessica denkt dat haar topic branch nu klaar is, maar ze wil weten wat ze in haar werk moet mergen zodat ze kan pushen. Ze voert `git log` uit om dat uit te zoeken:
248
+
249
+ $ git log --no-merges origin/master ^issue54
250
+ commit 738ee872852dfaa9d6634e0dea7a324040193016
251
+ Author: John Smith <jsmith@example.com>
252
+ Date: Fri May 29 16:01:27 2009 -0700
253
+
254
+ removed invalid default value
255
+
256
+ Nu kan Jessica het werk van haar onderwerp mergen in haar `master` branch, John's werk (`origin/master`) in haar `master` branch mergen, en dan naar de server pushen. Eerst schakelt ze terug naar haar `master` branch om al dit werk te integreren:
257
+
258
+ $ git checkout master
259
+ Switched to branch "master"
260
+ Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
261
+
262
+ Ze kan `origin/master` of `issue54` als eerste mergen - ze zijn beide stroomopwaarts dus de volgorde maakt niet uit. Uiteindelijk zou de snapshot gelijk moeten zijn ongeacht welke volgorde ze kiest; alleen de geschiedenis zal iets verschillen. Ze kiest ervoor om `issue54` eerst samen te voegen:
263
+
264
+ $ git merge issue54
265
+ Updating fbff5bc..4af4298
266
+ Fast forward
267
+ README | 1 +
268
+ lib/simplegit.rb | 6 +++++-
269
+ 2 files changed, 6 insertions(+), 1 deletions(-)
270
+
271
+ Er doen zich geen problemen voor, zoals je kunt zien was het een eenvoudige fast-forward. Nu merged Jessica John's werk (`origin/master`):
272
+
273
+ $ git merge origin/master
274
+ Auto-merging lib/simplegit.rb
275
+ Merge made by recursive.
276
+ lib/simplegit.rb | 2 +-
277
+ 1 files changed, 1 insertions(+), 1 deletions(-)
278
+
279
+ Alles merged netjes, en Jessica's historie ziet er uit als Figuur 5-9.
280
+
281
+ Insert 18333fig0509.png
282
+ Figuur 5-9. Jessica's historie na het mergen van John's wijzigingen.
283
+
284
+ Nu is `origin/master` bereikbaar vanuit Jessica's `master` branch, dus ze zou in staat moeten zijn om succesvol te pushen (even aangenomen dat John in de tussentijd niets gepusht heeft):
285
+
286
+ $ git push origin master
287
+ ...
288
+ To jessica@githost:simplegit.git
289
+ 72bbc59..8059c15 master -> master
290
+
291
+ Iedere ontwikkelaar heeft een paar keer gecommit en elkaars werk succesvol samengevoegd, zie Figuur 5-10.
292
+
293
+ Insert 18333fig0510.png
294
+ Figuur 5-10. Jessica's historie na alle wijzigingen teruggezet te hebben op de server.
295
+
296
+ Dit is één van de eenvoudigste workflows. Je werkt een tijdje, over het algemeen in een topic branch, en merged dit in je `master` branch als het klaar is om te worden geïntegreerd. Als je dat werk wilt delen, dan merge je het in je eigen `master` branch, en vervolgens fetch je `origin/master` en merge je deze als het gewijzigd is, en als laatste push je deze naar de `master` branch op de server. De algemene volgorde is zoiets als die getoond in Figuur 5-11.
297
+
298
+ Insert 18333fig0511.png
299
+ Figuur 5-11. Algemene volgorde van gebeurtenissen voor een eenvoudige multi-ontwikkelaar Git workflow.
300
+
301
+ ### Besloten aangestuurd team ###
302
+
303
+ In het volgende scenario zul je kijken naar de rol van de bijdragers in een grotere besloten groep. Je zult leren hoe te werken in een omgeving waar kleine groepen samenwerken aan functies, waarna die team-gebaseerde bijdragen worden geïntegreerd door een andere partij.
304
+
305
+ Stel dat John en Jessica samen werken aan een functie, terwijl Jessica en Josie aan een tweede aan het werken zijn. In dit geval gebruikt het bedrijf een integratie-manager achtige workflow, waarbij het werk van de individuele groepen alleen wordt geïntegreerd door bepaalde ontwikkelaars, en de `master` branch van het hoofd repo alleen kan worden vernieuwd door die ontwikkelaars. In dit scenario wordt al het werk gedaan in team-gebaseerde branches en later door de integrators samengevoegd.
306
+
307
+ Laten we Jessica's workflow volgen terwijl ze aan haar twee features werkt, in parallel met twee verschillende ontwikkelaars in deze omgeving. We nemen even aan dat ze haar repository al gecloned heeft, en dat ze besloten heeft als eerste te werken aan `featureA`. Ze maakt een nieuwe branch aan voor de functie en doet daar wat werk:
308
+
309
+ # Jessica's Machine
310
+ $ git checkout -b featureA
311
+ Switched to a new branch "featureA"
312
+ $ vim lib/simplegit.rb
313
+ $ git commit -am 'add limit to log function'
314
+ [featureA 3300904] add limit to log function
315
+ 1 files changed, 1 insertions(+), 1 deletions(-)
316
+
317
+ Op dit punt, moet ze haar werk delen met John, dus ze pusht haar commits naar de `featureA` branch op de server. Jessica heeft geen push toegang op de `master` branch - alleen de integratoren hebben dat - dus ze moet naar een andere branch pushen om samen te kunnen werken met John:
318
+
319
+ $ git push origin featureA
320
+ ...
321
+ To jessica@githost:simplegit.git
322
+ * [new branch] featureA -> featureA
323
+
324
+ Jessica mailt John om hem te zeggen dat ze wat werk gepusht heeft in een branch genaamd `featureA` en dat hij er nu naar kan kijken. Terwijl ze op terugkoppeling van John wacht, besluit Jessica te beginnen met het werken aan `featureB` met Josie. Om te beginnen start ze een nieuwe functie branch, gebaseerd op de `master` branch van de server:
325
+
326
+ # Jessica's Machine
327
+ $ git fetch origin
328
+ $ git checkout -b featureB origin/master
329
+ Switched to a new branch "featureB"
330
+
331
+ Nu doet Jessica een paar commits op de `featureB` branch:
332
+
333
+ $ vim lib/simplegit.rb
334
+ $ git commit -am 'made the ls-tree function recursive'
335
+ [featureB e5b0fdc] made the ls-tree function recursive
336
+ 1 files changed, 1 insertions(+), 1 deletions(-)
337
+ $ vim lib/simplegit.rb
338
+ $ git commit -am 'add ls-files'
339
+ [featureB 8512791] add ls-files
340
+ 1 files changed, 5 insertions(+), 0 deletions(-)
341
+
342
+ Jessica's repository ziet eruit als Figuur 5-12.
343
+
344
+ Insert 18333fig0512.png
345
+ Figuur 5-12. Jessica's initiële commit historie.
346
+
347
+ Ze is klaar om haar werk te pushen, maar ze krijgt een mail van Josie dat een branch met wat initieel werk erin al gepusht is naar de server in de `featureBee` branch. Jessica moet die wijzigingen eerst mergen met die van haar voordat ze kan pushen naar de server. Ze kan dan Josie's wijzigingen ophalen met `git fetch`:
348
+
349
+ $ git fetch origin
350
+ ...
351
+ From jessica@githost:simplegit
352
+ * [new branch] featureBee -> origin/featureBee
353
+
354
+ Jessica kan dit nu mergen in het werk wat zij gedaan heeft met `git merge`:
355
+
356
+ $ git merge origin/featureBee
357
+ Auto-merging lib/simplegit.rb
358
+ Merge made by recursive.
359
+ lib/simplegit.rb | 4 ++++
360
+ 1 files changed, 4 insertions(+), 0 deletions(-)
361
+
362
+ Er is wel een klein probleempje - ze moet het gemergde werk in haar `featureB` branch naar de `featureBee` branch op de server zetten. Ze kan dat doen door de lokale branch door te geven aan het `git push` commando, gevolgd door een dubbele punt (:), gevolgd door de remote branch:
363
+
364
+ $ git push origin featureB:featureBee
365
+ ...
366
+ To jessica@githost:simplegit.git
367
+ fba9af8..cd685d1 featureB -> featureBee
368
+
369
+ Dit wordt een _refspec_ genoemd. Zie Hoofdstuk 9 voor een gedetailleerdere behandeling van Git refspecs en de verschillende dingen die je daarmee kan doen.
370
+
371
+ Vervolgens mailt John naar Jessica om te zeggen dat hij wat wijzigingen naar de `featureA` branch gepusht heeft, en om haar te vragen die te verifiëren. Ze voert een `git fetch` uit om die wijzigingen op te halen:
372
+
373
+ $ git fetch origin
374
+ ...
375
+ From jessica@githost:simplegit
376
+ 3300904..aad881d featureA -> origin/featureA
377
+
378
+ Daarna kan ze zien wat er veranderd is met `git log`:
379
+
380
+ $ git log origin/featureA ^featureA
381
+ commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6
382
+ Author: John Smith <jsmith@example.com>
383
+ Date: Fri May 29 19:57:33 2009 -0700
384
+
385
+ changed log output to 30 from 25
386
+
387
+ Uiteindelijk merged ze John's werk in haar eigen `featureA` branch:
388
+
389
+ $ git checkout featureA
390
+ Switched to branch "featureA"
391
+ $ git merge origin/featureA
392
+ Updating 3300904..aad881d
393
+ Fast forward
394
+ lib/simplegit.rb | 10 +++++++++-
395
+ 1 files changed, 9 insertions(+), 1 deletions(-)
396
+
397
+ Jessica wil iets kleins wijzigen, dus doet ze nog een commit en pusht dit naar de server:
398
+
399
+ $ git commit -am 'small tweak'
400
+ [featureA ed774b3] small tweak
401
+ 1 files changed, 1 insertions(+), 1 deletions(-)
402
+ $ git push origin featureA
403
+ ...
404
+ To jessica@githost:simplegit.git
405
+ 3300904..ed774b3 featureA -> featureA
406
+
407
+ Jessica's commit historie ziet er nu uit zoals Figuur 5-13.
408
+
409
+ Insert 18333fig0513.png
410
+ Figuur 5-13. Jessica's historie na het committen op een feature branch.
411
+
412
+ Jessica, Josie en John informeren de integrators nu dat de `featureA` en `featureBee` branches op de server klaar zijn voor integratie in de hoofdlijn. Nadat zij die branches in de hoofdlijn geïntegreerd hebben, zal een fetch de nieuwe merge commits ophalen, waardoor de commit historie er uit ziet zoals Figuur 5-14.
413
+
414
+
415
+ Insert 18333fig0514.png
416
+ Figuur 5-14. Jessica's historie na het mergen van allebei haar onderwerp branches.
417
+
418
+ Veel groepen schakelen om naar Git juist vanwege de mogelijkheid om meerdere teams in parallel te kunnen laten werken, waarbij de verschillende lijnen van werk laat in het proces gemerged worden. De mogelijkheid van kleinere subgroepen of een team om samen te werken via remote branches zonder het hele team erin te betrekken of te hinderen is een enorm voordeel van Git. De volgorde van de workflow die je hier zag is ongeveer zoals Figuur 5-15.
419
+
420
+ Insert 18333fig0515.png
421
+ Figuur 5-15. Eenvoudige volgorde in de workflow van dit aangestuurde team.
422
+
423
+ ### Klein openbaar project ###
424
+
425
+ Het bijdragen aan openbare, of publieke, projecten gaat op een iets andere manier. Omdat je niet de toestemming hebt om de branches van het project rechtstreeks te updaten, moet je het werk op een andere manier naar de beheerders krijgen. Dit eerste voorbeeld beschrijft het bijdragen via afsplitsen (forken) op Git hosts die het eenvoudig aanmaken van forks ondersteunen. De repo.or.cz en GitHub hosting sites ondersteunen dit beide, en veel project beheerders verwachten deze manier van bijdragen. De volgende paragraaf behandelt projecten die de voorkeur hebben om bijdragen in de vorm van patches via e-mail te ontvangen.
426
+
427
+ Eerst zal je waarschijnlijk de hoofdrepository clonen, een topic branch maken voor de patch of reeks patches die je van plan bent bij te dragen, en je werk daarop doen. De te volgen stappen zien er zo uit:
428
+
429
+ $ git clone (url)
430
+ $ cd project
431
+ $ git checkout -b featureA
432
+ $ (work)
433
+ $ git commit
434
+ $ (work)
435
+ $ git commit
436
+
437
+ Je kunt eventueel besluiten `rebase -i` te gebruiken om je werk in één enkele commit samen te persen (squash), of het werk in de commits te herschikken om de patch eenvoudiger te kunnen laten reviewen door de beheerders - zie Hoofdstuk 6 voor meer informatie over het interactief rebasen.
438
+
439
+ Als je werk op de branch af is, en je klaar bent om het over te dragen aan de beheerders, ga je naar de originele project pagina en klik op de "Fork" knop. Hiermee maak je een eigen overschrijfbare fork van het project. Je moet de URL van deze nieuwe repository URL toevoegen als een tweede remote, in dit geval `myfork` genaamd:
440
+
441
+ $ git remote add myfork (url)
442
+
443
+ Je wilt je werk daar naartoe pushen. Het is het makkelijkst om de remote branch waar je op zit te werken te pushen naar je repository, in plaats van het te mergen in je master branch en die te pushen. De reden hiervan is, dat als het werk niet wordt geaccepteerd of alleen ge-cherry picked (deels overgenomen), je jouw master branch niet hoeft terug te draaien. Als de beheerders je werk mergen, rebasen of cherry picken, dan krijg je het uiteindelijk toch binnen door hun repository te pullen:
444
+
445
+ $ git push myfork featureA
446
+
447
+ Als jouw werk gepusht is naar jouw fork, dan moet je de beheerder inlichten. Dit wordt een pull request (haal-binnen-verzoek) genoemd, en je kunt deze via de website genereren - GitHub heeft een "pull request" knop die de beheerder automatisch een bericht stuurt - of het `git request-pull` commando uitvoeren en de uitvoer handmatig naar de projectbeheerder mailen.
448
+
449
+ Het `request-pull` commando neemt de basis branch waarin je de topic branch gepulled wil hebben, en de URL van de Git repository waar je ze uit wil laten pullen, en maakt een samenvatting van alle wijzigingen die je gepulled wenst te hebben. Bijvoorbeeld, als Jessica John een pull request wil sturen, en ze heeft twee commits gedaan op de topic branch die ze zojuist gepusht heeft, dan kan ze dit uitvoeren:
450
+
451
+ $ git request-pull origin/master myfork
452
+ The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40:
453
+ John Smith (1):
454
+ added a new function
455
+
456
+ are available in the git repository at:
457
+
458
+ git://githost/simplegit.git featureA
459
+
460
+ Jessica Smith (2):
461
+ add limit to log function
462
+ change log output to 30 from 25
463
+
464
+ lib/simplegit.rb | 10 +++++++++-
465
+ 1 files changed, 9 insertions(+), 1 deletions(-)
466
+
467
+ De uitvoer kan naar de beheerders gestuurd worden: het vertelt ze waar het werk vanaf gebranched is, vat de commits samen en vertelt waar vandaan ze dit werk kunnen pullen.
468
+
469
+ Bij een project waarvan je niet de beheerder bent, is het over het algemeen eenvoudiger om een branch zoals `master` altijd de `origin/master` te laten tracken, en je werk te doen in topic branches die je eenvoudig weg kunt gooien als ze geweigerd worden. Als je je werkthema's gescheiden houdt in topic branches maakt dat het ook eenvoudiger voor jou om je werk te rebasen als de punt van de hoofd-repository in de tussentijd verschoven is en je commits niet langer netjes toegepast kunnen worden. Bijvoorbeeld, als je een tweede onderwerp wilt bijdragen aan een project, ga dan niet verder werken op de topic branch die je zojuist gepusht hebt - begin opnieuw vanaf de `master` branch van het hoofd repository:
470
+
471
+ $ git checkout -b featureB origin/master
472
+ $ (work)
473
+ $ git commit
474
+ $ git push myfork featureB
475
+ $ (email maintainer)
476
+ $ git fetch origin
477
+
478
+ Nu zijn al je onderwerpen opgeslagen in een silo - vergelijkbaar met een patch reeks (queue) - die je kunt herschrijven, rebasen en wijzigen zonder dat de onderwerpen elkaar beïnvloeden of van elkaar afhankelijk zijn zoals in Figuur 5-16.
479
+
480
+ Insert 18333fig0516.png
481
+ Figuur 5-16. Initiële commit historie met werk van featureB.
482
+
483
+ Stel dat de project-beheerder een verzameling andere patches binnengehaald heeft en jouw eerste branch geprobeerd heeft, maar dat die niet meer netjes merged. In dat geval kun je proberen die branch te rebasen op `origin/master`, de conflicten op te lossen voor de beheerder, en dan je wijzigingen opnieuw aanbieden:
484
+
485
+ $ git checkout featureA
486
+ $ git rebase origin/master
487
+ $ git push -f myfork featureA
488
+
489
+ Dit herschrijft je geschiedenis zodat die eruit ziet als in Figuur 5-17.
490
+
491
+ Insert 18333fig0517.png
492
+ Figuur 5-17. Commit historie na werk van featureA.
493
+
494
+ Omdat je de branch gerebased hebt, moet je de `-f` specificeren met je push commando om in staat te zijn de `featureA` branch op de server te vervangen met een commit die er geen afstammeling van is. Een alternatief zou zijn dit nieuwe werk naar een andere branch op de server te pushen (misschien `featureAv2` genaamd).
495
+
496
+ Laten we eens kijken naar nog een mogelijk scenario: de beheerder heeft je werk bekeken in je tweede branch en vind het concept goed, maar zou willen dat je een implementatie detail verandert. Je moet deze gelegenheid meteen gebruiken om het werk te baseren op de huidige `master` branch van het project. Je begint een nieuwe branch gebaseerd op de huidige `origin/master` branch, squashed de `featureB` wijzigingen er naartoe, lost conflicten op, doet de implementatie wijziging en pusht deze terug als een nieuwe branch:
497
+
498
+ $ git checkout -b featureBv2 origin/master
499
+ $ git merge --no-commit --squash featureB
500
+ $ (change implementation)
501
+ $ git commit
502
+ $ git push myfork featureBv2
503
+
504
+ De `--squash` optie pakt al het werk op de gemergde branch en perst dat samen in één non-merge commit bovenop de branch waar je op zit. De `--no-commit` optie vertelt Git dat hij niet automatisch een commit moet doen. Dit stelt je in staat om alle wijzigingen van een andere branch te introduceren en dan meer wijzigingen te doen, alvorens de nieuwe commit te doen.
505
+
506
+ Je kunt de beheerder nu een bericht sturen dat je de gevraagde wijzigingen gemaakt hebt en dat ze die wijzigingen kunnen vinden in je `featureBv2` branch (zie Figuur 5-18).
507
+
508
+ Insert 18333fig0518.png
509
+ Figuur 5-18. Commit historie na het featureBv2 werk.
510
+
511
+ ### Openbaar groot project ###
512
+
513
+ Veel grote projecten hebben vastgestelde procedures voor het accepteren van patches - je zult de specifieke regels voor ieder project goed moeten bekijken, omdat ze verschillend zullen zijn. Veel grote projecten accepteren patches veelal via ontwikkelaar-maillijsten, daarom zal ik zo'n voorbeeld nu laten zien.
514
+
515
+ De workflow is vergelijkbaar met het vorige geval - je maakt topic branches voor iedere patch waar je aan werkt. Het verschil is hoe je die aanlevert bij het project. In plaats van het project te forken en naar je eigen schrijfbare versie te pushen, genereer je e-mail versies van iedere reeks commits en mailt die naar de ontwikkelaar-maillijst:
516
+
517
+ $ git checkout -b topicA
518
+ $ (work)
519
+ $ git commit
520
+ $ (work)
521
+ $ git commit
522
+
523
+ Nu heb je twee commits die je wil sturen naar de maillijst. Je gebruikt `git format-patch` om de mbox-geformatteerde bestanden te genereren die je kunt mailen naar de lijst. Dit vormt iedere commit om naar een e-mail bericht met de eerste regel van het commit bericht als het onderwerp, en de rest van het bericht plus de patch die door de commit wordt geïntroduceerd als de inhoud. Het prettige hieraan is dat met het toepassen van een patch uit een mail die gegenereerd is met `format-patch` alle commit informatie blijft behouden. In de volgende paragraaf zal je hiervan meer zien, als je deze commits gaat toepassen:
524
+
525
+ $ git format-patch -M origin/master
526
+ 0001-add-limit-to-log-function.patch
527
+ 0002-changed-log-output-to-30-from-25.patch
528
+
529
+ Het `format-patch` commando drukt de namen af van de patch bestanden die het maakt. De `-M` optie vertelt Git te kijken naar hernoemingen. De bestanden komen er uiteindelijk zo uit te zien:
530
+
531
+ $ cat 0001-add-limit-to-log-function.patch
532
+ From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
533
+ From: Jessica Smith <jessica@example.com>
534
+ Date: Sun, 6 Apr 2008 10:17:23 -0700
535
+ Subject: [PATCH 1/2] add limit to log function
536
+
537
+ Limit log functionality to the first 20
538
+
539
+ ---
540
+ lib/simplegit.rb | 2 +-
541
+ 1 files changed, 1 insertions(+), 1 deletions(-)
542
+
543
+ diff --git a/lib/simplegit.rb b/lib/simplegit.rb
544
+ index 76f47bc..f9815f1 100644
545
+ --- a/lib/simplegit.rb
546
+ +++ b/lib/simplegit.rb
547
+ @@ -14,7 +14,7 @@ class SimpleGit
548
+ end
549
+
550
+ def log(treeish = 'master')
551
+ - command("git log #{treeish}")
552
+ + command("git log -n 20 #{treeish}")
553
+ end
554
+
555
+ def ls_tree(treeish = 'master')
556
+ --
557
+ 1.6.2.rc1.20.g8c5b.dirty
558
+
559
+ Je kunt deze patch bestanden ook aanpassen om meer informatie, die je niet in het commit bericht wilt laten verschijnen, voor de maillijst toe te voegen . Als je tekst toevoegt tussen de `---` regel en het begin van de patch (de `lib/simplegit.rb` regel), dan kunnen ontwikkelaars dit lezen, maar tijdens het toepassen van de patch wordt dit weggelaten.
560
+
561
+ Om dit te mailen naar een maillijst, kan je het bestand in je mail-applicatie plakken of het sturen via een commandoregel programma. Het plakken van de tekst veroorzaakt vaak formaterings problemen, in het bijzonder bij "slimmere" clients die de newlines en andere witruimte niet juist behouden. Gelukkig levert Git een gereedschap die je helpt om juist geformatteerde patches via IMAP te versturen, wat het alweer een stuk makkelijker voor je maakt. Ik zal zal je laten zien hoe je een patch via Gmail stuurt, wat de mail-applicatie is die ik toevallig gebruik. Je kunt gedetailleerde instructies voor een aantal mail programma's vinden aan het eind van het voornoemde `Documentation/SubmittingPatches` bestand in de Git broncode.
562
+
563
+ Eerst moet je de imap sectie in je `~/.gitconfig` bestand instellen. Je kunt iedere waarde apart instellen met een serie `git config` commando's, of je kunt ze handmatig toevoegen, maar uiteindelijk moet je config bestand er ongeveer zo uitzien:
564
+
565
+ [imap]
566
+ folder = "[Gmail]/Drafts"
567
+ host = imaps://imap.gmail.com
568
+ user = user@gmail.com
569
+ pass = p4ssw0rd
570
+ port = 993
571
+ sslverify = false
572
+
573
+ Als je IMAP server geen SSL gebruikt, zijn de laatste twee regels waarschijnlijk niet nodig, en de waarde voor host zal `imap://` zijn in plaats van `imaps://`.
574
+ Als dat ingesteld is, kun je `git send-email` gebruiken om de patch reeks in de Drafts map van de gespecificeerde IMAP server te zetten:
575
+
576
+ $ cat *.patch |git imap-send
577
+ Resolving imap.gmail.com... ok
578
+ Connecting to [74.125.142.109]:993... ok
579
+ Logging in...
580
+ sending 2 messages
581
+ 100% (2/2) done
582
+
583
+ Nu kan je naar jouw Drafts folder gaan, het To veld wijzigen naar de maillijst waar je de patch naartoe stuurt en misschien de beheerder of verantwoordelijke voor dat deel in de CC zetten en dan versturen.
584
+
585
+ Je kunt de patches ook via een SMTP server sturen. Zoals eerder kan je elke waarde apart instellen met een serie `git config` commando's, of je kunt ze handmatig in de sendmail sectie in je `~/.gitconfig` bestand zetten:
586
+
587
+ [sendemail]
588
+ smtpencryption = tls
589
+ smtpserver = smtp.gmail.com
590
+ smtpuser = user@gmail.com
591
+ smtpserverport = 587
592
+
593
+ Als dit gedaan is, kan je `git send-email` gebruiken om je patches te sturen:
594
+
595
+ $ git send-email *.patch
596
+ 0001-added-limit-to-log-function.patch
597
+ 0002-changed-log-output-to-30-from-25.patch
598
+ Who should the emails appear to be from? [Jessica Smith <jessica@example.com>]
599
+ Emails will be sent from: Jessica Smith <jessica@example.com>
600
+ Who should the emails be sent to? jessica@example.com
601
+ Message-ID to be used as In-Reply-To for the first email? y
602
+
603
+ Dan spuuwt Git een bergje log-informatie uit voor elke patch die je stuurt, wat er ongeveer zo uitziet:
604
+
605
+ (mbox) Adding cc: Jessica Smith <jessica@example.com> from
606
+ \line 'From: Jessica Smith <jessica@example.com>'
607
+ OK. Log says:
608
+ Sendmail: /usr/sbin/sendmail -i jessica@example.com
609
+ From: Jessica Smith <jessica@example.com>
610
+ To: jessica@example.com
611
+ Subject: [PATCH 1/2] added limit to log function
612
+ Date: Sat, 30 May 2009 13:29:15 -0700
613
+ Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com>
614
+ X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty
615
+ In-Reply-To: <y>
616
+ References: <y>
617
+
618
+ Result: OK
619
+
620
+ ### Samenvatting ###
621
+
622
+ In dit hoofdstuk is een aantal veel voorkomende workflows behandeld, die je kunt gebruiken om te kunnen werken in een aantal zeer verschillende typen Git projecten die je misschien zult tegenkomen. En er zijn een aantal nieuwe gereedschappen geïntroduceerd die je helpen om dit proces te beheren. Wat hierna volgt zal je laten zien hoe je aan de andere kant van de tafel werkt: een Git project beheren. Je zult leren hoe een welwillende dictator of integratie manager te zijn.
623
+
624
+ ## Het beheren van een project ##
625
+
626
+ Naast weten hoe effectief bij te dragen aan een project, moet je waarschijnlijk ook moeten weten hoe je er een beheert. Dit kan bestaan uit het accepteren en toepassen van patches die met `format-patch` gemaakt en naar je gemaild zijn, of het integreren van wijzigingen in de remote branches van repositories die je hebt toegevoegd als remotes van je project. Of je nu een canonieke repository beheert, of wilt bijdragen door het controleren of goedkeuren van patches, je moet weten hoe werk te ontvangen op een zodanige manier die het duidelijkst is voor andere bijdragers en voor jou op langere termijn vol te houden.
627
+
628
+ ### Werken in topic branches ###
629
+
630
+ Als je overweegt om nieuw werk te integreren, is het over het algemeen een goed idee om het uit te proberen in een topic branch - een tijdelijke branch, speciaal gemaakt om dat nieuwe werk uit te proberen. Op deze manier is het handig om een patch individueel te behandelen en het even opzij te zetten als het niet werkt, totdat je tijd hebt om er op terug te komen. Als je een eenvoudige branchnaam maakt, gebaseerd op het onderwerp van het werk dat je aan het proberen bent, bijvoorbeeld `ruby_client` of zoiets beschrijvends, dan is het makkelijk om te herinneren als je het voor een tijdje opzij legt en er later op terug komt. De beheerder van het Git project heeft de neiging om deze branches ook van een naamsruimte (namespace) te voorzien - zoals `sc/ruby_client`, waarbij `sc` een afkorting is van de persoon die het werk heeft bijgedragen.
631
+ Zoals je je zult herinneren, kun je de branch gebaseerd op je master branch zo maken:
632
+
633
+ $ git branch sc/ruby_client master
634
+
635
+ Of, als je er ook meteen naar wilt omschakelen, kun je de `checkout -b` optie gebruiken:
636
+
637
+ $ git checkout -b sc/ruby_client master
638
+
639
+ Nu ben je klaar om het bijgedragen werk in deze topic branch toe te voegen, en te bepalen of je het wilt mergen in je meer permanente branches.
640
+
641
+ ### Patches uit e-mail toepassen ###
642
+
643
+ Als je een patch per e-mail ontvangt, en je moet die integreren in je project, moet je de patch in je topic branch toepassen om het te evalueren. Er zijn twee manieren om een gemailde patch toe te passen: met `git apply` of met `git am`.
644
+
645
+ #### Een patch toepassen met apply ####
646
+
647
+ Als je de patch ontvangen hebt van iemand die het gegenereerd heeft met de `git diff` of een Unix `diff` commando, kun je het toepassen met het `git apply` commando. Aangenomen dat je de patch als `/tmp/patch-ruby-client.patch` opgeslagen hebt, kun je de patch als volgt toepassen:
648
+
649
+ $ git apply /tmp/patch-ruby-client.patch
650
+
651
+ Dit wijzigt de bestanden in je werk directory. Het is vrijwel gelijk aan het uitvoeren van een `patch -p1` commando om de patch toe te passen, alhoewel het meer paranoïde is en minder "fuzzy matches" accepteert dan patch. Het handelt ook het toevoegen, verwijderen, en hernoemen van bestanden af als ze beschreven staan in het `git diff` formaat, wat `patch` niet doet. Als laatste volgt `git apply` een "pas alles toe of laat alles weg" model waarbij alles of niets wordt toegepast. Dit in tegenstelling tot `patch` die gedeeltelijke patches kan toepassen, waardoor je werkdirectory in een vreemde status achterblijft. Over het algemeen is `git apply` meer paranoïde dan `patch`. Het zal geen commit voor je aanmaken: na het uitvoeren moet je de geïntroduceerde wijzigingen handmatig stagen en committen.
652
+
653
+ Je kunt ook `git apply` gebruiken om te zien of een patch netjes kan worden toepast voordat je het echt doet; je kunt `git apply --check` uitvoeren met de patch:
654
+
655
+ $ git apply --check 0001-seeing-if-this-helps-the-gem.patch
656
+ error: patch failed: ticgit.gemspec:1
657
+ error: ticgit.gemspec: patch does not apply
658
+
659
+ Als er geen uitvoer is, dan zou de patch netjes moeten passen. Dit commando retourneert ook een niet-nul status als de controle faalt, zodat je het kunt gebruiken in scripts als je dat zou willen.
660
+
661
+ #### Een patch met am toepassen ####
662
+
663
+ Als de bijdrager een Git gebruiker is en zo vriendelijk is geweest om het `format-patch` commando te gebruiken om de patch te genereren, dan is je werk eenvoudiger omdat de patch de auteur informatie en een commit bericht voor je bevat. Als het enigzins kan, probeer dan je bijdragers aan te moedigen om `format-patch` te gebruiken in plaats van `diff` om patches te genereren voor je. Je zou alleen `git apply` willen hoeven te gebruiken voor oude patches en dat soort dingen.
664
+
665
+ Om een patch gegenereerd met `format-patch` toe te passen, gebruik je `git am`. Technisch is `git am` gemaakt om een mbox bestand te lezen, dat een eenvoudig gewone platte tekstformaat is om één of meer e-mail berichten in een tekstbestand op te slaan. Het ziet er ongeveer zo uit:
666
+
667
+ From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
668
+ From: Jessica Smith <jessica@example.com>
669
+ Date: Sun, 6 Apr 2008 10:17:23 -0700
670
+ Subject: [PATCH 1/2] add limit to log function
671
+
672
+ Limit log functionality to the first 20
673
+
674
+ Dit is het begin van de uitvoer van het format-patch commando dat je gezien hebt in de vorige paragraaf. Dit is ook een geldig mbox e-mail formaat. Als iemand jou de patch correct gemaild heeft door gebruik te maken van `git send-email` en je downloadt dat in een mbox formaat, dan kan je het `git am` naar dat mbox bestand verwijzen, en het zal beginnen met alle patches die het tegenkomt toe te passen. Als je een mail client gebruikt die meerdere e-mails kan opslaan in mbox formaat, dan kun je hele reeksen patches in een bestand opslaan en dan `git am` gebruiken om ze één voor één toe te passen.
675
+
676
+ Maar, als iemand een patch bestand heeft geüpload die gegenereerd is met `format-patch` naar een ticket systeem of zoiets, kun je het bestand lokaal opslaan en dan dat opgeslagen bestand aan `git am` doorgeven om het te applyen:
677
+
678
+ $ git am 0001-limit-log-function.patch
679
+ Applying: add limit to log function
680
+
681
+ Je ziet dat het netjes is toegepast, en automatisch een nieuwe commit voor je heeft aangemaakt. De auteursinformatie wordt gehaald uit de `From` en `Date` velden in de kop, en het bericht van de commit wordt gehaald uit de `Subject` en de inhoud (voor de patch) uit het mailbericht zelf. Bijvoorbeeld, als deze patch was toegepast van het mbox voorbeeld dat ik zojuist getoond heb, dan zou de gegenereerde commit er ongeveer zo uit zien:
682
+
683
+ $ git log --pretty=fuller -1
684
+ commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
685
+ Author: Jessica Smith <jessica@example.com>
686
+ AuthorDate: Sun Apr 6 10:17:23 2008 -0700
687
+ Commit: Scott Chacon <schacon@gmail.com>
688
+ CommitDate: Thu Apr 9 09:19:06 2009 -0700
689
+
690
+ add limit to log function
691
+
692
+ Limit log functionality to the first 20
693
+
694
+ De `Commit` informatie toont de persoon die de patch toegepast heeft en de tijd waarop het is toegepast. De `Author` informatie de persoon die de patch oorspronkelijk gemaakt heeft en wanneer het gemaakt is.
695
+
696
+ Maar het is mogelijk dat de patch niet netjes toegepast kan worden. Misschien is jouw hoofdbranch te ver afgeweken van de branch waarop de patch gebouwd is, of is de patch afhankelijk van een andere patch, die je nog niet hebt toegepast. In dat geval zal het `git am` proces falen en je vragen wat je wilt doen:
697
+
698
+ $ git am 0001-seeing-if-this-helps-the-gem.patch
699
+ Applying: seeing if this helps the gem
700
+ error: patch failed: ticgit.gemspec:1
701
+ error: ticgit.gemspec: patch does not apply
702
+ Patch failed at 0001.
703
+ When you have resolved this problem run "git am --resolved".
704
+ If you would prefer to skip this patch, instead run "git am --skip".
705
+ To restore the original branch and stop patching run "git am --abort".
706
+
707
+ Dit commando zet conflict markeringen in alle bestanden waar het problemen mee heeft, net zoals een conflicterende merge of rebase operatie. Je lost dit probleem op een vergelijkbare manier op: wijzig het bestand om het conflict op te lossen, stage het bestand en voer dan `git am --resolved` uit om door te gaan met de volgende patch:
708
+
709
+ $ (fix the file)
710
+ $ git add ticgit.gemspec
711
+ $ git am --resolved
712
+ Applying: seeing if this helps the gem
713
+
714
+ Als je wilt dat Git iets meer intelligentie toepast om het conflict op te lossen, kun je een `-3` optie eraan meegeven, dit zorgt ervoor dat Git een driewegs-merge probeert. Deze optie staat standaard niet aan omdat het niet werkt als de commit waarvan de patch zegt dat het op gebaseerd is niet in je repository zit. Als je die commit wel hebt - als de patch gebaseerd was op een publieke commit - dan is de `-3` over het algemeen veel slimmer in het toepassen van een conflicterende patch:
715
+
716
+ $ git am -3 0001-seeing-if-this-helps-the-gem.patch
717
+ Applying: seeing if this helps the gem
718
+ error: patch failed: ticgit.gemspec:1
719
+ error: ticgit.gemspec: patch does not apply
720
+ Using index info to reconstruct a base tree...
721
+ Falling back to patching base and 3-way merge...
722
+ No changes -- Patch already applied.
723
+
724
+ In dit geval, probeerde ik een patch te applyen die ik al eerder toegepast had. Zonder de `-3` optie ziet het eruit als een conflict.
725
+
726
+ Als je een aantal patches van een mbox toepast, kun je ook het `am` commando in een interactieve modus uitvoeren, wat bij iedere patch die het vind stopt en je vraagt of je het wilt applyen:
727
+
728
+ $ git am -3 -i mbox
729
+ Commit Body is:
730
+ --------------------------
731
+ seeing if this helps the gem
732
+ --------------------------
733
+ Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all
734
+
735
+ Dit is prettig als je een aantal patches bewaard hebt, omdat je de patch eerst kunt zien als je niet kunt herinneren wat het is, of de patch niet wilt toepassen omdat je dat al eerder gedaan hebt.
736
+
737
+ Als alle patches voor je topic branch zijn toegepast en gecommit zijn op je branch, kan je besluiten of en hoe ze te integreren in een branch met een langere looptijd.
738
+
739
+ ### Remote branches uitchecken ###
740
+
741
+ Als je bijdrage van een Git gebruiker komt die zijn eigen repository opgezet heeft, een aantal patches daarin gepusht heeft, en jou de URL naar de repository gestuurd heeft en de naam van de remote branch waarin de wijzigingen zitten, kan je ze toevoegen als een remote en het mergen lokaal doen.
742
+
743
+ Bijvoorbeeld, als Jessica je een e-mail stuurt waarin staat dat ze een prachtig mooie nieuwe feature in de `ruby-client` branch van haar repository heeft, kun je deze testen door de remote toe te voegen en die branch lokaal te bekijken:
744
+
745
+ $ git remote add jessica git://github.com/jessica/myproject.git
746
+ $ git fetch jessica
747
+ $ git checkout -b rubyclient jessica/ruby-client
748
+
749
+ Als ze je later opnieuw mailt met een andere branch die weer een andere mooie feature bevat, dan kun je die ophalen en bekijken omdat je de remote al ingesteld hebt.
750
+
751
+ Dit is meest practisch als je vaak met een persoon werkt. Als iemand een enkele patch eens in de zoveel tijd bij te dragen heeft, dan is het accepteren per mail misschien minder tijdrovend dan te eisen dat iedereen hun eigen server moet beheren, en daarna voortdurend remotes te moeten toevoegen en verwijderen voor die paar patches. Je zult daarbij waarschijnlijk ook niet honderden remotes willen hebben, elk voor iemand die maar een patch of twee bijdraagt. Aan de andere kant, scripts en gehoste diensten maken het wellicht eenvoudiger; het hangt sterk af van de manier waarop ontwikkelt en hoe je bijdragers ontwikkelen.
752
+
753
+ Het andere voordeel van deze aanpak is dat je de historie van de commits ook krijgt. Alhoewel je misschien terechte merge problemen hebt, weet je op welk punt in de historie hun werk is gebaseerd; een echte drieweg merge is de standaard in plaats van een `-3` te moeten meegeven en hopen dat de patch gegenereerd was van een publieke commit waar je toegang toe hebt.
754
+
755
+ Als je maar af en toe met een persoon werkt, maar toch op deze manier van hen wilt pullen, dan kun je de URL van de remote repository geven aan het `git pull` commando. Dit doet een eenmalig pull en bewaart de URL niet als een remote referentie:
756
+
757
+ $ git pull git://github.com/onetimeguy/project.git
758
+ From git://github.com/onetimeguy/project
759
+ * branch HEAD -> FETCH_HEAD
760
+ Merge made by recursive.
761
+
762
+ ### Bepalen wat geïntroduceerd wordt ###
763
+
764
+ Je hebt een topic branch dat bijgedragen werk bevat. Nu kan je besluiten wat je er mee wilt doen. Deze paragraaf behandelt een paar commando's nogmaals om te laten zien hoe je ze kunt gebruiken om precies te reviewen wat je zult introduceren als je dit merged in je hoofd branch.
765
+
766
+ Het is vaak handig om een review te krijgen van alle commits die in deze branch zitten, maar die niet in je master branch zitten. Je kunt commits weglaten die al in de master branch zitten door de `--not` optie mee te geven voor de branch naam. Bijvoorbeeld, als je bijdrager je twee patches stuurt, je hebt een branch genaamd `contrib` gemaakt en hebt die patches daar toegepast, dan kun je dit uitvoeren:
767
+
768
+ $ git log contrib --not master
769
+ commit 5b6235bd297351589efc4d73316f0a68d484f118
770
+ Author: Scott Chacon <schacon@gmail.com>
771
+ Date: Fri Oct 24 09:53:59 2008 -0700
772
+
773
+ seeing if this helps the gem
774
+
775
+ commit 7482e0d16d04bea79d0dba8988cc78df655f16a0
776
+ Author: Scott Chacon <schacon@gmail.com>
777
+ Date: Mon Oct 22 19:38:36 2008 -0700
778
+
779
+ updated the gemspec to hopefully work better
780
+
781
+ Om te zien welke wijzigingen door een commit worden geïntroduceerd, onthoud dan dat je de `-p` optie kunt meegeven aan `git log` en dan zal het de geïntroduceerde diff erachter plakken bij iedere commit.
782
+
783
+ Om een volledige diff te zien van wat zou gebeuren als je deze topic branch merged met een andere branch, zul je misschien een vreemde truc moeten toepassen om de juiste resultaten te krijgen. Je zult misschien denken om dit uit te voeren:
784
+
785
+ $ git diff master
786
+
787
+ Dit commando geeft je een diff, maar het kan misleidend zijn. Als je `master` branch vooruit geschoven is sinds je de topic branch er vanaf hebt gemaakt, dan zul je ogenschijnlijk vreemde resultaten krijgen. Dit gebeurt omdat Git de snapshots van de laatste commit op de topic branch waar je op zit vergelijkt met het laatste snapshot van de `master` branch. Bijvoorbeeld, als je een regel in een bestand hebt toegevoegd op de `master` branch, dan zal een directe vergelijking van de snapshots eruit zien alsof de topic branch die regel gaat verwijderen.
788
+
789
+ Als `master` een directe voorganger is van je topic branch is dit geen probleem, maar als de twee histories uit elkaar zijn gegaan, zal de diff eruit zien alsof je alle nieuwe spullen in je topic branch toevoegt en al hetgeen wat alleen in de `master` branch staat weghaalt.
790
+
791
+ Wat je eigenlijk had willen zien zijn de wijzigingen die in de topic branch zijn toegevoegd: het werk dat je zult introduceren als je deze branch met master merged. Je doet dat door Git de laatste commit op je topic branch te laten vergelijken met de eerste gezamenlijke voorouder die het heeft met de master branch.
792
+
793
+ Technisch, kun je dat doen door de gezamenlijke voorouder op te zoeken en dan daar je diff op uit te voeren:
794
+
795
+ $ git merge-base contrib master
796
+ 36c7dba2c95e6bbb78dfa822519ecfec6e1ca649
797
+ $ git diff 36c7db
798
+
799
+ Maar, dat is niet handig, dus levert Git een andere verkorte manier om hetzelfde te doen: de driedubbele punt syntax. In de context van het `diff` commando, kun je drie punten achter een andere branch zetten om een `diff` te doen tussen de laatste commit van de branch waar je op zit en de gezamenlijke voorouder met een andere branch:
800
+
801
+ $ git diff master...contrib
802
+
803
+ Dit commando laat alleen het werk zien dat je huidige topic branch heeft geïntroduceerd sinds de gezamenlijke voorouder met master. Dat is een erg handige syntax om te onthouden.
804
+
805
+ ### Bijgedragen werk integreren ###
806
+
807
+ Als al het werk in je onderwerp branch klaar is om te worden geïntegreerd in een hogere branch, dan is de vraag hoe het te doen. En daarbij, welke workflow wil je gebruiken om je project te beheren? Je hebt een aantal keuzes, dus ik zal er een paar behandelen.
808
+
809
+ #### Mergende workflows ####
810
+
811
+ Een eenvoudige workflow merged je werk in de `master` branch. In dit scenario heb je een `master` branch die feitelijk de stabiele code bevat. Als je werk in een topic branch hebt waaraan je gewerkt hebt, of dat iemand anders heeft bijgedragen en je hebt dat nagekeken, dan merge je het in de master branch, verwijdert de topic branch en vervolgt het proces. Als we een repository hebben met werk in twee branches genaamd `ruby_client` en `php_client`, wat eruit ziet zoals Figuur 5-19 en mergen eerst `ruby_client` en daarna `php_client`, dan zal je historie er uit gaan zien zoals in Figuur 5-20.
812
+
813
+ Insert 18333fig0519.png
814
+ Figuur 5-19. Historie met een aantal topic branches.
815
+
816
+ Insert 18333fig0520.png
817
+ Figuur 5-20. Na het mergen van een topic branch.
818
+
819
+ Dat is waarschijnlijk de eenvoudigste workflow, maar het wordt problematisch als je werkt met grotere repositories of projecten.
820
+
821
+ Als je meer ontwikkelaars hebt of een groter project, dan zul je waarschijnlijk minstens een twee-fasen merge cyclus willen toepassen. In dat geval heb je twee langlopende branches, `master` en `develop`, waarbij je bepaalt dat `master` alleen vernieuwd wordt als een zeer stabiele release is gemaakt en alle nieuwe code geïntegreerd is in de `develop` branch. Je pusht beide branches op regelmatige basis naar de publieke repository. Iedere keer als je een nieuw topic branch hebt om te mergen (Figuur 5-21), merge je het in `develop` (Figuur 5-22). En als je een tag gemaakt heb van een release, doe je een fast-forward van `master` naar waar de nu stabiele `develop` branch is (Figuur 5-23).
822
+
823
+ Insert 18333fig0521.png
824
+ Figuur 5-21. Voor een merge van een topic branch.
825
+
826
+ Insert 18333fig0522.png
827
+ Figuur 5-22. Na een merge van een topic branch.
828
+
829
+ Insert 18333fig0523.png
830
+ Figuur 5-23. Na een release van een topic branch.
831
+
832
+ Op deze manier, als mensen de repository van je project clonen, dan kunnen ze kiezen om master uit checken en daarmee de laatste stabiele versie te bouwen en die eenvoudig up-to-date te houden, of ze kunnen develop uit checken waar het nieuwere materiaal in staat.
833
+ Je kunt dit concept ook verder doorvoeren, waarbij je een integratie branch hebt waar al het werk gemerged wordt. Als de codebasis op die branch stabiel is en de alle tests daar slagen, dan merge je het in een develop branch. Pas als het daar een periode stabiel is gebleken, dan fast-forward je de master branch.
834
+
835
+ #### workflows met grote merges ####
836
+
837
+ Het Git project heeft vier langlopende branches: `master`, `next`, en `pu` (proposed updates, voorgestelde vernieuwingen) voor nieuw spul, en `maint` voor onderhoudswerk (maintenance backports). Als nieuw werk wordt geïntroduceerd door bijdragers, wordt het samengeraapt in topic branches in de repository van de beheerder op een manier die lijkt op wat ik omschreven heb (zie Figuur 5-24). Hier worden de topics geëvalueerd om te bepalen of ze veilig zijn en klaar voor verdere verwerking of dat ze nog wat werk nodig hebben. Als ze veilig zijn, worden ze in `next` gemerged, en wordt die branch gepusht zodat iedereen de geïntegreerde topics kan uitproberen.
838
+
839
+ Insert 18333fig0524.png
840
+ Figuur 5-24. Een complexe serie van parallel bijgedragen topic branches beheren.
841
+
842
+ Als de topics nog werk nodig hebben, dan worden ze in plaats daarvan gemerged in `pu`. Zodra vastgesteld is dat ze helemaal stabiel zijn, dan worden de topics opnieuw gemerged in `master` en worden dan herbouwd van de topics die in `next` waren, maar nog niet gepromoveerd waren naar `master`. Dit betekent dat `master` vrijwel altijd vooruit beweegt, `next` eens in de zoveel tijd gerebased wordt, en `pu` nog vaker gerebased wordt (zie Figuur 5-25).
843
+
844
+ Insert 18333fig0525.png
845
+ Figuur 5-25. Bijgedragen topic branches mergen in langlopende integratie branches.
846
+
847
+ Als een onderwerp branch uiteindelijk is gemerged in `master`, dan wordt het verwijderd van de repository. Het Git project heeft ook een `maint` branch, die geforked is van de laatste release om teruggewerkte (backported) patches te leveren in het geval dat een onderhoudsrelease nodig is. Dus als je de Git repository cloned, dan heb je vier branches die je kunt uitchecken om het project in verschillende stadia van ontwikkeling te evalueren, afhankelijk van hoe nieuw je alles wilt hebben of hoe je wil bijdragen. En de beheerders hebben een gestructureerde workflow om ze te helpen nieuwe bijdragen aan de tand te voelen.
848
+
849
+ #### Rebasende en cherry pick workflows ####
850
+
851
+ Andere beheerders geven de voorkeur aan rebasen of bijgedragen werk te cherry picken naar hun master branch in plaats van ze erin te mergen, om een vrijwel lineaire historie te behouden. Als je werk in een topic branch hebt en hebt besloten dat je het wil integreren, dan ga je naar die branch en voert het rebase commando uit om de wijzigingen op je huidige master branch te baseren (of `develop`, enzovoorts). Als dat goed werkt, dan kun je de `master` branch fast-forwarden, en eindig je met een lineaire project historie.
852
+
853
+ De andere manier om geïntroduceerd werk van de ene naar de andere branch te verplaatsen is om het te cherry picken. Een cherry-pick in Git is een soort rebase voor een enkele commit. Het pakt de patch die was geïntroduceerd in een commit en probeert die weer toe te passen op de branch waar je nu op zit. Dit is handig als je een aantal commits op een topic branch hebt en je er slechts één van wilt integreren, of als je alleen één commit op een topic branch hebt en er de voorkeur aan geeft om het te cherry-picken in plaats van rebase uit te voeren. Bijvoorbeeld, stel dat je een project hebt dat eruit ziet als Figuur 5-26.
854
+
855
+ Insert 18333fig0526.png
856
+ Figuur 5-26. Voorbeeld historie voor een cherry pick.
857
+
858
+ Als je commit `e43a6` in je master branch wilt pullen, dan kun je dit uitvoeren
859
+
860
+ $ git cherry-pick e43a6fd3e94888d76779ad79fb568ed180e5fcdf
861
+ Finished one cherry-pick.
862
+ [master]: created a0a41a9: "More friendly message when locking the index fails."
863
+ 3 files changed, 17 insertions(+), 3 deletions(-)
864
+
865
+ Dit pulled dezelfde wijziging zoals geïntroduceerd in `e43a6`, maar je krijgt een nieuwe SHA-1 waarde, omdat de gegevens op een andere manier toegepast zijn. Nu ziet je historie eruit als Figuur 5-27.
866
+
867
+ Insert 18333fig0527.png
868
+ Figuur 5-27. Historie na het cherry-picken van een commit op een topic branch.
869
+
870
+ Nu kun je de topic branch verwijderen en de commits die je niet wilde pullen weggooien.
871
+
872
+ ### Je releases taggen ###
873
+
874
+ Als je hebt besloten om een release te maken, zul je waarschijnlijk een tag willen aanmaken zodat je die release op elk moment in de toekomst opnieuw kunt maken. Je kunt een nieuwe tag maken zoals ik heb beschreven in Hoofdstuk 2. Als je besluit om de tag als de beheerder te signeren, dan ziet het taggen er misschien zo uit:
875
+
876
+ $ git tag -s v1.5 -m 'my signed 1.5 tag'
877
+ You need a passphrase to unlock the secret key for
878
+ user: "Scott Chacon <schacon@gmail.com>"
879
+ 1024-bit DSA key, ID F721C45A, created 2009-02-09
880
+
881
+ Als je tags signeert, dan heb je misschien een problem om de publieke PGP sleutel, die gebruikt is om de tags te signeren, te distribueren. De beheerder van het Git project heeft dit probleem opgelost door hun publieke sleutel als een blob in de repository mee te nemen en een tag te maken die direct naar die inhoud wijst. Om dit te doen kun je uitvinden welke sleutel je wilt door `gpg --list-keys` uit te voeren:
882
+
883
+ $ gpg --list-keys
884
+ /Users/schacon/.gnupg/pubring.gpg
885
+ ---------------------------------
886
+ pub 1024D/F721C45A 2009-02-09 [expires: 2010-02-09]
887
+ uid Scott Chacon <schacon@gmail.com>
888
+ sub 2048g/45D02282 2009-02-09 [expires: 2010-02-09]
889
+
890
+ Daarna kun je de sleutel direct in de Git database importeren, door het te exporteren en te "pipen" naar `git hash-object`, wat een nieuwe blob schrijft in Git met die inhoud en je de SHA-1 van de blob teruggeeft:
891
+
892
+ $ gpg -a --export F721C45A | git hash-object -w --stdin
893
+ 659ef797d181633c87ec71ac3f9ba29fe5775b92
894
+
895
+ Nu je de inhoud van je sleutel in Git hebt, kun je een tag aanmaken die direct daar naar wijst door de nieuw SHA-1 waarde die het `hash-object` commando je gaf te specificeren:
896
+
897
+ $ git tag -a maintainer-pgp-pub 659ef797d181633c87ec71ac3f9ba29fe5775b92
898
+
899
+ Als je `git push --tags` uitvoert, zal de `maintainer-pgp-pub` tag met iedereen gedeeld worden. Als iemand een tag wil verifiëren, dan kunnen ze jouw PGP sleutel direct importeren door de blob direct uit de database te halen en het in GPG te importeren:
900
+
901
+ $ git show maintainer-pgp-pub | gpg --import
902
+
903
+ Ze kunnen die sleutel gebruiken om al je gesigneerde tags te verifiëren. Als je instructies in het tag bericht zet, dan zal `git show <tag>` je eindgebruikers meer specifieke instructies geven over tag verificatie.
904
+
905
+ ### Een bouw nummer genereren ###
906
+
907
+ Omdat Git geen monotoon oplopende nummers heeft zoals 'v123' of iets gelijkwaardigs om bij iedere commit mee te worden genomen, en je een voor mensen leesbare naam wilt hebben bij een commit, kan je `git describe` uitvoeren op die commit. Git geeft je de naam van de dichtstbijzijnde tag met het aantal commits achter die tag en een gedeeltelijke SHA-1 waarde van de commit die je omschrijft:
908
+
909
+ $ git describe master
910
+ v1.6.2-rc1-20-g8c5b85c
911
+
912
+ Op deze manier kun je een snapshot of "build" exporteren en het vernoemen naar iets dat begrijpelijk is voor mensen. Sterker nog: als je Git, gecloned van het Git repository, vanaf broncode gebouwd hebt geeft `git --version` je iets dat er zo uitziet. Als je een commit omschrijft die je direct getagged hebt, dan krijg je de tag naam.
913
+
914
+ Het `git describe` commando geeft beschreven tags de voorkeur (tags gemaakt met de `-a` of `-s` vlag), dus release tags moeten op deze manier aangemaakt worden als je `git describe` gebruikt, om er zeker van te zijn dat de commit juist benoemd wordt als het omschreven wordt. Je kunt deze tekst ook gebruiken als het doel van een checkout of show commando, alhoewel het afhankelijk is van de verkorte SHA-1 waarde aan het einde, dus het zou niet eeuwig geldig kunnen zijn. Bijvoorbeeld, de Linux kernel sprong recentelijk van 8 naar 10 karakters om er zeker van de zijn dat de SHA-1 uniek zijn, oudere `git describe` commando uitvoernamen werden daardoor ongeldig.
915
+
916
+ ### Een release voorbereiden ###
917
+
918
+ Nu wil je een build vrijgeven. Een van de dingen die je wilt doen is een archief maken van de laatste snapshot van je code voor de arme stumperds die geen Git gebruiken. Het commando om dit te doen is `git archive`:
919
+
920
+ $ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz
921
+ $ ls *.tar.gz
922
+ v1.6.2-rc1-20-g8c5b85c.tar.gz
923
+
924
+ Als iemand die tarball opent, dan krijgen ze de laatste snapshot van je project onder een project directory. Je kunt op vrijwel dezelfde manier ook een zip archief maken, maar dan door de `format=zip` optie mee te geven aan `git archive`:
925
+
926
+ $ git archive master --prefix='project/' --format=zip > `git describe master`.zip
927
+
928
+ Je hebt nu een mooie tarball en een zip archief van je project release, die je kunt uploaden naar je website of naar mensen kunt e-mailen.
929
+
930
+ ### De shortlog ###
931
+
932
+ De tijd is gekomen om de maillijst met mensen die willen weten wat er gebeurt in je project te mailen. Een prettige manier om een soort van wijzigingsverslag te krijgen van wat er is toegevoegd in je project sinds je laatste release of e-mail is om het `git shortlog` commando te gebruiken. Het vat alle commits samen binnen de grenswaarden die je het geeft. Bijvoorbeeld het volgende geeft je een samenvatting van alle commits sinds je vorige release, als je laatste release v1.0.1 heette:
933
+
934
+ $ git shortlog --no-merges master --not v1.0.1
935
+ Chris Wanstrath (8):
936
+ Add support for annotated tags to Grit::Tag
937
+ Add packed-refs annotated tag support.
938
+ Add Grit::Commit#to_patch
939
+ Update version and History.txt
940
+ Remove stray `puts`
941
+ Make ls_tree ignore nils
942
+
943
+ Tom Preston-Werner (4):
944
+ fix dates in history
945
+ dynamic version method
946
+ Version bump to 1.0.2
947
+ Regenerated gemspec for version 1.0.2
948
+
949
+ Je krijgt een opgeschoonde samenvatting van alle commits sinds v1.0.1, gegroepeerd op auteur, die je naar de lijst kunt e-mailen.
950
+
951
+ ## Samenvatting ##
952
+
953
+ Je zou je nu redelijk op je gemak moeten voelen om aan een project bij te dragen met Git, maar ook om je eigen project te beheren of de bijdragen van andere gebruikers te integreren. Gefeliciteerd, je bent nu een effectieve Git ontwikkelaar! In het volgende hoofdstuk vindt je nog krachtigere tools en tips om met complexe situaties om te gaan, waarmee je een echte Git meester zullen worden.