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,1177 @@
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
+ # Git tools #
38
+
39
+ Nu heb je de meeste commando's en werkwijzen geleerd die je dagelijks nodig hebt om een Git repository voor je broncode te beheren en te onderhouden. Je hebt de basistaken van het tracken en committen van bestanden onder de knie, en je hebt de kracht van de staging area en lichtgewicht topic branching en mergen in de vingers.
40
+
41
+ Nu ga je een aantal zeer krachtige dingen verkennen die Git voor je kan doen, die je niet per se dagelijks gebruikt, maar die je op een bepaald moment toch nodig kunt gaan hebben.
42
+
43
+ ## Revisie selectie ##
44
+
45
+ Git stelt je in staat om specifieke commits of een serie commits op diverse manieren te specificeren. Ze zijn niet meteen voor de hand liggend, maar behulpzaam om te weten.
46
+
47
+ ### Enkele revisies ###
48
+
49
+ Natuurlijk kun je naar een commit refereren met de SHA-1 hash die het toegekend is, maar er zijn ook meer mensvriendelijke manieren om naar een commit te refereren. In deze paragraaf worden diverse manieren getoond waarop je naar een enkele commit kunt refereren.
50
+
51
+ ### Korte SHA ###
52
+
53
+ Git is slim genoeg om uit te vinden welke commit je bedoelde te typen als je het de eerste paar karakters geeft, zolang je gedeeltelijke SHA-1 maar minstens vier karakters lang en ondubbelzinnig is; dat wil zeggen dat slechts één object in de huidige repository begint met die gedeeltelijke SHA-1.
54
+
55
+ Bijvoorbeeld, stel dat je om een specifieke commit te zien een `git log` commando uitvoert en de commit identificeert waarin je een bepaalde functionaliteit hebt toegevoegd:
56
+
57
+ $ git log
58
+ commit 734713bc047d87bf7eac9674765ae793478c50d3
59
+ Author: Scott Chacon <schacon@gmail.com>
60
+ Date: Fri Jan 2 18:32:33 2009 -0800
61
+
62
+ fixed refs handling, added gc auto, updated tests
63
+
64
+ commit d921970aadf03b3cf0e71becdaab3147ba71cdef
65
+ Merge: 1c002dd... 35cfb2b...
66
+ Author: Scott Chacon <schacon@gmail.com>
67
+ Date: Thu Dec 11 15:08:43 2008 -0800
68
+
69
+ Merge commit 'phedders/rdocs'
70
+
71
+ commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
72
+ Author: Scott Chacon <schacon@gmail.com>
73
+ Date: Thu Dec 11 14:58:32 2008 -0800
74
+
75
+ added some blame and merge stuff
76
+
77
+ Kies in dit geval `1c002dd....`. Als je op die commit `git show` uitvoert, dan zijn de volgende commando's gelijkwaardig (aangenomen dat de kortere versies ondubbelzinnig zijn):
78
+
79
+ $ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
80
+ $ git show 1c002dd4b536e7479f
81
+ $ git show 1c002d
82
+
83
+ Git kan met een korte unieke afkorting van een SHA-1 waarde uit de voeten. Als je `--abbrev-commit` meegeeft aan het `git log` commando, dan zal de output kortere waarden gebruiken maar ze uniek houden; het gebruikt standaard zeven karakters maar maakt ze langer indien nodig om de SHA-1 ondubbelzinnig te houden:
84
+
85
+ $ git log --abbrev-commit --pretty=oneline
86
+ ca82a6d changed the version number
87
+ 085bb3b removed unnecessary test code
88
+ a11bef0 first commit
89
+
90
+ Over het algemeen zijn acht tot tien karakters meer dan voldoende om binnen een project uniek te zijn. Een van de grootste Git projecten, de Linux kernel, begint 12 karakters van de mogelijke 40 nodig te hebben om uniek te blijven.
91
+
92
+ ### EEN KORTE NOTITIE OVER SHA-1 ###
93
+
94
+ Veel mensen beginnen bezorgd te raken dat ze op een bepaald moment door puur toeval, twee objecten in hun repository hebben die naar dezelfde SHA-1 waarde hashen. Wat dan?
95
+
96
+ Mocht je een object committen dat hashed naar dezelfde SHA-1 waarde als een vorig object in je repository, dan zal Git het vorige reeds aanwezige object in je Git database zien en aannemen dat het al geschreven was. Als je op een bepaald moment dat object opnieuw probeert uit te checken, dan zal je altijd de gegevens van het eerste object krijgen.
97
+
98
+ <!-- Vraag: weet iemand de officiéle term voor botsingswaarschijnlijkheid? Via de Engelse Wikipedia kom ik (via collision probability) op universal hashing, maar is de formule niet te zien. -->
99
+ Maar wat je moet beseffen is hoe vreselijk onwaarschijnlijk dit scenario is. De SHA-1 waarde is 20 bytes, oftewel 160 bits. Het aantal benodigde random gehashte objecten om een 50% waarschijnlijkheid van een botsing te garanderen is ongeveer 2^80 (de formule om botsingswaarschijnlijkheid te bepalen is `p = (n(n-1)/2) * (1/2^160)`). 2^80 is 1.2 x 10^24 of 1 miljoen miljard miljard. Dat is 1.200 keer het aantal zandkorrels op aarde.
100
+
101
+ Hier is een voorbeeld om je een idee te geven wat er voor nodig is om een SHA-1 botsing te krijgen. Als alle 6.5 miljard mensen op aarde zouden programmeren, en iedere seconde zou ieder van hen code genereren die gelijk was aan de hele Linux kernel-geschiedenis (1 miljoen Git objecten) en dat in één gigantische Git repository pushen, dan zou het vijf jaar duren voordat die repository genoeg objecten zou bevatten om een 50% waarschijnlijkheid van één enkele SHA-1 object botsing te krijgen. De kans is groter dat elk lid van je programmeerteam zal worden aangevallen en gedood door wolven bij ongerelateerde incidenten op dezelfde avond.
102
+
103
+ ### Branch referenties ###
104
+
105
+ De meest eenvoudige manier om een commit te specificeren heeft als voorwaarde dat je er een branchreferentie naar hebt wijzen. Dan kun je een branchnaam in ieder Git commando gebruiken dat een commitobject of SHA-1 waarde verwacht. Bijvoorbeeld, als je het laatste commitobject op een branch wil tonen, dan zijn de volgende commando's gelijkwaardig, aangenomen dat de `topic1` branch naar `ca82a6d` wijst:
106
+
107
+ $ git show ca82a6dff817ec66f44342007202690a93763949
108
+ $ git show topic1
109
+
110
+ Als je wilt zien naar welke specifieke SHA een branch wijst, of als je wil zien wat ieder van deze voorbeelden in termen van SHA's voorstellen, dan kun je een Git sanitaire voorzieningen (plumbing) tool genaamd `rev-parse` gebruiken. Je kunt in Hoofdstuk 9 kijken voor meer informatie over plumbingtools, eigenlijk is `rev-parse` er voor low-level operaties en is niet ontworpen voor dagelijks gebruik. Maar het kan behulpzaam zijn op momenten dat je moet zien wat er echt aan de hand is. Hier kun je `rev-parse` uitvoeren op je branch.
111
+
112
+ $ git rev-parse topic1
113
+ ca82a6dff817ec66f44342007202690a93763949
114
+
115
+ ### RefLog afkortingen ###
116
+
117
+ Een van de dingen die Git in de achtergrond doet terwijl jij lekker zit te werken is een reflog bijhouden: een log waarin is vastgelegd naar welke referenties de HEAD en de branches de laatste paar maanden hebben gewezen.
118
+
119
+ Je kunt je reflog zien door `git reflog` te gebruiken:
120
+
121
+ $ git reflog
122
+ 734713b HEAD@{0}: commit: fixed refs handling, added gc auto, updated
123
+ d921970 HEAD@{1}: merge phedders/rdocs: Merge made by recursive.
124
+ 1c002dd HEAD@{2}: commit: added some blame and merge stuff
125
+ 1c36188 HEAD@{3}: rebase -i (squash): updating HEAD
126
+ 95df984 HEAD@{4}: commit: # This is a combination of two commits.
127
+ 1c36188 HEAD@{5}: rebase -i (squash): updating HEAD
128
+ 7e05da5 HEAD@{6}: rebase -i (pick): updating HEAD
129
+
130
+ Iedere keer als de punt van je branch om een of andere reden is gewijzigd, dan bewaart Git die informatie voor je in deze tijdelijke geschiedenis. En je kunt ook oudere commits met deze gegevens specificeren. Als je de vijfde voorgaande waarde van de HEAD van je repository wilt zien, dan kun je de `@{n}` referentie gebruiken, die je in de reflog output kunt zien:
131
+
132
+ $ git show HEAD@{5}
133
+
134
+ Je kunt deze syntax ook gebruiken om te zien waar een branch een bepaalde tijd geleden was. Bijvoorbeeld, om te zien waar je `master` branch gisteren was, kun je dit typen
135
+
136
+ $ git show master@{yesterday}
137
+
138
+ Dat laat je zien waar de punt van de branch gisteren was. Deze techniek werkt alleen voor gegevens die nog steeds in je reflog staan, dus je kunt het niet gebruiken om te kijken naar commits die ouder zijn dan een paar maanden.
139
+
140
+ Om reflog informatie te zien, in hetzelfde formaat als de `git log` output, kun je `git log -g` uitvoeren:
141
+
142
+ $ git log -g master
143
+ commit 734713bc047d87bf7eac9674765ae793478c50d3
144
+ Reflog: master@{0} (Scott Chacon <schacon@gmail.com>)
145
+ Reflog message: commit: fixed refs handling, added gc auto, updated
146
+ Author: Scott Chacon <schacon@gmail.com>
147
+ Date: Fri Jan 2 18:32:33 2009 -0800
148
+
149
+ fixed refs handling, added gc auto, updated tests
150
+
151
+ commit d921970aadf03b3cf0e71becdaab3147ba71cdef
152
+ Reflog: master@{1} (Scott Chacon <schacon@gmail.com>)
153
+ Reflog message: merge phedders/rdocs: Merge made by recursive.
154
+ Author: Scott Chacon <schacon@gmail.com>
155
+ Date: Thu Dec 11 15:08:43 2008 -0800
156
+
157
+ Merge commit 'phedders/rdocs'
158
+
159
+ Het is belangrijk om op te merken dat deze informatie strikt lokaal is - het is een log van wat jij hebt gedaan in jouw repository. De referenties zullen niet hetzelfde zijn in de kopie van de repository die iemand anders gemaakt heeft; en meteen nadat je een eerste clone van een repository hebt gemaakt heb je een lege reflog, omdat er nog geen activiteit is geweest in je repository. `git show HEAD@{2.months.ago}` uitvoeren werkt alleen als je het project minstens twee maanden geleden gecloned hebt, als je het vijf minuten geleden gecloned hebt krijg je geen resultaten.
160
+
161
+ ### Voorouder referenties ###
162
+
163
+ De andere veelgebruikte manier om een commit te specificeren is via zijn voorouders. Als je een `^` aan het einde van een referentie zet, zal Git hieruit herleiden dat het de ouder van die commit betekent.
164
+ Stel dat je naar de geschiedenis van je project kijkt:
165
+
166
+ $ git log --pretty=format:'%h %s' --graph
167
+ * 734713b fixed refs handling, added gc auto, updated tests
168
+ * d921970 Merge commit 'phedders/rdocs'
169
+ |\
170
+ | * 35cfb2b Some rdoc changes
171
+ * | 1c002dd added some blame and merge stuff
172
+ |/
173
+ * 1c36188 ignore *.gem
174
+ * 9b29157 add open3_detach to gemspec file list
175
+
176
+ Dan zie je de vorige commit door `HEAD^` te specificeren, wat "de ouder van HEAD" betekent:
177
+
178
+ $ git show HEAD^
179
+ commit d921970aadf03b3cf0e71becdaab3147ba71cdef
180
+ Merge: 1c002dd... 35cfb2b...
181
+ Author: Scott Chacon <schacon@gmail.com>
182
+ Date: Thu Dec 11 15:08:43 2008 -0800
183
+
184
+ Merge commit 'phedders/rdocs'
185
+
186
+ Je kunt ook een getal na de `^` zetten, bijvoorbeeld `d921970^2` betekent "de tweede ouder van d921970." Deze syntax is alleen nuttig voor merge commits, omdat die meer dan één ouder hebben. De eerste ouder is de branch waar jij op was toen je mergede, en de andere is de commit op de branch die je gemerged hebt:
187
+
188
+ $ git show d921970^
189
+ commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
190
+ Author: Scott Chacon <schacon@gmail.com>
191
+ Date: Thu Dec 11 14:58:32 2008 -0800
192
+
193
+ added some blame and merge stuff
194
+
195
+ $ git show d921970^2
196
+ commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548
197
+ Author: Paul Hedderly <paul+git@mjr.org>
198
+ Date: Wed Dec 10 22:22:03 2008 +0000
199
+
200
+ Some rdoc changes
201
+
202
+ De andere manier om voorouders mee te specificeren is de `~`. Dit refereert ook naar de eerste ouder, dus `HEAD~` en `HEAD^` zijn gelijk. Het verschil wordt pas duidelijk als je een getal specificeert. `HEAD~2` betekent "de eerste ouder van de eerste ouder", of "de grootouder" - het doorloopt de eerste ouders het aantal keren dat je specificeert. Bijvoorbeeld, in de geschiedenis die eerder getoond werd, zou `HEAD~3` het volgende resultaat geven
203
+
204
+ $ git show HEAD~3
205
+ commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
206
+ Author: Tom Preston-Werner <tom@mojombo.com>
207
+ Date: Fri Nov 7 13:47:59 2008 -0500
208
+
209
+ ignore *.gem
210
+
211
+ Dit kan ook geschreven worden als `HEAD^^^` wat, nogmaals, de eerste ouder van de eerste ouder van de eerste ouder is:
212
+
213
+ $ git show HEAD^^^
214
+ commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
215
+ Author: Tom Preston-Werner <tom@mojombo.com>
216
+ Date: Fri Nov 7 13:47:59 2008 -0500
217
+
218
+ ignore *.gem
219
+
220
+ Je kunt deze syntaxen combineren: je kunt de tweede ouder van de vorige referentie krijgen (aangenomen dat het een merge commit was) door `HEAD~3^2` te gebruiken, enzovoort.
221
+
222
+ ### Commit reeksen ###
223
+
224
+ Nu je individuele commits kunt specificeren, laten we zien hoe je reeksen van commits kunt specificeren. Dit is vooral erg nuttig bij het beheren van je branches - als je veel branches hebt, kan je reeks-specificaties gebruiken om vragen te beantwoorden als: "Wat voor werk zit er op deze branch dat ik nog niet in mijn hoofdbranch gemerged heb?"
225
+
226
+ #### Dubbel-punt ####
227
+
228
+ De meest voorkomende reeks specificatie is de dubbel-punt syntax. Eigenlijk vraag je hiermee aan Git een reeks commits op te zoeken, die bereikbaar zijn van de ene commit maar niet vanuit een ander. Bijvoorbeeld, stel dat je een commit-geschiedenis hebt die eruit ziet zoals in Figuur 6-1.
229
+
230
+ Insert 18333fig0601.png
231
+ Figuur 6-1. Voorbeeldgeschiedenis voor reeks-selectie.
232
+
233
+ Je wilt zien wat er in je experimentele branch zit dat nog niet in je hoofdbranch gemerged is. Je kunt Git vragen om een log te tonen van alleen die commits met `master..experiment`, wat zoveel betekent als "alle commits die bereikbaar zijn voor experiment, die niet bereikbaar zijn voor master". Om de voorbeelden kort en duidelijk te houden zal ik de letters van de commitobjecten in het diagram gebruiken in plaats van de echte log output, in de volgorde waarin ze getoond zouden worden:
234
+
235
+ $ git log master..experiment
236
+ D
237
+ C
238
+
239
+ Als je echter het tegenovergestelde wilt zien - alle commits in `master` die niet in `experiment` zitten - dan moet je de branchnamen omdraaien. `experiment..master` toont je alles in `master` wat niet bereikbaar is vanuit `experiment`:
240
+
241
+ $ git log experiment..master
242
+ F
243
+ E
244
+
245
+ Dit is handig als je de `experiment` branch up to date wilt houden en alvast wilt zien wat je op het punt staat te mergen. Een ander veel voorkomend gebruik van deze syntax is zien wat je op het punt staat naar een remote de pushen:
246
+
247
+ $ git log origin/master..HEAD
248
+
249
+ Dit commando toont je alle commits in je huidige branch, die niet in de `master` branch op de remote `origin` zitten. Als je een `git push` uitvoert, en je huidige branch volgt de `origin/master`, dan zijn de commits die getoond worden door `git log origin/master..HEAD` de commits die verstuurd zullen worden naar de server.
250
+ Je kunt ook één kant van de syntax weglaten om Git de HEAD laten aannemen. Bijvoorbeeld, je krijgt dezelfde resultaten als in het vorige voorbeeld door `git log origin/master..` te typen - Git vult HEAD in als er één kant ontbreekt.
251
+
252
+ #### Dubbele punten ####
253
+
254
+ De syntax met de dubbel-punt is makkelijk als een afkorting, maar misschien wil je meer dan twee branches specificeren om je revisie aan te geven, zoals het zien welke commits in één van de branches in een reeks zitten, die nog niet in de branch zitten waar je nu op werkt. Git laat je dit doen door of het `^` karakter of `--not`, te gebruiken voor iedere referentie waarvan je de bereikbare commits niet wilt zien. Dus deze drie commando's zijn gelijk:
255
+
256
+ $ git log refA..refB
257
+ $ git log ^refA refB
258
+ $ git log refB --not refA
259
+
260
+ Dit is prettig omdat met deze syntax je meer dan twee referenties in je vraag kunt specificeren, wat je niet met de dubbel punt syntax kan doen. Bijvoorbeeld, als je alle commits wilt zien die bereikbaar zijn vanuit `refA` of `refB`, maar niet vanuit `refC`, dan kun je één van deze intypen:
261
+
262
+ $ git log refA refB ^refC
263
+ $ git log refA refB --not refC
264
+
265
+ Dit zorgt voor een erg krachtig revisie vraagsysteem dat je kan helpen om uit te zoeken wat in je branches zit.
266
+
267
+ #### Drievoudige punt ####
268
+
269
+ De laatste veelgebruikte reeks-selectie syntax is de drievoudige punt syntax, wat alle commits specificeert die bereikbaar zijn door één van de twee referenties, maar niet door allebei. Kijk nog eens naar de voorbeeld commitgeschiedenis in Figuur 6-1.
270
+ Als je wilt zien wat in je `master` of in je `experiment` zit, maar geen gedeelde referenties, dan kun je dit uitvoeren
271
+
272
+ $ git log master...experiment
273
+ F
274
+ E
275
+ D
276
+ C
277
+
278
+ Nogmaals, dit geeft je normale `log` output, maar toont je alleen de commit-informatie voor deze vier commits, getoond in de traditionele volgorde van committijdstip.
279
+
280
+ Een veelgebruikte optie bij het `log` command in dit geval is `--left-right`, wat je laat zien aan welke kant van de reeks elke commit zit. Dit helpt de data bruikbaarder te maken:
281
+
282
+ $ git log --left-right master...experiment
283
+ < F
284
+ < E
285
+ > D
286
+ > C
287
+
288
+ Met deze tools, kun je Git eenvoudiger laten weten welke commit of commits je wilt inspecteren.
289
+
290
+ ## Interactief stagen ##
291
+
292
+ Bij Git worden een aantal scripts geleverd, die sommige commandline taken makkelijker maken. Hier zul je een aantal interactieve commando's zien, die je kunnen helpen om je commits zo samen te stellen dat ze alleen bepaalde combinaties en delen van bestanden bevatten. Deze tools zijn erg nuttig als je een reeks bestanden aanpast en dan besluit dat je deze wijzigingen in een aantal gefocuste commits wilt hebben in plaats van één grote rommelige commit. Op deze manier ben je er zeker van dat je commits logische aparte wijzigingensets zijn en makkelijk gereviewed kunnen worden door je mede-ontwikkelaars.
293
+ Als je `git add` uitvoert met de `-i` of `--interactive` optie, dan schakelt Git over naar een interactieve shell modus, waarbij zoiets als dit getoond wordt:
294
+
295
+ $ git add -i
296
+ staged unstaged path
297
+ 1: unchanged +0/-1 TODO
298
+ 2: unchanged +1/-1 index.html
299
+ 3: unchanged +5/-1 lib/simplegit.rb
300
+
301
+ *** Commands ***
302
+ 1: status 2: update 3: revert 4: add untracked
303
+ 5: patch 6: diff 7: quit 8: help
304
+ What now>
305
+
306
+ Je kunt zien dat dit commando je een heel andere kijk op je staging area geeft - eigenlijk dezelfde informatie die je krijgt met het `git status` commando, maar dan compacter en meer informatief. Het toont links de wijzigingen die je gestaged hebt, en de niet gestagede wijzigingen rechts.
307
+
308
+ Hierna volgt een commando-sectie. Hier kun je een aantal dingen doen waaronder bestanden stagen, bestanden unstagen, delen van bestanden stagen, ungetrackte bestanden toevoegen, en diffs zien van wat gestaged is.
309
+
310
+ ### Bestanden stagen en unstagen ###
311
+
312
+ Als je `2` of `u` op de `What now>` prompt typt, dan vraagt het script welke bestanden je wilt stagen:
313
+
314
+ What now> 2
315
+ staged unstaged path
316
+ 1: unchanged +0/-1 TODO
317
+ 2: unchanged +1/-1 index.html
318
+ 3: unchanged +5/-1 lib/simplegit.rb
319
+ Update>>
320
+
321
+ Om de TODO en index.html bestanden te stagen, kun je de getallen typen:
322
+
323
+ Update>> 1,2
324
+ staged unstaged path
325
+ * 1: unchanged +0/-1 TODO
326
+ * 2: unchanged +1/-1 index.html
327
+ 3: unchanged +5/-1 lib/simplegit.rb
328
+ Update>>
329
+
330
+ De `*` naast ieder bestand geeft aan dat het bestand geselecteerd is om gestaged te worden. Als je Enter indrukt na niets getypt te hebben op de `Update>>` prompt, dan zal Git alles wat geselecteerd staat pakken en voor je stagen:
331
+
332
+ Update>>
333
+ updated 2 paths
334
+
335
+ *** Commands ***
336
+ 1: status 2: update 3: revert 4: add untracked
337
+ 5: patch 6: diff 7: quit 8: help
338
+ What now> 1
339
+ staged unstaged path
340
+ 1: +0/-1 nothing TODO
341
+ 2: +1/-1 nothing index.html
342
+ 3: unchanged +5/-1 lib/simplegit.rb
343
+
344
+ Nu kun je zien dat de TODO en index.html bestanden gestaged zijn, en het simplegit.rb bestand nog steeds unstaged is. Als je het TODO bestand nu wilt unstagen, dan gebruik je de `3` of `r` (voor revert) optie:
345
+
346
+ *** Commands ***
347
+ 1: status 2: update 3: revert 4: add untracked
348
+ 5: patch 6: diff 7: quit 8: help
349
+ What now> 3
350
+ staged unstaged path
351
+ 1: +0/-1 nothing TODO
352
+ 2: +1/-1 nothing index.html
353
+ 3: unchanged +5/-1 lib/simplegit.rb
354
+ Revert>> 1
355
+ staged unstaged path
356
+ * 1: +0/-1 nothing TODO
357
+ 2: +1/-1 nothing index.html
358
+ 3: unchanged +5/-1 lib/simplegit.rb
359
+ Revert>> [enter]
360
+ reverted one path
361
+
362
+ Als je nu nog eens naar je Git status kijkt, kun je zien dat je het TODO bestand ge-unstaged hebt:
363
+
364
+ *** Commands ***
365
+ 1: status 2: update 3: revert 4: add untracked
366
+ 5: patch 6: diff 7: quit 8: help
367
+ What now> 1
368
+ staged unstaged path
369
+ 1: unchanged +0/-1 TODO
370
+ 2: +1/-1 nothing index.html
371
+ 3: unchanged +5/-1 lib/simplegit.rb
372
+
373
+ Om de diff te zien van wat je gestaged hebt, kun je het `6` of `d` (voor diff) commando gebruiken. Het toont je een lijst van je gestagede bestanden, en je kunt de bestanden selecteren waarvan je de gestagede diff wilt zien. Dit is vergelijkbaar met het specificeren van `git diff --cached` op de commando regel:
374
+
375
+ *** Commands ***
376
+ 1: status 2: update 3: revert 4: add untracked
377
+ 5: patch 6: diff 7: quit 8: help
378
+ What now> 6
379
+ staged unstaged path
380
+ 1: +1/-1 nothing index.html
381
+ Review diff>> 1
382
+ diff --git a/index.html b/index.html
383
+ index 4d07108..4335f49 100644
384
+ --- a/index.html
385
+ +++ b/index.html
386
+ @@ -16,7 +16,7 @@ Date Finder
387
+
388
+ <p id="out">...</p>
389
+
390
+ -<div id="footer">contact : support@github.com</div>
391
+ +<div id="footer">contact : email.support@github.com</div>
392
+
393
+ <script type="text/javascript">
394
+
395
+ Met deze simpele commando's kun je de interactieve toevoegmodus gebruiken om op een iets eenvoudigere manier met je staging area om te gaan.
396
+
397
+ ### Patches stagen ###
398
+
399
+ Het is met Git ook mogelijk om bepaalde delen van bestanden te stagen en de rest niet. Bijvoorbeeld, als je twee wijzigingen maakt in je simplegit.rb bestand en één van die twee wilt stagen en de andere niet, dan is dat eenvoudig in Git. Vanaf de interactieve prompt, type `5` of `p` (voor patch). Git zal je vragen welke bestanden je deels wilt stagen en daarna, voor iedere sectie van de geselecteerde bestanden, zal het stukken van de bestandsdiff tonen en je vragen of je ze wilt stagen, één voor één:
400
+
401
+ diff --git a/lib/simplegit.rb b/lib/simplegit.rb
402
+ index dd5ecc4..57399e0 100644
403
+ --- a/lib/simplegit.rb
404
+ +++ b/lib/simplegit.rb
405
+ @@ -22,7 +22,7 @@ class SimpleGit
406
+ end
407
+
408
+ def log(treeish = 'master')
409
+ - command("git log -n 25 #{treeish}")
410
+ + command("git log -n 30 #{treeish}")
411
+ end
412
+
413
+ def blame(path)
414
+ Stage this hunk [y,n,a,d,/,j,J,g,e,?]?
415
+
416
+ Hier heb je erg veel opties. Door `?` te typen krijg je een lijst met wat je kunt doen:
417
+
418
+ Stage this hunk [y,n,a,d,/,j,J,g,e,?]? ?
419
+ y - stage this hunk
420
+ n - do not stage this hunk
421
+ a - stage this and all the remaining hunks in the file
422
+ d - do not stage this hunk nor any of the remaining hunks in the file
423
+ g - select a hunk to go to
424
+ / - search for a hunk matching the given regex
425
+ j - leave this hunk undecided, see next undecided hunk
426
+ J - leave this hunk undecided, see next hunk
427
+ k - leave this hunk undecided, see previous undecided hunk
428
+ K - leave this hunk undecided, see previous hunk
429
+ s - split the current hunk into smaller hunks
430
+ e - manually edit the current hunk
431
+ ? - print help
432
+
433
+ Over het algemeen zal je `y` of `n` typen als je elke homp (hunk) wilt stagen, maar voor bepaalde bestanden ze allemaal stagen, of voor een bepaalde hunk de beslissing uit stellen kan ook behulpzaam zijn. Als je een gedeelte van het bestand wilt stagen en een ander gedeelte unstaged wilt laten, dan zal je status output er zo uitzien:
434
+
435
+ What now> 1
436
+ staged unstaged path
437
+ 1: unchanged +0/-1 TODO
438
+ 2: +1/-1 nothing index.html
439
+ 3: +1/-1 +4/-0 lib/simplegit.rb
440
+
441
+ De status van het simplegit.rb bestand is interessant. Het laat zien dat een paar regels gestaged zijn, en een paar niet. Je hebt dit bestand deels gestaged. Nu kan je het interactieve toevoeg script verlaten en het `git commit` commando uitvoeren om de gedeeltelijk gestagede bestanden te committen.
442
+
443
+ Tot slot hoef je niet in de interactieve toevoeg modus te zijn om het gedeeltelijke bestands-stagen te doen, je kunt hetzelfde script starten door `git add -p` of `git add --patch` op de commando regel te gebruiken.
444
+
445
+ ## Stashen ##
446
+
447
+ Vaak, als je aan een deel van je project hebt zitten werken, zijn de dingen in een rommelige staat en wil je van branch veranderen om aan iets anders te werken. Het probleem is dat je geen halfklaar werk wilt committen, alleen maar om later verder te kunnen gaan vanaf hetzelfde punt. Het oplossing voor dit probleem is het `git stash` commando.
448
+
449
+ Stashen (wegstoppen) pakt de vervuilde status van je werkdirectory - dat wil zeggen: je gewijzigde getrackte bestanden en gestagede wijzigingen, en bewaart het op een stapel onafgemaakte wijzigingen die je op ieder tijdstip opnieuw kunt toepassen.
450
+
451
+ ### Je werk stashen ###
452
+
453
+ Om dit te demonstreren, ga je project in en begin met werken aan een paar bestanden en misschien stage je een van de wijzigingen. Als je `git status` uitvoert, kun je de vervuilde status zien:
454
+
455
+ $ git status
456
+ # On branch master
457
+ # Changes to be committed:
458
+ # (use "git reset HEAD <file>..." to unstage)
459
+ #
460
+ # modified: index.html
461
+ #
462
+ # Changes not staged for commit:
463
+ # (use "git add <file>..." to update what will be committed)
464
+ #
465
+ # modified: lib/simplegit.rb
466
+ #
467
+
468
+ Nu wil je van branch veranderen, maar je wilt hetgeen je aan hebt zitten werken nog niet committen, dus je gaat de wijzigingen stashen. Om een nieuwe stash op de stapel te zetten, voer je `git stash` uit:
469
+
470
+ $ git stash
471
+ Saved working directory and index state \
472
+ "WIP on master: 049d078 added the index file"
473
+ HEAD is now at 049d078 added the index file
474
+ (To restore them type "git stash apply")
475
+
476
+ Je werkdirectory is schoon:
477
+
478
+ $ git status
479
+ # On branch master
480
+ nothing to commit, working directory clean
481
+
482
+ Nu kan je eenvoudig van branch wisselen en ergens anders aan werken, je wijzigingen zijn opgeslagen op de stapel. Om te zien welke stashes je opgeslagen hebt, kun je `git stash list` gebruiken:
483
+
484
+ $ git stash list
485
+ stash@{0}: WIP on master: 049d078 added the index file
486
+ stash@{1}: WIP on master: c264051 Revert "added file_size"
487
+ stash@{2}: WIP on master: 21d80a5 added number to log
488
+
489
+ In dit geval waren er twee stashes al eerder opgeslagen, dus heb je toegang tot drie verschillende gestashede werken. Je kunt degene die je zojuist gestashed hebt opnieuw toepassen, door het commando uit te voeren dat in de help output van het originele stash commando stond: `git stash apply`. Als je een van de oudere stashes wilt toepassen, dan kun je die specificeren door hem te benoemen, zoals hier: `git apply stash stash@{2}`. Als je geen stash specificeert, neemt Git aan dat je de meest recente stash bedoelt en probeert die toe te passen:
490
+
491
+ $ git stash apply
492
+ # On branch master
493
+ # Changes not staged for commit:
494
+ # (use "git add <file>..." to update what will be committed)
495
+ #
496
+ # modified: index.html
497
+ # modified: lib/simplegit.rb
498
+ #
499
+
500
+ Je kunt zien dat Git opnieuw de bestanden wijzigt die je uncommitte toen je de stash opsloeg. In dit geval had je een schone werkdirectory toen je de stash probeerde toe te passen, en dat je probeerde deze op dezelfde branch toe te passen als waar je hem van opgeslagen hebt. Maar het hebben van een schone werkdirectory en het toepassen op dezelfde branch zijn niet noodzakelijk om een stash succesvol toe te kunnen passen. Je kunt een stash op één branch opslaan, later naar een andere branch omschakelen, en daar opnieuw de wijzigingen toe proberen te passen. Je kunt ook gewijzigde en uncommitted bestanden in je werkdirectory hebben wanneer je een stash probeert toe te passen, Git geeft merge conflicten aan als iets niet meer netjes toe te passen is.
501
+
502
+ De wijzigingen aan je bestanden zijn opnieuw toegepast, maar het bestand dat je eerder gestaged had is niet opnieuw gestaged. Om dat te doen moet je het `git stash apply` commando met de `--index` optie uitvoeren om het commando te vertellen de gestagede wijzigingen opnieuw proberen toe te passen. Als je dat had uitgevoerd, dan zou je weer op je originele uitgangspunt zijn uitgekomen:
503
+
504
+ $ git stash apply --index
505
+ # On branch master
506
+ # Changes to be committed:
507
+ # (use "git reset HEAD <file>..." to unstage)
508
+ #
509
+ # modified: index.html
510
+ #
511
+ # Changes not staged for commit:
512
+ # (use "git add <file>..." to update what will be committed)
513
+ #
514
+ # modified: lib/simplegit.rb
515
+ #
516
+
517
+ De apply optie probeert alleen het gestashete werk toe te passen - je blijft op de stapel behouden. Om het te verwijderen kun je `git stash drop` uitvoeren, met de naam van de stash die je wilt verwijderen:
518
+
519
+ $ git stash list
520
+ stash@{0}: WIP on master: 049d078 added the index file
521
+ stash@{1}: WIP on master: c264051 Revert "added file_size"
522
+ stash@{2}: WIP on master: 21d80a5 added number to log
523
+ $ git stash drop stash@{0}
524
+ Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)
525
+
526
+ Je kunt ook `git stash pop` uitvoeren om de stash toe te passen en deze direct van de stapel te verwijderen.
527
+
528
+ ### Een stash ont-toepassen ###
529
+
530
+ In sommige situaties zou het kunnen voorkomen dat je gestashde wijzigingen wilt toepassen, wat werk doen en dan de wijzigingen die van de stash waren gekomen ont-toepassen. Git heeft niet zoiets als een `stash unapply` commando, maar het is mogelijk om het effect te bereiken door simpelweg de patch op te halen die bij een stash hoort, en deze in zijn achteruit toe te passen:
531
+
532
+ $ git stash show -p stash@{0} | git apply -R
533
+
534
+ Nogmaals: als je geen stash specificeert gaat Git van de meest recente stash uit:
535
+
536
+ $ git stash show -p | git apply -R
537
+
538
+ Wellicht wil je een alias maken en effectief een `stash-unapply` commando aan je Git toevoegen. Bijvoorbeeld:
539
+
540
+ $ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
541
+ $ git stash apply
542
+ $ #... work work work
543
+ $ git stash-unapply
544
+
545
+ ### Een branch van een stash maken ###
546
+
547
+ Als je wat werk stashed, het daar poosje laat liggen, en doorwerkt op de branch waarvan je het werk gestashed hebt, dan kun je een probleem krijgen met het opnieuw toe passen van dat werk. Als het toepassen een bestand probeert te wijzigen dat je sindsdien gewijzigd hebt krijg je een merge conflict en zul je dat moeten proberen oplossen. Als je een eenvoudiger manier wilt hebben om je gestashde wijzigingen opnieuw te testen, kun je `git stash branch` uitvoeren. Dit zal een nieuwe branch voor je aanmaken, de commit waar je op zat toen je het werk stashte uitchecken, je werk opnieuw toepassen en dan de stash droppen als het succesvol is toegepast:
548
+
549
+ $ git stash branch testchanges
550
+ Switched to a new branch "testchanges"
551
+ # On branch testchanges
552
+ # Changes to be committed:
553
+ # (use "git reset HEAD <file>..." to unstage)
554
+ #
555
+ # modified: index.html
556
+ #
557
+ # Changes not staged for commit:
558
+ # (use "git add <file>..." to update what will be committed)
559
+ #
560
+ # modified: lib/simplegit.rb
561
+ #
562
+ Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)
563
+
564
+ Dit is een prettige manier om gestashed werk eenvoudig terug te halen en eraan te werken in een nieuwe branch.
565
+
566
+ ## Geschiedenis herschrijven ##
567
+
568
+ Vaak zal je, als je met Git werkt, je commit geschiedenis om een of andere reden willen aanpassen. Één van de mooie dingen van Git is dat het je in staat stelt om beslissingen op het laatst mogelijke moment te maken. Je kunt bepalen welke bestanden in welke commits gaan vlak voordat je commit, door middel van de staging area, je kunt besluiten dat je toch nog niet aan iets had willen beginnen met het stash commando en je kunt commits herschrijven ook al zijn ze al gebeurd, waardoor het lijkt alsof ze op een andere manier gebeurd zijn. Dit kan bijvoorbeeld de volgorde van de commits zijn, berichten of bestanden in een commit wijzigen, commits samenpersen(squashen) of opsplitsen, of complete commits weghalen - en dat allemaal voordat je jouw werk met anderen deelt.
569
+
570
+ In deze paragraaf zal je leren hoe je deze handige taken uitvoert, zodat je jouw commit geschiedenis er uit kunt laten zien zoals jij dat wilt, voordat je het met anderen deelt.
571
+
572
+ ### De laatste commit veranderen ###
573
+
574
+ De laatste commit veranderen is waarschijnlijk de meest voorkomende geschiedenis wijziging die je zult doen. Vaak wil je twee basale dingen aan je laatste commit wijzigen: het commit bericht, of de snapshot, dat je zojuist opgeslagen hebt, wijzigen door het toevoegen, wijzigen of weghalen van bestanden.
575
+
576
+ Als je alleen je laatste commit bericht wilt wijzigen, dan is dat heel eenvoudig:
577
+
578
+ $ git commit --amend
579
+
580
+ Dat plaatst je in de teksteditor met je laatste commit bericht erin, klaar voor je om het bericht te wijzigen. Als je opslaat en de editor sluit, dan schrijft de editor een nieuwe commit met dat bericht en maakt dat je laatste commit.
581
+
582
+ Als je hebt gecommit en daarna wil je het snapshot dat je gecommit hebt wijzigen, door het toevoegen of wijzigen van bestanden, misschien omdat je vergeten was een nieuw bestand toe te voegen toen je committe, gaat het proces vergelijkbaar. Je staged de wijzigingen die je wilt door een bestand te wijzigen en `git add` er op uit te voeren, of `git rm` op een getrackt bestand, en de daaropvolgende `git commit --amend` pakt je huidige staging area en maakt dat het snapshot voor de nieuwe commit.
583
+
584
+ Je moet wel oppassen met deze techniek, omdat het amenden de SHA-1 van de commit wijzigt. Het is vergelijkbaar met een kleine rebase: niet je laatste commit wijzigen als je die al gepusht hebt.
585
+
586
+ ### Meerdere commit berichten wijzigen ###
587
+
588
+ Om een commit te wijzigen die verder terug in je geschiedenis zit, moet je meer complexe tools gebruiken. Git heeft geen geschiedenis-wijzig tool, maar je kunt de rebase tool gebruiken om een serie commits op de HEAD te rebasen waarop ze origineel gebaseerd, in plaats van ze naar een andere te verhuizen. Met de interactieve rebase tool kun je dan na iedere commit die je wilt wijzigen stoppen en het bericht wijzigen, bestanden toevoegen, of doen wat je ook maar wilt. Je kunt rebase interactief uitvoeren door de `-i` optie aan `git rebase` toe te voegen. Je moet aangeven hoe ver terug je commits wilt herschrijven door het commando te vertellen op welke commit het moet rebasen.
589
+
590
+ Bijvoorbeeld, als je de laatste drie commit berichten wilt veranderen, of een van de commit berichten in die groep, dan geef je de ouder van de laatste commit die je wilt wijzigen mee als argument aan `git rebase -i`, wat `HEAD~2^` of `HEAD~3` is. Het kan makkelijker zijn om de `~3` te onthouden, omdat je de laatste drie commits probeert te wijzigen; maar houd in gedachten dat je eigenlijk vier commits terug aangeeft; de ouder van de laatste commit die je wilt veranderen:
591
+
592
+ $ git rebase -i HEAD~3
593
+
594
+ Onthoud, nogmaals, dat dit een rebase commando is - iedere commit in de reeks `HEAD~3..HEAD` zal worden herschreven, of je het bericht nu wijzigt of niet. Voeg geen commit toe die je al naar een centrale server gepusht hebt; als je dit doet breng je andere gebruikers in de war omdat je ze een alternatieve versie van dezelfde wijziging te geeft.
595
+
596
+ Dit commando uitvoeren geeft je een lijst met commits in je tekst editor die er ongeveer zo uit ziet:
597
+
598
+ pick f7f3f6d changed my name a bit
599
+ pick 310154e updated README formatting and added blame
600
+ pick a5f4a0d added cat-file
601
+
602
+ # Rebase 710f0f8..a5f4a0d onto 710f0f8
603
+ #
604
+ # Commands:
605
+ # p, pick = use commit
606
+ # r, reword = use commit, but edit the commit message
607
+ # e, edit = use commit, but stop for amending
608
+ # s, squash = use commit, but meld into previous commit
609
+ # f, fixup = like "squash", but discard this commit's log message
610
+ # x, exec = run command (the rest of the line) using shell
611
+ #
612
+ # These lines can be re-ordered; they are executed from top to bottom.
613
+ #
614
+ # If you remove a line here THAT COMMIT WILL BE LOST.
615
+ #
616
+ # However, if you remove everything, the rebase will be aborted.
617
+ #
618
+ # Note that empty commits are commented out
619
+
620
+ Het is belangrijk om op te merken dat deze commits in de tegengestelde volgorde getoond worden dan hoe je ze normaliter ziet als je het `log` commando gebruikt. Als je een `log` uitvoert, zie je zoiets als dit:
621
+
622
+ $ git log --pretty=format:"%h %s" HEAD~3..HEAD
623
+ a5f4a0d added cat-file
624
+ 310154e updated README formatting and added blame
625
+ f7f3f6d changed my name a bit
626
+
627
+ Merk de omgekeerde volgorde op. De interactieve rebase geeft je een script dat het gaat uitvoeren. Het zal beginnen met de commit die je specificeert op de commando regel (`HEAD~3`) en de wijzigingen in elk van deze commits van voor naar achter opnieuw afspelen. Het toont de oudste het eerst in plaats van de nieuwste, omdat dat deze de eerste is die zal worden afgespeeld.
628
+
629
+ Je moet het script zodanig aanpassen dat het stopt bij de commit die je wilt wijzigen. Om dat te doen moet je het woord "pick" veranderen in het woord "edit" voor elke commit waarbij je het script wilt laten stoppen. Bijvoorbeeld, om alleen het derde commit bericht te wijzigen verander je het bestand zodat het er zo uitziet:
630
+
631
+ edit f7f3f6d changed my name a bit
632
+ pick 310154e updated README formatting and added blame
633
+ pick a5f4a0d added cat-file
634
+
635
+ Als je dit opslaat en de editor sluit, spoelt Git terug naar de laatste commit van die lijst en zet je op de commando regel met de volgende boodschap:
636
+
637
+ $ git rebase -i HEAD~3
638
+ Stopped at 7482e0d... updated the gemspec to hopefully work better
639
+ You can amend the commit now, with
640
+
641
+ git commit --amend
642
+
643
+ Once you’re satisfied with your changes, run
644
+
645
+ git rebase --continue
646
+
647
+ Deze instructies vertellen je precies wat je moet doen. Type
648
+
649
+ $ git commit --amend
650
+
651
+ Wijzig het commit bericht en verlaat de editor. Voer vervolgens dit uit
652
+
653
+ $ git rebase --continue
654
+
655
+ Dit commando zal de andere twee commits automatisch toepassen, en je bent klaar. Als je "pick" op meerdere regels in "edit" verandert, dan kan je deze stappen herhalen voor iedere commit die je in "edit" veranderd hebt. Elke keer zal Git stoppen, je de commit laten wijzigen en verder gaan als je klaar bent.
656
+
657
+ ### Commits opnieuw rangschikken ###
658
+
659
+ Je kunt een interactieve rebase ook gebruiken om commits opnieuw te rangschikken of zijn geheel te verwijderen. Als je de "added cat-file" commit wilt verwijderen en de volgorde waarin de andere twee commits zijn geïntroduceerd wilt veranderen, dan kun je het rebase script van dit
660
+
661
+ pick f7f3f6d changed my name a bit
662
+ pick 310154e updated README formatting and added blame
663
+ pick a5f4a0d added cat-file
664
+
665
+ veranderen in dit:
666
+
667
+ pick 310154e updated README formatting and added blame
668
+ pick f7f3f6d changed my name a bit
669
+
670
+ Als je dan opslaat en de editor sluit, zal Git je branch terugzetten naar de ouder van deze commits, eerst `310154e` en dan `f7f3f6d` toepassen, en dan stoppen. Effectief verander je de volgorde van die commits en verwijder je de "added cat-file" commit volledig.
671
+
672
+ ### Een commit samenpersen (squashing) ###
673
+
674
+ Het is ook mogelijk een serie commits te pakken en ze in één enkele commit samen te persen (squash) met de interactieve rebase tool. Het script stopt behulpzame instructies in het rebase bericht:
675
+
676
+ #
677
+ # Commands:
678
+ # p, pick = use commit
679
+ # r, reword = use commit, but edit the commit message
680
+ # e, edit = use commit, but stop for amending
681
+ # s, squash = use commit, but meld into previous commit
682
+ # f, fixup = like "squash", but discard this commit's log message
683
+ # x, exec = run command (the rest of the line) using shell
684
+ #
685
+ # These lines can be re-ordered; they are executed from top to bottom.
686
+ #
687
+ # If you remove a line here THAT COMMIT WILL BE LOST.
688
+ #
689
+ # However, if you remove everything, the rebase will be aborted.
690
+ #
691
+ # Note that empty commits are commented out
692
+
693
+ Als je in plaats van "pick" of "edit", "squash" specificeert zal Git zowel die verandering als de verandering die er direct aan vooraf gaat toepassen, en je dwingen om de commit berichten samen te voegen. Dus als je een enkele commit van deze drie commits wil maken, laat je het script er zo uit zien:
694
+
695
+ pick f7f3f6d changed my name a bit
696
+ squash 310154e updated README formatting and added blame
697
+ squash a5f4a0d added cat-file
698
+
699
+ Als je de editor opslaat en sluit, zal Git alle drie wijzigingen toepassen en je terug in de editor brengen om de drie commit berichten samen te voegen:
700
+
701
+ # This is a combination of 3 commits.
702
+ # The first commit's message is:
703
+ changed my name a bit
704
+
705
+ # This is the 2nd commit message:
706
+
707
+ updated README formatting and added blame
708
+
709
+ # This is the 3rd commit message:
710
+
711
+ added cat-file
712
+
713
+ Als je dat opslaat, heb je een enkele commit die de veranderingen van alle drie vorige commits introduceert.
714
+
715
+ ### Een commit splitsen ###
716
+
717
+ Een commit opsplitsen zal een commit ongedaan maken, en dan net zo vaak gedeeltelijk stagen en committen als het aantal commits waar je mee wilt eindigen. Bijvoorbeeld, stel dat je de middelste van je drie commits wilt splitsen. In plaats van "updated README formatting and added blame" wil je het splitsen in twee commits: "updated README formatting" als eerste, en "added blame" als tweede. Je kunt dat doen in het `rebase -i` script door de instructie van de commit die je wilt splitsen te veranderen in "edit":
718
+
719
+ pick f7f3f6d changed my name a bit
720
+ edit 310154e updated README formatting and added blame
721
+ pick a5f4a0d added cat-file
722
+
723
+ Als je opslaat en de editor verlaat, spoelt Git terug naar de parent van de eerste commit in de lijst, past de eerste commit toe (`f7f3f6d`), past de tweede toe (`310154e`), en zet je dan in de console. Daar kan je een gemengde reset doen van die commit met `git reset HEAD^` , wat effectief de commit terugdraait en de gewijzigde bestanden unstaged laat. Nu kan je de wijzigingen die gereset zijn nemen en er meerdere commits van maken. Eenvoudigweg bestanden stagen en committen tot je meerdere commits hebt, en dan `git rebase --continue` uitvoeren zodra je klaar bent:
724
+
725
+ $ git reset HEAD^
726
+ $ git add README
727
+ $ git commit -m 'updated README formatting'
728
+ $ git add lib/simplegit.rb
729
+ $ git commit -m 'added blame'
730
+ $ git rebase --continue
731
+
732
+ Git zal de laatste commit (`a5f4a0d`) in het script toepassen, en je geschiedenis zal er zo uitzien:
733
+
734
+ $ git log -4 --pretty=format:"%h %s"
735
+ 1c002dd added cat-file
736
+ 9b29157 added blame
737
+ 35cfb2b updated README formatting
738
+ f3cc40e changed my name a bit
739
+
740
+ Nogmaals, dit verandert alle SHA's van alle commits in de lijst, dus zorg er voor dat er geen commit in die lijst zit die je al naar een gedeelde repository gepusht hebt.
741
+
742
+ ### De optie met atoomkracht: filter-branch ###
743
+
744
+ Er is nog een geschiedenis-herschrijvende optie, die je kunt gebruiken als je een groter aantal commits moet herschrijven op een gescripte manier. Bijvoorbeeld, het globaal veranderen van je e-mail adres of een bestand uit iedere commit verwijderen. Het commando heet `filter-branch` en het kan grote gedeelten van je geschiedenis herschrijven, dus je moet het niet gebruiken tenzij je project nog niet publiekelijk is gemaakt, en andere mensen nog geen werk hebben gebaseerd op jouw commits die je op het punt staat te herschrijven. Maar het kan heel handig zijn. Je zult een paar gebruikelijke toepassingen zien zodat je een idee krijgt waar het toe in staat is.
745
+
746
+ #### Een bestand uit iedere commit verwijderen ####
747
+
748
+ Dit gebeurt vrij regelmatig. Iemand voegt per ongeluk een enorm binair bestand toe met een achteloze `git add .`, en je wilt het overal weghalen. Misschien heb je per ongeluk een bestand dat een wachtwoord bevat gecommit, en je wilt dat project open source maken. `filter-branch` is dan de tool dat je wilt gebruiken om je hele geschiedenis schoon te poetsen. Om een bestand met de naam passwords.txt uit je hele geschiedenis weg te halen, kun je de `--tree-filter` optie toevoegen aan `filter-branch`:
749
+
750
+ $ git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
751
+ Rewrite 6b9b3cf04e7c5686a9cb838c3f36a8cb6a0fc2bd (21/21)
752
+ Ref 'refs/heads/master' was rewritten
753
+
754
+ De `--tree-filter` optie voert het gegeven commando uit na elke checkout van het project, en commit de resultaten weer. In dit geval verwijder je een bestand genaamd passwords.txt van elke snapshot, of het bestaat of niet. Als je alle per ongeluk toegevoegde editor backup bestanden wilt verwijderen, kun je bijvoorbeeld dit uitvoeren `git filter-branch --tree-filter "rm -f *~" HEAD`.
755
+
756
+ Je zult Git objectbomen en commits zien herschrijven en op het eind de branch wijzer zien verplaatsen. Het is over het algemeen een goed idee om dit in een test branch te doen, en dan je master branch te hard-resetten nadat je gecontroleerd hebt dat de uitkomst echt is als je het wilt hebben. Om `filter-branch` op al je branches uit te voeren, moet je `--all` aan het commando meegeven.
757
+
758
+ #### Een subdirectory de nieuwe root maken ####
759
+
760
+ Stel dat je een import vanuit een ander versiebeheersysteem hebt gedaan, en subdirectories hebt die niet zinnig zijn (trunk, tags, enzovoort). Als je de `trunk` subdirectory de nieuwe root van het project wilt maken voor elke commit, kan `filter-branch` je daar ook mee helpen:
761
+
762
+ $ git filter-branch --subdirectory-filter trunk HEAD
763
+ Rewrite 856f0bf61e41a27326cdae8f09fe708d679f596f (12/12)
764
+ Ref 'refs/heads/master' was rewritten
765
+
766
+ Nu is de nieuwe project root elke keer de inhoud van de `trunk` subdirectory. Git zal ook automatisch commits verwijderen die geen betrekking hadden op die subdirectory.
767
+
768
+ #### E-mail adressen globaal veranderen ####
769
+
770
+ Een ander veel voorkomend geval is dat je vergeten bent om `git config` uit te voeren om je naam en e-mail adres in te stellen voordat je begon met werken, of misschien wil je een project op het werk open source maken en al je werk e-mail adressen veranderen naar je persoonlijke adres. Hoe dan ook, je kunt e-mail adressen in meerdere commits ook in één klap veranderen met `filter-branch`. Je moet wel oppassen dat je alleen die e-mail adressen aanpast die van jou zijn, dus gebruik je `--commit-filter`:
771
+
772
+ $ git filter-branch --commit-filter '
773
+ if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
774
+ then
775
+ GIT_AUTHOR_NAME="Scott Chacon";
776
+ GIT_AUTHOR_EMAIL="schacon@example.com";
777
+ git commit-tree "$@";
778
+ else
779
+ git commit-tree "$@";
780
+ fi' HEAD
781
+
782
+ Dit gaat alle commits door en herschrijft ze zodat het jouw nieuwe adres bevat. Om dat commits de SHA-1 waarde van hun ouders bevatten, zal dit commando iedere commit SHA in jouw geschiedenis veranderen, niet alleen diegene die het gezochte e-mailadres bevatten.
783
+
784
+ ## Debuggen met Git ##
785
+
786
+ Git levert ook een paar tools om je problemen te helpen debuggen in je projecten. Omdat Git is ontworpen te werken met bijna elk type project zijn deze tools erg generiek, maar ze kunnen je vaak helpen een bug of schuldige te vinden als de dingen verkeerd gaan.
787
+
788
+ ### Aantekenen van bestanden ###
789
+
790
+ Als je een bug in je code traceert en wilt weten wanneer het was geïntroduceerd en waarom, dan is bestands aantekenen vaak je beste methode. Het toont je welke commit de laatste was die iets wijzigde in een bepaald bestand. Dus als je ziet dat een methode in je code bugs bevat, dan kun je het bestand aantekenen met `git blame` om te zien wanneer een regel van de methode voor het laatst aangepast was en door wie. Dit voorbeeld gebruikt de `-L` optie om de output te beperken tot regel 12 tot en met 22:
791
+
792
+ $ git blame -L 12,22 simplegit.rb
793
+ ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 12) def show(tree = 'master')
794
+ ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 13) command("git show #{tree}")
795
+ ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 14) end
796
+ ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 15)
797
+ 9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 16) def log(tree = 'master')
798
+ 79eaf55d (Scott Chacon 2008-04-06 10:15:08 -0700 17) command("git log #{tree}")
799
+ 9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 18) end
800
+ 9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 19)
801
+ 42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 20) def blame(path)
802
+ 42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 21) command("git blame #{path}")
803
+ 42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 22) end
804
+
805
+ Merk op dat het eerste veld de gedeeltelijke SHA-1 van de commit is die als laatste die regel gewijzigd heeft. De volgende twee velden zijn waarden die gehaald zijn uit die commit: de naam van de auteur en de datum van die commit, zodat je makkelijk kunt zien wie die regel aangepast heeft en wanneer. Daarna komt het regelnummer en de inhoud van dat bestand. Let ook op de `^4832fe2` commit regels, die aangeven dat die regels in de allereerste commit van dat bestand zaten. Die commit is gedaan toen dit bestand voor het eerst was toegevoegd aan dit project, en die regels zijn sindsdien ongewijzigd gebleven. Dit is ietwat wat verwarrend, want nu heb je minstens drie manieren gezien waarop Git het `^` symbool gebruikt om een SHA van een commit aan te passen, maar dit is wat het hier betekent.
806
+
807
+ Een ander gave ding van Git is dat het naamswijzigingen van bestanden niet expliciet bijhoudt. Het slaat de snapshots op en probeert dan impliciet uit te vogelen dat er iets hernoemd is, nadat dat gebeurd is. Een van de interessante gevolgen hiervan is dat je Git ook kunt vragen om allerlei soorten code verplaatsingen uit te zoeken. Als je `-C` aan `git blame` meegeeft, zal Git het bestand dat je aantekent analyseren en proberen uit te vinden waar stukjes code daarin oorspronkelijk vandaan kwamen als ze ergens vandaan gekopieerd zijn. Recentelijk was ik een bestand genaamd `GITServerHandler.m` aan het omschrijven naar meerdere bestanden, waarvan `GITPackUpload.m` er een was. Door `GITPackUpload.m` te blamen met de `-C` optie, kon ik zien waar delen van de code oorspronkelijk vandaan kwamen:
808
+
809
+ $ git blame -C -L 141,153 GITPackUpload.m
810
+ f344f58d GITServerHandler.m (Scott 2009-01-04 141)
811
+ f344f58d GITServerHandler.m (Scott 2009-01-04 142) - (void) gatherObjectShasFromC
812
+ f344f58d GITServerHandler.m (Scott 2009-01-04 143) {
813
+ 70befddd GITServerHandler.m (Scott 2009-03-22 144) //NSLog(@"GATHER COMMI
814
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 145)
815
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 146) NSString *parentSha;
816
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 147) GITCommit *commit = [g
817
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 148)
818
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 149) //NSLog(@"GATHER COMMI
819
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 150)
820
+ 56ef2caf GITServerHandler.m (Scott 2009-01-05 151) if(commit) {
821
+ 56ef2caf GITServerHandler.m (Scott 2009-01-05 152) [refDict setOb
822
+ 56ef2caf GITServerHandler.m (Scott 2009-01-05 153)
823
+
824
+ Dit is echt heel handig. Normaal krijg je als de originele commit de commit waar je de code naartoe gekopieerd hebt, omdat dat de eerste keer is dat je die regels aangeraakt hebt in dit bestand. Git vertelt je de oorspronkelijke commit waarin je deze regels geschreven hebt, zelfs als dat in een ander bestand was.
825
+
826
+ ### Binair zoeken ###
827
+
828
+ Een bestand aantekenen helpt als je al weet waar het probleem zit. Als je niet weet waar de fout zit en er zijn dozijnen of honderden commits geweest sinds de laatste staat waarvan je weet dat de code werkte, dan zal je waarschijnlijk bij `git bisect` aankloppen voor hulp. Het `bisect` commando zoekt binair door je commit-geschiedenis om je zo snel als mogelijk te helpen identificeren welke commit het issue introduceerde.
829
+
830
+ Stel dat je zojuist een release van je code naar een productie omgeving gepusht hebt, en je krijgt bug rapporten dat er iets gebeurt wat niet in je development omgeving gebeurde en je kunt je niet voorstellen waarom de code dat aan het doen is. Je gaat terug naar je code, en het blijkt dat je het probleem kunt reproduceren maar je kunt niet zien wat er verkeerd gaat. Je kunt de code uitpluizen (bisecten) om het uit te vinden. Als eerste voer je `git bisect start` uit om aan de boel op te starten, en dan gebruik je `git bisect bad` om het systeem te vertellen dat de huidige commit waar je op zit kapot is. Dan moet je bisect vertellen wanneer de laatste goede status was, met `git bisect good [goede_commit]`:
831
+
832
+ $ git bisect start
833
+ $ git bisect bad
834
+ $ git bisect good v1.0
835
+ Bisecting: 6 revisions left to test after this
836
+ [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo
837
+
838
+ Git heeft gezien dat er ongeveer 12 commits geweest zijn tussen de commit die je als laatste goede commit gemarkeerd hebt (v1.0) en de huidige slechte versie, en het heeft de middelste voor je uitgecheckt. Op dit punt kun je de test uitvoeren om te zien of het probleem op deze commit ook aanwezig is. Als dat zo is, dan was het probleem ergens voor deze middelste commit geïntroduceerd, zo niet dan is het probleem na deze commit geïntroduceerd. Het blijkt dat hier geen probleem is, dus vertel je Git dat door `git bisect good` te typen en je reis te vervolgen:
839
+
840
+ $ git bisect good
841
+ Bisecting: 3 revisions left to test after this
842
+ [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing
843
+
844
+ Nu zit je op een andere commit, halverwege degene die je zojuist getest hebt en je slechte commit. Je voert je test opnieuw uit, en stelt vast dat deze commit kapot is, dus vertel je dat Git met `git bisect bad`:
845
+
846
+ $ git bisect bad
847
+ Bisecting: 1 revisions left to test after this
848
+ [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table
849
+
850
+ Deze commit is in orde, en nu heeft Git alle informatie die het nodig heeft om vast te stellen wanneer het probleem was geïntroduceerd. Het vertelt je de SHA-1 van de eerste slechte commit en toont een stukje commit informatie en welke bestanden aangepast waren in die commit, zodat je er achter kunt komen wat deze bug geïntroduceerd kan hebben:
851
+
852
+ $ git bisect good
853
+ b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit
854
+ commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04
855
+ Author: PJ Hyett <pjhyett@example.com>
856
+ Date: Tue Jan 27 14:48:32 2009 -0800
857
+
858
+ secure this thing
859
+
860
+ :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730
861
+ f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config
862
+
863
+ Als je klaar bent, moet je `git bisect reset` uitvoeren om je HEAD terug te zetten naar het punt waar je was toen je startte, anders eindig je in een vreemde status:
864
+
865
+ $ git bisect reset
866
+
867
+ Dit is een krachtige tool, die je kan helpen om in enkele minuten honderden commits te doorzoeken op zoek naar een fout. Sterker nog, als je een script hebt die eindigt met 0 als het project goed is of niet-0 als het fout is, kan je `git bisect` volledig automatiseren. Eerst vertel je het de scope van de bisect door het de goede en slechte commits te geven. Als je kan dit doen door ze op te geven bij het `bisect start` commando, waarbij je de slechte commit eerst en de laatst bekende goede commit als tweede geeft:
868
+
869
+ $ git bisect start HEAD v1.0
870
+ $ git bisect run test-error.sh
871
+
872
+ Door het zo te doen wordt `test-error.sh` uitgevoerd bij elke commit die uitgecheckt wordt, totdat Git de eerste kapotte commit vindt. Je kunt ook iets als `make` of `make tests` uitvoeren, of wat je ook hebt dat automatische tests voor je uitvoert.
873
+
874
+ ## Submodules ##
875
+
876
+ Het komt vaak voor dat terwijl je zit te werken aan het ene project, je een ander project daarbinnen moet gebruiken. Bijvoorbeeld een library die een derde partij ontwikkeld heeft, of die je separaat aan het ontwikkelen bent en gebruikt in meerdere projecten. Een veel voorkomend probleem komt in deze scenario's naar voren: je wilt de twee projecten apart behandelen, maar wel binnen de andere kunnen gebruiken.
877
+
878
+ Hier is een voorbeeld. Stel dat je een website aan het ontwikkelen bent en Atom feeds aan het maken bent. In plaats van je eigen Atom-genererende code te schrijven, besluit je een library te gebruiken. Je zult deze code dan moeten includen van een gedeelde library zoals een CPAN installatie of een Ruby gem, of de broncode kopiéren naar je eigen projectboom. Het probleem met de library includen is dat het lastig is om de library op enige manier aan te passen, en vaak nog lastiger is om het uit te rollen omdat je zeker moet zijn dat iedere client die library beschikbaar heeft. Het probleem van de broncode in je project stoppen is dat alle aanpassingen die je maakt lastig te mergen zijn op het moment dat stroomopwaarts veranderingen beschikbaar komen.
879
+
880
+ Git pakt dit probleem aan door submodules te gebruiken. Submodules geven je de mogelijkheid om een Git repository als een subdirectory van een ander Git repository te gebruiken. Dit stelt je in staat staat een ander repository in je project te klonen en je commits gescheiden te houden.
881
+
882
+ ### Beginnen met submodules ###
883
+
884
+ Stel dat je de Rack library (een Ruby web server gateway interface) wilt toevoegen aan je project, misschien je eigen veranderingen eraan wilt onderhouden, maar ook veranderingen van stroomopwaarts wilt mergen. Het eerste wat je moet doen is de externe repository klonen in jouw subdirectory. Je voegt externe projecten als submodules toe door middel van het `git submodule add` commando:
885
+
886
+ $ git submodule add git://github.com/chneukirchen/rack.git rack
887
+ Initialized empty Git repository in /opt/subtest/rack/.git/
888
+ remote: Counting objects: 3181, done.
889
+ remote: Compressing objects: 100% (1534/1534), done.
890
+ remote: Total 3181 (delta 1951), reused 2623 (delta 1603)
891
+ Receiving objects: 100% (3181/3181), 675.42 KiB | 422 KiB/s, done.
892
+ Resolving deltas: 100% (1951/1951), done.
893
+
894
+ Nu heb je het Rack project als een subdirectory genaamd `rack` in je eigen project. Je kunt die subdirectory in gaan, wijzigingen maken, je eigen schrijfbare remote repository toevoegen waar je veranderingen in kunt pushen, vanuit de originele repository fetchen en mergen, en zo meer. Als je `git status` uitvoert vlak nadat je de submodule toevoegt, zie je twee dingen:
895
+
896
+ $ git status
897
+ # On branch master
898
+ # Changes to be committed:
899
+ # (use "git reset HEAD <file>..." to unstage)
900
+ #
901
+ # new file: .gitmodules
902
+ # new file: rack
903
+ #
904
+
905
+ Eerst zie je het `.gitmodules` bestand. Dit is een configuratie bestand dat de mapping opslaat tussen de URL van het project en de lokale subdirectory waarin je het gepulled hebt:
906
+
907
+ $ cat .gitmodules
908
+ [submodule "rack"]
909
+ path = rack
910
+ url = git://github.com/chneukirchen/rack.git
911
+
912
+ Als je meerdere submodules hebt, zal je meerdere vermeldingen hebben in dit bestand. Het is belangrijk om op te merken dat dit bestand net als je andere bestanden ook onder versiebeheer staat, net als het `.gitignore` bestand. Het wordt samen met de rest van het project gepusht en gepulled. Op deze manier weten andere mensen die je project klonen waar ze de submodule projecten vandaan moeten halen.
913
+
914
+ De andere vermelding in de `git status` uitvoer is de rack regel. Als je `git diff` daarop uitvoert zul je iets interessants zien:
915
+
916
+ $ git diff --cached rack
917
+ diff --git a/rack b/rack
918
+ new file mode 160000
919
+ index 0000000..08d709f
920
+ --- /dev/null
921
+ +++ b/rack
922
+ @@ -0,0 +1 @@
923
+ +Subproject commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
924
+
925
+ Hoewel `rack` een subdirectory in je werkdirectory is, ziet Git het als een submodule en zal de inhoud niet tracken als je niet in die directory staat. In plaats daarvan slaat Git het als een aparte commit op van die repository. Als je wijzigingen maakt en in die subdirectory een commit doet, zal het superproject zien dat de HEAD daar is veranderd en de exacte commit opslaan waarop je op dat moment zit te werken; op die manier zullen anderen die dit project klonen de omgeving exact kunnen reproduceren.
926
+
927
+ Dit is een belangrijk punt met submodules: je slaat ze op als de exacte commit waar ze op staan. Je kunt een submodule niet opslaan als `master` of een andere symbolische referentie.
928
+
929
+ Als je commit, zou je zoiets als dit moeten zien:
930
+
931
+ $ git commit -m 'first commit with submodule rack'
932
+ [master 0550271] first commit with submodule rack
933
+ 2 files changed, 4 insertions(+), 0 deletions(-)
934
+ create mode 100644 .gitmodules
935
+ create mode 160000 rack
936
+
937
+ Merk de 160000 modus op voor de rack vermelding. Dat is een speciale modus binnen Git, die in feite betekent dat je een commit als een directory vermelding opslaat in plaats van als een subdirectory of een bestand.
938
+
939
+ Je kunt de `rack` directory als een apart project behandelen en je superproject van tijd tot tijd vernieuwen met een pointer naar de laatste commit in dat subproject. Alle Git commando's werken onafhankelijk in de twee directories:
940
+
941
+ $ git log -1
942
+ commit 0550271328a0038865aad6331e620cd7238601bb
943
+ Author: Scott Chacon <schacon@gmail.com>
944
+ Date: Thu Apr 9 09:03:56 2009 -0700
945
+
946
+ first commit with submodule rack
947
+ $ cd rack/
948
+ $ git log -1
949
+ commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
950
+ Author: Christian Neukirchen <chneukirchen@gmail.com>
951
+ Date: Wed Mar 25 14:49:04 2009 +0100
952
+
953
+ Document version change
954
+
955
+ ### Een project met submodules clonen ###
956
+
957
+ Hier ga je een project met een submodule erin clonen. Als je zo'n project ontvangt, krijg je de directories die submodules bevatten, maar nog niet de bestanden:
958
+
959
+ $ git clone git://github.com/schacon/myproject.git
960
+ Initialized empty Git repository in /opt/myproject/.git/
961
+ remote: Counting objects: 6, done.
962
+ remote: Compressing objects: 100% (4/4), done.
963
+ remote: Total 6 (delta 0), reused 0 (delta 0)
964
+ Receiving objects: 100% (6/6), done.
965
+ $ cd myproject
966
+ $ ls -l
967
+ total 8
968
+ -rw-r--r-- 1 schacon admin 3 Apr 9 09:11 README
969
+ drwxr-xr-x 2 schacon admin 68 Apr 9 09:11 rack
970
+ $ ls rack/
971
+ $
972
+
973
+ De `rack` directory is er, maar hij is leeg. Je moet twee commando's uitvoeren: `git submodule init` om je lokale configuratie bestand te initialiseren, en `git submodule update` om alle data van dat project te fetchen en de juiste commit die in je superproject staat uit te checken:
974
+
975
+ $ git submodule init
976
+ Submodule 'rack' (git://github.com/chneukirchen/rack.git) registered for path 'rack'
977
+ $ git submodule update
978
+ Initialized empty Git repository in /opt/myproject/rack/.git/
979
+ remote: Counting objects: 3181, done.
980
+ remote: Compressing objects: 100% (1534/1534), done.
981
+ remote: Total 3181 (delta 1951), reused 2623 (delta 1603)
982
+ Receiving objects: 100% (3181/3181), 675.42 KiB | 173 KiB/s, done.
983
+ Resolving deltas: 100% (1951/1951), done.
984
+ Submodule path 'rack': checked out '08d709f78b8c5b0fbeb7821e37fa53e69afcf433'
985
+
986
+ Nu is je `rack` subdirectory in exact dezelfde staat als het was toen je het eerder gecommit had. Als een andere developer wijzigingen doet op de rack code en commit en je pulled die referentie en merged de code, dan krijg je iets dat een beetje vreemd is:
987
+
988
+ $ git merge origin/master
989
+ Updating 0550271..85a3eee
990
+ Fast forward
991
+ rack | 2 +-
992
+ 1 files changed, 1 insertions(+), 1 deletions(-)
993
+ [master*]$ git status
994
+ # On branch master
995
+ # Changes not staged for commit:
996
+ # (use "git add <file>..." to update what will be committed)
997
+ # (use "git checkout -- <file>..." to discard changes in working directory)
998
+ #
999
+ # modified: rack
1000
+ #
1001
+
1002
+ Je hebt iets gemerged dat eigenlijk een wijziging is op de pointer naar je submodule; maar de code in de submodule directory wordt niet vernieuwd, dus het lijkt erop dat je een vervuilde status hebt in je werkdirectory:
1003
+
1004
+ $ git diff
1005
+ diff --git a/rack b/rack
1006
+ index 6c5e70b..08d709f 160000
1007
+ --- a/rack
1008
+ +++ b/rack
1009
+ @@ -1 +1 @@
1010
+ -Subproject commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
1011
+ +Subproject commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
1012
+
1013
+ Dit is het omdat de pointer die je hebt voor de submodule niet is wat eigenlijk in de submodule directory zit. Om dit te repareren moet je `git submodule update` opnieuw uitvoeren:
1014
+
1015
+ $ git submodule update
1016
+ remote: Counting objects: 5, done.
1017
+ remote: Compressing objects: 100% (3/3), done.
1018
+ remote: Total 3 (delta 1), reused 2 (delta 0)
1019
+ Unpacking objects: 100% (3/3), done.
1020
+ From git@github.com:schacon/rack
1021
+ 08d709f..6c5e70b master -> origin/master
1022
+ Submodule path 'rack': checked out '6c5e70b984a60b3cecd395edd5b48a7575bf58e0'
1023
+
1024
+ Je moet dit iedere keer doen wanneer je een submodule wijziging pulled in het hoofdproject. Het is vreemd, maar het werkt.
1025
+
1026
+ Één bekend probleem doet zich voor als een developer een lokale wijziging in een submodule doet maar die niet naar een publieke server pusht. Dan committen ze een pointer naar de niet-publieke status en pushen deze naar het superproject. Als andere developers dan `git submodule update` proberen uit te voeren, dan zal het submodule systeem de commit die gerefereerd wordt niet kunnen vinden omdat het alleen op het systeem van de eerste developer bestaat. Als dat gebeurt, zal je een foutmelding als deze zien:
1027
+
1028
+ $ git submodule update
1029
+ fatal: reference isn’t a tree: 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
1030
+ Unable to checkout '6c5e70b984a60b3cecd395edd5ba7575bf58e0' in submodule path 'rack'
1031
+
1032
+ Je moet dan bekijken wie als laatste de submodule veranderd heeft:
1033
+
1034
+ $ git log -1 rack
1035
+ commit 85a3eee996800fcfa91e2119372dd4172bf76678
1036
+ Author: Scott Chacon <schacon@gmail.com>
1037
+ Date: Thu Apr 9 09:19:14 2009 -0700
1038
+
1039
+ added a submodule reference I will never make public. hahahahaha!
1040
+
1041
+ Dan stuur je een e-mail naar die jongen en gaat heel boos zijn tegen hem.
1042
+
1043
+ ### Superprojecten ###
1044
+
1045
+ Soms willen developers een combinatie van subdirectories van een groot project hebben, afhankelijk van het team waarin ze zitten. Dit komt vaak voor als je van CVS of Subversion af komt, waar je een module of verzameling subdirectory gedefinieerd hebt en je wilt deze workflow behouden.
1046
+
1047
+ Een goeie manier om dit in Git te doen is om elk van de subdirectories een aparte Git repository te maken en dan superproject Git repositories te maken die meerdere submodules bevatten. Een voordeel van deze aanpak is dat je meer specifiek kunt definiéren wat de relaties tussen de projecten zijn met behulp van tags en branches in de superprojects.
1048
+
1049
+ ### Problemen met submodules ###
1050
+
1051
+ Submodules gebruiken is echter niet zonder probleempjes. Ten eerste moet je relatief voorzichtig zijn met het werken in de directory van de submodule. Als je `git submodule update` uitvoert, zal het de specifieke versie van het project uitchecken, maar niet binnen een branch. Dit wordt een afgekoppelde (detached) HEAD genoemd - het houdt in dat het HEAD bestand direct naar een commit wijst en niet naar een symbolische referentie. Het probleem is dat je over het algemeen niet wilt werken in een detached HEAD omgeving, omdat het eenvoudig is om wijzigingen te verliezen. Als je een initiéle `submodule update` doet, in die submodule directory commit zonder een branch te maken om in te werken en dan nogmaals `git submodule update` uitvoert in het superproject zonder in de tussentijd te committen, dan zal Git je wijzigingen overschrijven zonder het je te vertellen. Technisch gezien ben je het werk niet kwijt, maar je zult geen branch hebben die er naar wijst, dus het zal wat lastig zijn om het terug te halen.
1052
+
1053
+ Om dit probleem te vermijden creéer je een branch zodra je in een submodule directory werkt met behulp van `git checkout -b work` of iets dergelijks. Als je de tweede keer de submodule update doet, zal het nog steeds je werk terugdraaien maar je heb tenminste een pointer om naar terug te keren.
1054
+
1055
+ Tussen branches omschakelen die submodules bevatten kan ook lastig zijn. Als je een nieuwe branch aanmaakt, daar een submodule toevoegt en dat terug wisselt naar een branch zonder die submodule, zul je nog steeds de submodule directory als een ungetrackte subdirectory hebben:
1056
+
1057
+ $ git checkout -b rack
1058
+ Switched to a new branch "rack"
1059
+ $ git submodule add git@github.com:schacon/rack.git rack
1060
+ Initialized empty Git repository in /opt/myproj/rack/.git/
1061
+ ...
1062
+ Receiving objects: 100% (3184/3184), 677.42 KiB | 34 KiB/s, done.
1063
+ Resolving deltas: 100% (1952/1952), done.
1064
+ $ git commit -am 'added rack submodule'
1065
+ [rack cc49a69] added rack submodule
1066
+ 2 files changed, 4 insertions(+), 0 deletions(-)
1067
+ create mode 100644 .gitmodules
1068
+ create mode 160000 rack
1069
+ $ git checkout master
1070
+ Switched to branch "master"
1071
+ $ git status
1072
+ # On branch master
1073
+ # Untracked files:
1074
+ # (use "git add <file>..." to include in what will be committed)
1075
+ #
1076
+ # rack/
1077
+
1078
+ Je moet hem verplaatsen of verwijderen, in welk geval je hem opnieuw moet clonen als je terug wisselt. Daarbij loop je kans om lokale wijzigingen of branches te verliezen die je niet gepusht hebt.
1079
+
1080
+ De laatste grote valkuil waar veel mensen in lopen heeft te maken met het wisselen van subdirectories naar submodules. Als je bestanden in je project trackt, en je wilt ze naar een submodule verplaatsen, dan moet je voorzichtig zijn of zal Git boos op je worden. Stel dat je de rack bestanden in een subdirectory van je project hebt, en je wilt die naar een submodule omzetten. Als je de subdirectory weggooit en dan `submodule add` uitvoert, begint Git naar je te schreeuwen:
1081
+
1082
+ $ rm -Rf rack/
1083
+ $ git submodule add git@github.com:schacon/rack.git rack
1084
+ 'rack' already exists in the index
1085
+
1086
+ Je moet de `rack` subdirectory eerst unstagen. Dan kun je de submodule toevoegen:
1087
+
1088
+ $ git rm -r rack
1089
+ $ git submodule add git@github.com:schacon/rack.git rack
1090
+ Initialized empty Git repository in /opt/testsub/rack/.git/
1091
+ remote: Counting objects: 3184, done.
1092
+ remote: Compressing objects: 100% (1465/1465), done.
1093
+ remote: Total 3184 (delta 1952), reused 2770 (delta 1675)
1094
+ Receiving objects: 100% (3184/3184), 677.42 KiB | 88 KiB/s, done.
1095
+ Resolving deltas: 100% (1952/1952), done.
1096
+
1097
+ Stel nu dat je dat in een branch gedaan zou hebben. Als je probeert terug te wisselen naar een branch waar die bestanden nog in de echte boom zitten in plaats van in een submodule - dan krijg je deze foutmelding:
1098
+
1099
+ $ git checkout master
1100
+ error: Untracked working tree file 'rack/AUTHORS' would be overwritten by merge.
1101
+
1102
+ Je moet de `rack` submodule directory uit de weg ruimen voordat je naar een branch kunt omschakelen die hem nog niet heeft:
1103
+
1104
+ $ mv rack /tmp/
1105
+ $ git checkout master
1106
+ Switched to branch "master"
1107
+ $ ls
1108
+ README rack
1109
+
1110
+ Als je dan terug schakelt krijg je een lege `rack` directory. Je kunt dan nogmaals `git submodule update` uitvoeren om nog eens te clonen, of je kunt je `/tmp/rack` directory terug zetten in de lege directory.
1111
+
1112
+ ## Subboom mergen ##
1113
+
1114
+ Nu je de moeilijkheden van het submodulesysteem hebt gezien, laten we eens kijken naar een alternatieve manier om hetzelfde probleem aan te pakken. Zodra Git merged, kijkt het naar wat het moet mergen en kiest dan een toepasselijke mergestrategie om te gebruiken. Als je twee branches aan het mergen bent zal Git een _recursive_ strategie gebruiken. Als je meer dan twee branches aan het mergen bent zal Git de _octopus_ strategie kiezen. Deze strategieén worden automatisch voor je gekozen omdat de recursieve strategie complexe drie-weg merge situaties aan kan - bijvoorbeeld meer dan één gezamenlijke voorouder, maar het kan het alleen mergen van twee branches aan. De octopus merge kan meerdere branches aan, maar is voorzichtiger om moeilijke conflicten te vermijden, dus wordt deze gekozen als de standaard strategie als je meer dan twee branches probeert te mergen.
1115
+
1116
+ Maar er zijn andere strategieén die je ook kunt kiezen. Eén ervan is de _subtree_ merge, en je kunt deze gebruiken om het subproject probleem aan te gaan. Hier zul je zien hoe je dezelfde rack inbedding kunt doen als in de vorige paragraaf, maar in plaats daarvan subboom-merges gebruiken.
1117
+
1118
+ Het idee van de subboom-merge is dat je twee projecten hebt, en één van de projecten komt overeen met een subdirectory van de andere en omgekeerd. Als je een subboommerge specificeert, dan is Git slim genoeg om erachter te komen dat de ene een subboom van de andere is en vervolgens juist te mergen - het is best wel verbazingwekkend.
1119
+
1120
+ Eerst voeg je de Rack applicatie toe aan je project. Voeg het Rack project toe als een remote reference in je eigen project en check het dan uit in zijn eigen branch:
1121
+
1122
+ $ git remote add rack_remote git@github.com:schacon/rack.git
1123
+ $ git fetch rack_remote
1124
+ warning: no common commits
1125
+ remote: Counting objects: 3184, done.
1126
+ remote: Compressing objects: 100% (1465/1465), done.
1127
+ remote: Total 3184 (delta 1952), reused 2770 (delta 1675)
1128
+ Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, done.
1129
+ Resolving deltas: 100% (1952/1952), done.
1130
+ From git@github.com:schacon/rack
1131
+ * [new branch] build -> rack_remote/build
1132
+ * [new branch] master -> rack_remote/master
1133
+ * [new branch] rack-0.4 -> rack_remote/rack-0.4
1134
+ * [new branch] rack-0.9 -> rack_remote/rack-0.9
1135
+ $ git checkout -b rack_branch rack_remote/master
1136
+ Branch rack_branch set up to track remote branch refs/remotes/rack_remote/master.
1137
+ Switched to a new branch "rack_branch"
1138
+
1139
+ Nu heb je de root van het Rack project in je `rack_branch` branch en je eigen project in de `master` branch. Als je eerste de ene uitchecked en dan de andere, kun je zien dat ze verschillende project roots hebben:
1140
+
1141
+ $ ls
1142
+ AUTHORS KNOWN-ISSUES Rakefile contrib lib
1143
+ COPYING README bin example test
1144
+ $ git checkout master
1145
+ Switched to branch "master"
1146
+ $ ls
1147
+ README
1148
+
1149
+ Je gaat nu het Rack project in je `master` project pullen als een subdirectory. Je kunt dat in Git doen met `git read-tree`. Je zult meer over `read-tree` en zijn vriendjes leren in Hoofdstuk 9, maar weet voor nu dat het de roottree van een branch in je huidige staging area en werkdirectory leest. Je hebt zojuist teruggewisseld naar je `master` branch, en je pulled de `rack_branch` branch in de `rack` subdirectory van de `master` branch van je hoofdproject:
1150
+
1151
+ $ git read-tree --prefix=rack/ -u rack_branch
1152
+
1153
+ Als je commit, lijkt het alsof alle Rack bestanden in die subdirectory staan - alsof je ze uit een tarball gekopieerd hebt. Waar het interessant wordt is dat je vrij makkelijk veranderingen van één branch in de andere kunt mergen. Dus als het Rack project update kan je alle wijzigingen van stroomopwaartse binnenhalen door naar die branch te wisselen en te pullen:
1154
+
1155
+ $ git checkout rack_branch
1156
+ $ git pull
1157
+
1158
+ Dan kun je die veranderingen terug in je master branch mergen. Je kunt `git merge -s subtree` gebruiken en het zal prima werken, maar Git zal ook de geschiedenissen samenvoegen, en dat wil je eigenlijk niet. Om de veranderingen binnen te halen en het commit bericht voor te vullen, gebruik je de `--squash` en `--no-commit` opties samen met de `-s subtree` strategie optie:
1159
+
1160
+ $ git checkout master
1161
+ $ git merge --squash -s subtree --no-commit rack_branch
1162
+ Squash commit -- not updating HEAD
1163
+ Automatic merge went well; stopped before committing as requested
1164
+
1165
+ Alle wijzigingen van het Rack project worden gemerged en zijn klaar om lokaal gecommit te worden. Je kunt ook het tegenovergestelde doen: veranderingen doen in de `rack` subdirectory van de master branch en die later in je `rack_branch` branch mergen om ze naar de beheerders te sturen of ze stroomopwaarts te pushen.
1166
+
1167
+ Om een diff te krijgen tussen wat je in de `rack` subdirectory hebt en de code in je `rack_branch` branch (om te zien of je ze moet mergen) kan je niet het gebruikelijke `diff` commando toepassen. In plaats daarvan moet je `git diff-tree` uitvoeren met de branch waarmee je wilt vergelijken:
1168
+
1169
+ $ git diff-tree -p rack_branch
1170
+
1171
+ Of om te vergelijken met wat in je `rack` subdirectory zit met wat in de `master` branch op de server zat toen je de laatste keer fetchde, kan je dit uitvoeren:
1172
+
1173
+ $ git diff-tree -p rack_remote/master
1174
+
1175
+ ## Samenvatting ##
1176
+
1177
+ Je hebt een aantal geavanceerde tools gezien, die je in staat stellen je commits en staging area heel exact te manipuleren. Als je problemen signaleert kun je vrij eenvoudig uitvinden welke commit deze geïntroduceerd heeft, wanneer, en door wie. Als je subprojecten in je project wilt gebruiken, heb je een paar manieren gezien hoe je die een plaats kunt geven. Nu zou je in staat moeten zijn om de meeste dingen in Git te doen die je dagelijks op de commandline moet doen, en je erbij op je gemak te voelen.