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,604 @@
1
+ # Git 分支 #
2
+
3
+ 幾乎每一種版本控制系統都以某種形式支援分支。使用分支意味著你可以從開發主線上分離開來,然後在不影響主線的同時繼續工作。在很多版本控制系統中,這是個昂貴的過程,常常需要創建一個原始程式碼目錄的完整副本,對大型項目來說會花費很長時間。
4
+
5
+ 有人把 Git 的分支模型稱為“必殺技特性”,而正是因為它,將 Git 從版本控制系統家族裡區分出來。Git 有何特別之處呢?Git 的分支可謂是難以置信的羽量級,它的新建操作幾乎可以在瞬間完成,並且在不同分支間切換起來也差不多一樣快。和許多其他版本控制系統不同,Git 鼓勵在工作流程中頻繁使用分支與合併,哪怕一天之內進行許多次都沒有關係。理解分支的概念並熟練運用後,你才會意識到為什麼 Git 是一個如此強大而獨特的工具,並從此真正改變你的開發方式。
6
+
7
+ ## 何謂分支 ##
8
+
9
+ 為了理解 Git 分支的實現方式,我們需要回顧一下 Git 是如何儲存資料的。或許你還記得第一章的內容,Git 保存的不是檔差異或者變化量,而只是一系列檔快照。
10
+
11
+ 在 Git 中提交時,會保存一個提交(commit)物件,該物件包含一個指向暫存內容快照的指標,包含本次提交的作者等相關附屬資訊,包含零個或多個指向該提交物件的父物件指標:首次提交是沒有直接祖先的,普通提交有一個祖先,由兩個或多個分支合併產生的提交則有多個祖先。
12
+
13
+ 為直觀起見,我們假設在工作目錄中有三個檔,準備將它們暫存後提交。暫存操作會對每一個檔計算校驗和(即第一章中提到的 SHA-1 雜湊字串),然後把當前版本的檔快照保存到 Git 倉庫中(Git 使用 blob 類型的物件存儲這些快照),並將校驗和加入暫存區域:
14
+
15
+ $ git add README test.rb LICENSE
16
+ $ git commit -m 'initial commit of my project'
17
+
18
+ 當使用 `git commit` 新建一個提交物件前,Git 會先計算每一個子目錄(本例中就是專案根目錄)的校驗和,然後在 Git 倉庫中將這些目錄保存為樹(tree)物件。之後 Git 創建的提交物件,除了包含相關提交資訊以外,還包含著指向這個樹物件(專案根目錄)的指標,如此它就可以在將來需要的時候,重現此次快照的內容了。
19
+
20
+ 現在,Git 倉庫中有五個物件:三個表示檔快照內容的 blob 物件;一個記錄著目錄樹內容及其中各個檔對應 blob 物件索引的 tree 物件;以及一個包含指向 tree 物件(根目錄)的索引和其他提交資訊中繼資料的 commit 物件。概念上來說,倉庫中的各個物件保存的資料和相互關係看起來如圖 3-1 所示:
21
+
22
+ Insert 18333fig0301.png
23
+ 圖 3-1. 單個提交物件在倉庫中的資料結構
24
+
25
+ 作些修改後再次提交,那麼這次的提交物件會包含一個指向上次提交物件的指標(譯注:即下圖中的 parent 物件)。兩次提交後,倉庫歷史會變成圖 3-2 的樣子:
26
+
27
+ Insert 18333fig0302.png
28
+ 圖 3-2. 多個提交物件之間的連結關係
29
+
30
+ 現在來談分支。Git 中的分支,其實本質上僅僅是個指向 commit 物件的可變指標。Git 會使用 master 作為分支的預設名字。在若干次提交後,你其實已經有了一個指向最後一次提交物件的 master 分支,它在每次提交的時候都會自動向前移動。
31
+
32
+ Insert 18333fig0303.png
33
+ 圖 3-3. 分支其實就是從某個提交物件往回看的歷史
34
+
35
+ 那麼,Git 又是如何創建一個新的分支的呢?答案很簡單,創建一個新的分支指標。比如新建一個 testing 分支,可以使用 `git branch` 命令:
36
+
37
+ $ git branch testing
38
+
39
+ 這會在當前 commit 物件上新建一個分支指標(見圖 3-4)。
40
+
41
+ Insert 18333fig0304.png
42
+ 圖 3-4. 多個分支指向提交資料的歷史
43
+
44
+ 那麼,Git 是如何知道你當前在哪個分支上工作的呢?其實答案也很簡單,它保存著一個名為 HEAD 的特別指標。請注意它和你熟知的許多其他版本控制系統(比如 Subversion 或 CVS)裡的 HEAD 概念大不相同。在 Git 中,它是一個指向你正在工作中的本地分支的指標(譯注:將 HEAD 想像為當前分支的別名。)。運行 `git branch` 命令,僅僅是建立了一個新的分支,但不會自動切換到這個分支中去,所以在這個例子中,我們依然還在 master 分支裡工作(參考圖 3-5)。
45
+
46
+ Insert 18333fig0305.png
47
+ 圖 3-5. HEAD 指向當前所在的分支
48
+
49
+ 要切換到其他分支,可以執行 `git checkout` 命令。我們現在轉換到新建的 testing 分支:
50
+
51
+ $ git checkout testing
52
+
53
+ 這樣 HEAD 就指向了 testing 分支(見圖3-6)。
54
+
55
+ Insert 18333fig0306.png
56
+ 圖 3-6. HEAD 在你轉換分支時指向新的分支
57
+
58
+ 這樣的實現方式會給我們帶來什麼好處呢?好吧,現在不妨再提交一次:
59
+
60
+ $ vim test.rb
61
+ $ git commit -a -m 'made a change'
62
+
63
+ 圖 3-7 展示了提交後的結果。
64
+
65
+ Insert 18333fig0307.png
66
+ 圖 3-7. 每次提交後 HEAD 隨著分支一起向前移動
67
+
68
+ 非常有趣,現在 testing 分支向前移動了一格,而 master 分支仍然指向原先 `git checkout` 時所在的 commit 物件。現在我們回到 master 分支看看:
69
+
70
+ $ git checkout master
71
+
72
+ 圖 3-8 顯示了結果。
73
+
74
+ Insert 18333fig0308.png
75
+ 圖 3-8. HEAD 在一次 checkout 之後移動到了另一個分支
76
+
77
+ 這條命令做了兩件事。它把 HEAD 指標移回到 master 分支,並把工作目錄中的檔換成了 master 分支所指向的快照內容。也就是說,現在開始所做的改動,將始於本專案中一個較老的版本。它的主要作用是將 testing 分支裡作出的修改暫時取消,這樣你就可以向另一個方向進行開發。
78
+
79
+ 我們作些修改後再次提交:
80
+
81
+ $ vim test.rb
82
+ $ git commit -a -m 'made other changes'
83
+
84
+ 現在我們的項目提交歷史產生了分叉(如圖 3-9 所示),因為剛才我們創建了一個分支,轉換到其中進行了一些工作,然後又回到原來的主分支進行了另外一些工作。這些改變分別孤立在不同的分支裡:我們可以在不同分支裡反復切換,並在時機成熟時把它們合併到一起。而所有這些工作,僅僅需要 `branch` 和 `checkout` 這兩條命令就可以完成。
85
+
86
+ Insert 18333fig0309.png
87
+ 圖 3-9. 不同流向的分支歷史
88
+
89
+ 由於 Git 中的分支實際上僅是一個包含所指物件校驗和(40 個字元長度 SHA-1 字串)的檔,所以創建和銷毀一個分支就變得非常廉價。說白了,新建一個分支就是向一個檔寫入 41 個位元組(外加一個分行符號)那麼簡單,當然也就很快了。
90
+
91
+ 這和大多數版本控制系統形成了鮮明對比,它們管理分支大多採取備份所有專案檔案到特定目錄的方式,所以根據專案檔案數量和大小不同,可能花費的時間也會有相當大的差別,快則幾秒,慢則數分鐘。而 Git 的實現與項目複雜度無關,它永遠可以在幾毫秒的時間內完成分支的創建和切換。同時,因為每次提交時都記錄了祖先資訊(譯注:即 `parent` 物件),將來要合併分支時,尋找恰當的合併基礎(譯注:即共同祖先)的工作其實已經自然而然地擺在那裡了,所以實現起來非常容易。Git 鼓勵開發者頻繁使用分支,正是因為有著這些特性作保障。
92
+
93
+ 接下來看看,我們為什麼應該頻繁使用分支。
94
+
95
+ ## 分支的新建與合併 ##
96
+
97
+ 現在讓我們來看一個簡單的分支與合併的例子,實際工作中大體也會用到這樣的工作流程:
98
+
99
+ 1. 開發某個網站。
100
+ 2. 為實現某個新的需求,創建一個分支。
101
+ 3. 在這個分支上開展工作。
102
+
103
+ 假設此時,你突然接到一個電話說有個很嚴重的問題需要緊急修補,那麼可以按照下面的方式處理:
104
+
105
+ 1. 返回到原先已經發佈到生產伺服器上的分支。
106
+ 2. 為這次緊急修補建立一個新分支,並在其中修復問題。
107
+ 3. 通過測試後,回到生產伺服器所在的分支,將修補分支合併進來,然後再推送到生產伺服器上。
108
+ 4. 切換到之前實現新需求的分支,繼續工作。
109
+
110
+ ### 分支的新建與切換 ###
111
+
112
+ 首先,我們假設你正在專案中愉快地工作,並且已經提交了幾次更新(見圖 3-10)。
113
+
114
+ Insert 18333fig0310.png
115
+ 圖 3-10. 一個簡短的提交歷史
116
+
117
+ 現在,你決定要修補問題追蹤系統上的 #53 問題。順帶說明下,Git 並不同任何特定的問題追蹤系統打交道。這裡為了說明要解決的問題,才把新建的分支取名為 iss53。要新建並切換到該分支,運行 `git checkout` 並加上 `-b` 參數:
118
+
119
+ $ git checkout -b iss53
120
+ Switched to a new branch 'iss53'
121
+
122
+ 這相當於執行下面這兩條命令:
123
+
124
+ $ git branch iss53
125
+ $ git checkout iss53
126
+
127
+ 圖 3-11 示意該命令的執行結果。
128
+
129
+ Insert 18333fig0311.png
130
+ 圖 3-11. 創建了一個新分支的指標
131
+
132
+ 接著你開始嘗試修復問題,在提交了若干次更新後,`iss53` 分支的指標也會隨著向前推進,因為它就是當前分支(換句話說,當前的 `HEAD` 指標正指向 `iss53`,見圖 3-12):
133
+
134
+ $ vim index.html
135
+ $ git commit -a -m 'added a new footer [issue 53]'
136
+
137
+ Insert 18333fig0312.png
138
+ 圖 3-12. iss53 分支隨工作進展向前推進
139
+
140
+ 現在你就接到了那個網站問題的緊急電話,需要馬上修補。有了 Git ,我們就不需要同時發佈這個補丁和 `iss53` 裡作出的修改,也不需要在創建和發佈該補丁到伺服器之前花費大力氣來復原這些修改。唯一需要的僅僅是切換回 `master` 分支。
141
+
142
+ 不過在此之前,留心你的暫存區或者工作目錄裡,那些還沒有提交的修改,它會和你即將檢出的分支產生衝突從而阻止 Git 為你切換分支。切換分支的時候最好保持一個清潔的工作區域。稍後會介紹幾個繞過這種問題的辦法(分別叫做 stashing 和 commit amending)。目前已經提交了所有的修改,所以接下來可以正常轉換到 `master` 分支:
143
+
144
+ $ git checkout master
145
+ Switched to branch 'master'
146
+
147
+ 此時工作目錄中的內容和你在解決問題 #53 之前一模一樣,你可以集中精力進行緊急修補。這一點值得牢記:Git 會把工作目錄的內容恢復為檢出某分支時它所指向的那個提交物件的快照。它會自動添加、刪除和修改檔以確保目錄的內容和你當時提交時完全一樣。
148
+
149
+ 接下來,你得進行緊急修補。我們創建一個緊急修補分支 `hotfix` 來開展工作,直到搞定(見圖 3-13):
150
+
151
+ $ git checkout -b hotfix
152
+ Switched to a new branch 'hotfix'
153
+ $ vim index.html
154
+ $ git commit -a -m 'fixed the broken email address'
155
+ [hotfix 3a0874c] fixed the broken email address
156
+ 1 files changed, 1 deletion(-)
157
+
158
+ Insert 18333fig0313.png
159
+ 圖 3-13. hotfix 分支是從 master 分支所在點分化出來的
160
+
161
+ 有必要作些測試,確保修補是成功的,然後回到 `master` 分支並把它合併進來,然後發佈到生產伺服器。用 `git merge` 命令來進行合併:
162
+
163
+ $ git checkout master
164
+ $ git merge hotfix
165
+ Updating f42c576..3a0874c
166
+ Fast-forward
167
+ README | 1 -
168
+ 1 file changed, 1 deletion(-)
169
+
170
+ 請注意,合併時出現了“Fast forward”的提示。由於當前 `master` 分支所在的提交物件是要併入的 `hotfix` 分支的直接上游,Git 只需把 `master` 分支指標直接右移。換句話說,如果順著一個分支走下去可以到達另一個分支的話,那麼 Git 在合併兩者時,只會簡單地把指標右移,因為這種單線的歷史分支不存在任何需要解決的分歧,所以這種合併過程可以稱為快進(Fast forward)。
171
+
172
+ 現在最新的修改已經在當前 `master` 分支所指向的提交物件中了,可以部署到生產伺服器上去了(見圖 3-14)。
173
+
174
+ Insert 18333fig0314.png
175
+ 圖 3-14. 合併之後,master 分支和 hotfix 分支指向同一位置。
176
+
177
+ 在那個超級重要的修補發佈以後,你想要回到被打擾之前的工作。由於當前 `hotfix` 分支和 `master` 都指向相同的提交物件,所以 `hotfix` 已經完成了歷史使命,可以刪掉了。使用 `git branch` 的 `-d` 選項執行刪除操作:
178
+
179
+ $ git branch -d hotfix
180
+ Deleted branch hotfix (was 3a0874c).
181
+
182
+ 現在回到之前未完成的 #53 問題修復分支上繼續工作(圖 3-15):
183
+
184
+ $ git checkout iss53
185
+ Switched to branch 'iss53'
186
+ $ vim index.html
187
+ $ git commit -a -m 'finished the new footer [issue 53]'
188
+ [iss53 ad82d7a] finished the new footer [issue 53]
189
+ 1 file changed, 1 insertion(+)
190
+
191
+ Insert 18333fig0315.png
192
+ 圖 3-15. iss53 分支可以不受影響繼續推進。
193
+
194
+ 值得注意的是之前 `hotfix` 分支的修改內容尚未包含到 `iss53` 中來。如果需要納入此次修補,可以用 `git merge master` 把 master 分支合併到 `iss53`;或者等 `iss53` 完成之後,再將 `iss53` 分支中的更新併入 `master`。
195
+
196
+ ### 分支的合併 ###
197
+
198
+ 在問題 #53 相關的工作完成之後,可以合併回 `master` 分支。實際操作同前面合併 `hotfix` 分支差不多,只需回到 `master` 分支,運行 `git merge` 命令指定要合併進來的分支:
199
+
200
+ $ git checkout master
201
+ $ git merge iss53
202
+ Auto-merging README
203
+ Merge made by the 'recursive' strategy.
204
+ README | 1 +
205
+ 1 file changed, 1 insertion(+)
206
+
207
+ 請注意,這次合併操作的底層實現,並不同於之前 `hotfix` 的併入方式。因為這次你的開發歷史是從更早的地方開始分叉的。由於當前 `master` 分支所指向的提交物件(C4)並不是 `iss53` 分支的直接祖先,Git 不得不進行一些額外處理。就此例而言,Git 會用兩個分支的末端(C4 和 C5)以及它們的共同祖先(C2)進行一次簡單的三方合併計算。圖 3-16 用紅框標出了 Git 用於合併的三個提交對象:
208
+
209
+ Insert 18333fig0316.png
210
+ 圖 3-16. Git 為分支合併自動識別出最佳的同源合併點。
211
+
212
+ 這次,Git 沒有簡單地把分支指標右移,而是對三方合併後的結果重新做一個新的快照,並自動創建一個指向它的提交物件(C6)(見圖 3-17)。這個提交物件比較特殊,它有兩個祖先(C4 和 C5)。
213
+
214
+ 值得一提的是 Git 可以自己裁決哪個共同祖先才是最佳合併基礎;這和 CVS 或 Subversion(1.5 以後的版本)不同,它們需要開發者手工指定合併基礎。所以此特性讓 Git 的合併操作比其他系統都要簡單不少。
215
+
216
+ Insert 18333fig0317.png
217
+ 圖 3-17. Git 自動創建了一個包含了合併結果的提交物件。
218
+
219
+ 既然之前的工作成果已經合併到 `master` 了,那麼 `iss53` 也就沒用了。你可以就此刪除它,並在問題追蹤系統裡關閉該問題。
220
+
221
+ $ git branch -d iss53
222
+
223
+ ### 遇到衝突時的分支合併 ###
224
+
225
+ 有時候合併操作並不會如此順利。如果在不同的分支中都修改了同一個檔的同一部分,Git 就無法乾淨地把兩者合到一起(譯注:邏輯上說,這種問題只能由人來裁決。)。如果你在解決問題 #53 的過程中修改了 `hotfix` 中修改的部分,將得到類似下面的結果:
226
+
227
+ $ git merge iss53
228
+ Auto-merging index.html
229
+ CONFLICT (content): Merge conflict in index.html
230
+ Automatic merge failed; fix conflicts and then commit the result.
231
+
232
+ Git 作了合併,但沒有提交,它會停下來等你解決衝突。要看看哪些檔在合併時發生衝突,可以用 `git status` 查閱:
233
+
234
+ $ git status
235
+ On branch master
236
+ You have unmerged paths.
237
+ (fix conflicts and run "git commit")
238
+
239
+ Unmerged paths:
240
+ (use "git add <file>..." to mark resolution)
241
+
242
+ both modified: index.html
243
+
244
+ no changes added to commit (use "git add" and/or "git commit -a")
245
+
246
+ 任何包含未解決衝突的檔都會以未合併(unmerged)的狀態列出。Git 會在有衝突的檔裡加入標準的衝突解決標記,可以通過它們來手工定位並解決這些衝突。可以看到此檔包含類似下面這樣的部分:
247
+
248
+ <<<<<<< HEAD
249
+ <div id="footer">contact : email.support@github.com</div>
250
+ =======
251
+ <div id="footer">
252
+ please contact us at support@github.com
253
+ </div>
254
+ >>>>>>> iss53
255
+
256
+ 可以看到 `=======` 隔開的上半部分,是 `HEAD`(即 `master` 分支,在運行 `merge` 命令時所切換到的分支)中的內容,下半部分是在 `iss53` 分支中的內容。解決衝突的辦法無非是二者選其一或者由你親自整合到一起。比如你可以通過把這段內容替換為下面這樣來解決:
257
+
258
+ <div id="footer">
259
+ please contact us at email.support@github.com
260
+ </div>
261
+
262
+ 這個解決方案各採納了兩個分支中的一部分內容,而且我還刪除了 `<<<<<<<`,`=======` 和 `>>>>>>>` 這些行。在解決了所有檔裡的所有衝突後,運行 `git add` 將把它們標記為已解決狀態(譯注:實際上就是來一次快照保存到暫存區域。)。因為一旦暫存,就表示衝突已經解決。如果你想用一個有圖形介面的工具來解決這些問題,不妨運行 `git mergetool`,它會調用一個視覺化的合併工具並引導你解決所有衝突:
263
+
264
+ $ git mergetool
265
+
266
+ This message is displayed because 'merge.tool' is not configured.
267
+ See 'git mergetool --tool-help' or 'git help config' for more details.
268
+ 'git mergetool' will now attempt to use one of the following tools:
269
+ opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge
270
+ Merging:
271
+ index.html
272
+
273
+ Normal merge conflict for 'index.html':
274
+ {local}: modified file
275
+ {remote}: modified file
276
+ Hit return to start merge resolution tool (opendiff):
277
+
278
+ 如果不想用默認的合併工具(Git 為我默認選擇了 `opendiff`,因為我在 Mac 上運行了該命令),你可以在上方"merge tool candidates"裡找到可用的合併工具列表,輸入你想用的工具名。我們將在第七章討論怎樣改變環境中的預設值。
279
+
280
+ 退出合併工具以後,Git 會詢問你合併是否成功。如果回答是,它會為你把相關檔暫存起來,以表明狀態為已解決。
281
+
282
+ 再運行一次 `git status` 來確認所有衝突都已解決:
283
+
284
+ $ git status
285
+ On branch master
286
+ Changes to be committed:
287
+ (use "git reset HEAD <file>..." to unstage)
288
+
289
+ modified: index.html
290
+
291
+
292
+ 如果覺得滿意了,並且確認所有衝突都已解決,也就是進入了暫存區,就可以用 `git commit` 來完成這次合併提交。提交的記錄差不多是這樣:
293
+
294
+ Merge branch 'iss53'
295
+
296
+ Conflicts:
297
+ index.html
298
+ #
299
+ # It looks like you may be committing a merge.
300
+ # If this is not correct, please remove the file
301
+ # .git/MERGE_HEAD
302
+ # and try again.
303
+ #
304
+
305
+ 如果想給將來看這次合併的人一些方便,可以修改該資訊,提供更多合併細節。比如你都作了哪些改動,以及這麼做的原因。有時候裁決衝突的理由並不直接或明顯,有必要略加注解。
306
+
307
+ ## 分支的管理 ##
308
+
309
+ 到目前為止,你已經學會了如何創建、合併和刪除分支。除此之外,我們還需要學習如何管理分支,在日後的常規工作中會經常用到下面介紹的管理命令。
310
+
311
+ `git branch` 命令不僅僅能創建和刪除分支,如果不加任何參數,它會給出當前所有分支的清單:
312
+
313
+ $ git branch
314
+ iss53
315
+ * master
316
+ testing
317
+
318
+ 注意看 `master` 分支前的 `*` 字元:它表示當前所在的分支。也就是說,如果現在提交更新,`master` 分支將隨著開發進度前移。若要查看各個分支最後一個提交物件的資訊,運行 `git branch -v`:
319
+
320
+ $ git branch -v
321
+ iss53 93b412c fix javascript issue
322
+ * master 7a98805 Merge branch 'iss53'
323
+ testing 782fd34 add scott to the author list in the readmes
324
+
325
+ 要從該清單中篩選出你已經(或尚未)與當前分支合併的分支,可以用 `--merged` 和 `--no-merged` 選項(Git 1.5.6 以上版本)。比如用 `git branch --merged` 查看哪些分支已被併入當前分支(譯注:也就是說哪些分支是當前分支的直接上游。):
326
+
327
+ $ git branch --merged
328
+ iss53
329
+ * master
330
+
331
+ 之前我們已經合併了 `iss53`,所以在這裡會看到它。一般來說,清單中沒有 `*` 的分支通常都可以用 `git branch -d` 來刪掉。原因很簡單,既然已經把它們所包含的工作整合到了其他分支,刪掉也不會損失什麼。
332
+
333
+ 另外可以用 `git branch --no-merged` 查看尚未合併的工作:
334
+
335
+ $ git branch --no-merged
336
+ testing
337
+
338
+ 它會顯示還未合併進來的分支。由於這些分支中還包含著尚未合併進來的工作成果,所以簡單地用 `git branch -d` 刪除該分支會提示錯誤,因為那樣做會丟失資料:
339
+
340
+ $ git branch -d testing
341
+ error: The branch 'testing' is not fully merged.
342
+ If you are sure you want to delete it, run 'git branch -D testing'.
343
+
344
+ 不過,如果你確實想要刪除該分支上的改動,可以用大寫的刪除選項 `-D` 強制執行,就像上面提示資訊中給出的那樣。
345
+
346
+ ## 利用分支進行開發的工作流程 ##
347
+
348
+ 現在我們已經學會了新建分支和合併分支,可以(或應該)用它來做點什麼呢?在本節,我們會介紹一些利用分支進行開發的工作流程。而正是由於分支管理的便捷,才衍生出了這類典型的工作模式,你可以根據專案的實際情況選擇一種用用看。
349
+
350
+ ### 長期分支 ###
351
+
352
+ 由於 Git 使用簡單的三方合併,所以就算在較長一段時間內,反復多次把某個分支合併到另一分支,也不是什麼難事。也就是說,你可以同時擁有多個開放的分支,每個分支用於完成特定的任務,隨著開發的推進,你可以隨時把某個特性分支的成果並到其他分支中。
353
+
354
+ 許多使用 Git 的開發者都喜歡用這種方式來開展工作,比如僅在 `master` 分支中保留完全穩定的代碼,即已經發佈或即將發佈的代碼。與此同時,他們還有一個名為 `develop` 或 `next` 的平行分支,專門用於後續的開發,或僅用於穩定性測試 — 當然並不是說一定要絕對穩定,不過一旦進入某種穩定狀態,便可以把它合併到 `master` 裡。這樣,在確保這些已完成的特性分支(短期分支,比如之前的 `iss53` 分支)能夠通過所有測試,並且不會引入更多錯誤之後,就可以並到主幹分支中,等待下一次的發佈。
355
+
356
+ 本質上我們剛才談論的,是隨著提交物件不斷右移的指標。穩定分支的指標總是在提交歷史中落後一大截,而前沿分支總是比較靠前(見圖 3-18)。
357
+
358
+ Insert 18333fig0318.png
359
+ 圖 3-18. 穩定分支總是比較老舊。
360
+
361
+ 或者把它們想像成工作流水線,或許更好理解一些,經過測試的提交物件集合被遴選到更穩定的流水線(見圖 3-19)。
362
+
363
+ Insert 18333fig0319.png
364
+ 圖 3-19. 想像成流水線可能會容易點。
365
+
366
+ 你可以用這招維護不同層次的穩定性。某些大專案還會有個 `proposed`(建議)或 `pu`(proposed updates,建議更新)分支,它包含著那些可能還沒有成熟到進入 `next` 或 `master` 的內容。這麼做的目的是擁有不同層次的穩定性:當這些分支進入到更穩定的水準時,再把它們合併到更高層分支中去。再次說明下,使用多個長期分支的做法並非必需,不過一般來說,對於特大型項目或特複雜的專案,這麼做確實更容易管理。
367
+
368
+ ### 特性分支 ###
369
+
370
+ 在任何規模的專案中都可以使用特性(Topic)分支。一個特性分支是指一個短期的,用來實現單一特性或與其相關工作的分支。可能你在以前的版本控制系統裡從未做過類似這樣的事情,因為通常創建與合併分支消耗太大。然而在 Git 中,一天之內建立、使用、合併再刪除多個分支是常見的事。
371
+
372
+ 我們在上節的例子裡已經見過這種用法了。我們創建了 `iss53` 和 `hotfix` 這兩個特性分支,在提交了若干更新後,把它們合併到主幹分支,然後刪除。該技術允許你迅速且完全的進行語境切換 — 因為你的工作分散在不同的流水線裡,每個分支裡的改變都和它的目標特性相關,流覽代碼之類的事情因而變得更簡單了。你可以把作出的改變保持在特性分支中幾分鐘,幾天甚至幾個月,等它們成熟以後再合併,而不用在乎它們建立的順序或者進度。
373
+
374
+ 現在我們來看一個實際的例子。請看圖 3-20,由下往上,起先我們在 `master` 工作到 C1,然後開始一個新分支 `iss91` 嘗試修復 91 號缺陷,提交到 C6 的時候,又冒出一個解決該問題的新辦法,於是從之前 C4 的地方又分出一個分支 `iss91v2`,幹到 C8 的時候,又回到主幹 `master` 中提交了 C9 和 C10,再回到 `iss91v2` 繼續工作,提交 C11,接著,又冒出個不太確定的想法,從 `master` 的最新提交 C10 處開了個新的分支 `dumbidea` 做些試驗。
375
+
376
+ Insert 18333fig0320.png
377
+ 圖 3-20. 擁有多個特性分支的提交歷史。
378
+
379
+ 現在,假定兩件事情:我們最終決定使用第二個解決方案,即 `iss91v2` 中的辦法;另外,我們把 `dumbidea` 分支拿給同事們看了以後,發現它竟然是個天才之作。所以接下來,我們準備拋棄原來的 `iss91` 分支(實際上會丟棄 C5 和 C6),直接在主幹中併入另外兩個分支。最終的提交歷史將變成圖 3-21 這樣:
380
+
381
+ Insert 18333fig0321.png
382
+ 圖 3-21. 合併了 dumbidea 和 iss91v2 後的分支歷史。
383
+
384
+ 請務必牢記這些分支全部都是本地分支,這一點很重要。當你在使用分支及合併的時候,一切都是在你自己的 Git 倉庫中進行的 — 完全不涉及與伺服器的交互。
385
+
386
+ ## 遠端分支 ##
387
+
388
+ 遠端分支(remote branch)是對遠端倉庫中的分支的索引。它們是一些無法移動的本地分支;只有在 Git 進行網路交互時才會更新。遠端分支就像是書簽,提醒著你上次連接遠端倉庫時上面各分支的位置。
389
+
390
+ 我們用 `(遠端倉庫名)/(分支名)` 這樣的形式表示遠端分支。比如我們想看看上次同 `origin` 倉庫通訊時 `master` 分支的樣子,就應該查看 `origin/master` 分支。如果你和同伴一起修復某個問題,但他們先推送了一個 `iss53` 分支到遠端倉庫,雖然你可能也有一個本地的 `iss53` 分支,但指向伺服器上最新更新的卻應該是 `origin/iss53` 分支。
391
+
392
+ 可能有點亂,我們不妨舉例說明。假設你們團隊有個地址為 `git.ourcompany.com` 的 Git 伺服器。如果你從這裡克隆,Git 會自動為你將此遠端倉庫命名為 `origin`,並下載其中所有的資料,建立一個指向它的 `master` 分支的指標,在本地命名為 `origin/master`,但你無法在本地更改其資料。接著,Git 建立一個屬於你自己的本地 `master` 分支,始於 `origin` 上 `master` 分支相同的位置,你可以就此開始工作(見圖 3-22):
393
+
394
+ Insert 18333fig0322.png
395
+ 圖 3-22. 一次 Git 克隆會建立你自己的本地分支 master 和遠端分支 origin/master,並且將它們都指向 `origin` 上的 `master` 分支。
396
+
397
+ 如果你在本地 `master` 分支做了些改動,與此同時,其他人向 `git.ourcompany.com` 推送了他們的更新,那麼伺服器上的 `master` 分支就會向前推進,而於此同時,你在本地的提交歷史正朝向不同方向發展。不過只要你不和伺服器通訊,你的 `origin/master` 指標仍然保持原位不會移動(見圖 3-23)。
398
+
399
+ Insert 18333fig0323.png
400
+ 圖 3-23. 在本地工作的同時有人向遠端倉庫推送內容會讓提交歷史開始分流。
401
+
402
+ 可以運行 `git fetch origin` 來同步遠端伺服器上的資料到本地。該命令首先找到 `origin` 是哪個伺服器(本例為 `git.ourcompany.com`),從上面獲取你尚未擁有的資料,更新你本地的資料庫,然後把 `origin/master` 的指針移到它最新的位置上(見圖 3-24)。
403
+
404
+ Insert 18333fig0324.png
405
+ 圖 3-24. git fetch 命令會更新 remote 索引。
406
+
407
+ 為了演示擁有多個遠端分支(在不同的遠端伺服器上)的專案是如何工作的,我們假設你還有另一個僅供你的敏捷開發小組使用的內部伺服器 `git.team1.ourcompany.com`。可以用第二章中提到的 `git remote add` 命令把它加為當前專案的遠端分支之一。我們把它命名為 `teamone`,以便代替完整的 Git URL 以方便使用(見圖 3-25)。
408
+
409
+ Insert 18333fig0325.png
410
+ 圖 3-25. 把另一個伺服器加為遠端倉庫
411
+
412
+ 現在你可以用 `git fetch teamone` 來獲取小組伺服器上你還沒有的資料了。由於當前該伺服器上的內容是你 `origin` 伺服器上的子集,Git 不會下載任何資料,而只是簡單地創建一個名為 `teamone/master` 的遠端分支,指向 `teamone` 伺服器上 `master` 分支所在的提交物件 `31b8e`(見圖 3-26)。
413
+
414
+ Insert 18333fig0326.png
415
+ 圖 3-26. 你在本地有了一個指向 teamone 伺服器上 master 分支的索引。
416
+
417
+ ### 推送本地分支 ###
418
+
419
+ 要想和其他人分享某個本地分支,你需要把它推送到一個你擁有寫許可權的遠端倉庫。你創建的本地分支不會因為你的寫入操作而被自動同步到你引入的遠端伺服器上,你需要明確地執行推送分支的操作。換句話說,對於無意分享的分支,你儘管保留為私人分支好了,而只推送那些協同工作要用到的特性分支。
420
+
421
+ 如果你有個叫 `serverfix` 的分支需要和他人一起開發,可以運行 `git push (遠端倉庫名) (分支名)`:
422
+
423
+ $ git push origin serverfix
424
+ Counting objects: 20, done.
425
+ Compressing objects: 100% (14/14), done.
426
+ Writing objects: 100% (15/15), 1.74 KiB, done.
427
+ Total 15 (delta 5), reused 0 (delta 0)
428
+ To git@github.com:schacon/simplegit.git
429
+ * [new branch] serverfix -> serverfix
430
+
431
+ 這裡其實走了一點捷徑。Git 自動把 `serverfix` 分支名擴展為 `refs/heads/serverfix:refs/heads/serverfix`,意為“取出我在本地的 serverfix 分支,推送到遠端倉庫的 serverfix 分支中去”。我們將在第九章進一步介紹 `refs/heads/` 部分的細節,不過一般使用的時候都可以省略它。也可以運行 `git push origin serverfix:serverfix` 來實現相同的效果,它的意思是“上傳我本地的 serverfix 分支到遠端倉庫中去,仍舊稱它為 serverfix 分支”。通過此語法,你可以把本地分支推送到某個命名不同的遠端分支:若想把遠端分支叫作 `awesomebranch`,可以用 `git push origin serverfix:awesomebranch` 來推送數據。
432
+
433
+ 接下來,當你的協作者再次從伺服器上獲取資料時,他們將得到一個新的遠端分支 `origin/serverfix`,並指向伺服器上 `serverfix` 所指向的版本:
434
+
435
+ $ git fetch origin
436
+ remote: Counting objects: 20, done.
437
+ remote: Compressing objects: 100% (14/14), done.
438
+ remote: Total 15 (delta 5), reused 0 (delta 0)
439
+ Unpacking objects: 100% (15/15), done.
440
+ From git@github.com:schacon/simplegit
441
+ * [new branch] serverfix -> origin/serverfix
442
+
443
+ 值得注意的是,在 `fetch` 操作下載好新的遠端分支之後,你仍然無法在本地編輯該遠端倉庫中的分支。換句話說,在本例中,你不會有一個新的 `serverfix` 分支,有的只是一個你無法移動的 `origin/serverfix` 指標。
444
+
445
+ 如果要把該遠端分支的內容合併到當前分支,可以運行 `git merge origin/serverfix`。如果想要一份自己的 `serverfix` 來開發,可以在遠端分支的基礎上分化出一個新的分支來:
446
+
447
+ $ git checkout -b serverfix origin/serverfix
448
+ Branch serverfix set up to track remote branch serverfix from origin.
449
+ Switched to a new branch 'serverfix'
450
+
451
+ 這會切換到新建的 `serverfix` 本地分支,其內容同遠端分支 `origin/serverfix` 一致,這樣你就可以在裡面繼續開發了。
452
+
453
+ ### 跟蹤遠端分支 ###
454
+
455
+ 從遠端分支 `checkout` 出來的本地分支,稱為 _跟蹤分支_ (tracking branch)。跟蹤分支是一種和某個遠端分支有直接聯繫的本地分支。在跟蹤分支裡輸入 `git push`,Git 會自行推斷應該向哪個伺服器的哪個分支推送資料。同樣,在這些分支裡運行 `git pull` 會獲取所有遠端索引,並把它們的資料都合併到本地分支中來。
456
+
457
+ 在克隆倉庫時,Git 通常會自動創建一個名為 `master` 的分支來跟蹤 `origin/master`。這正是 `git push` 和 `git pull` 一開始就能正常工作的原因。當然,你可以隨心所欲地設定為其它跟蹤分支,比如 `origin` 上除了 `master` 之外的其它分支。剛才我們已經看到了這樣的一個例子:`git checkout -b [分支名] [遠端名]/[分支名]`。如果你有 1.6.2 以上版本的 Git,還可以用 `--track` 選項簡化:
458
+
459
+ $ git checkout --track origin/serverfix
460
+ Branch serverfix set up to track remote branch serverfix from origin.
461
+ Switched to a new branch 'serverfix'
462
+
463
+ 要為本地分支設定不同于遠端分支的名字,只需在第一個版本的命令裡換個名字:
464
+
465
+ $ git checkout -b sf origin/serverfix
466
+ Branch sf set up to track remote branch serverfix from origin.
467
+ Switched to a new branch 'sf'
468
+
469
+ 現在你的本地分支 `sf` 會自動將推送和抓取資料的位置定位到 `origin/serverfix` 了。
470
+
471
+ ### 刪除遠端分支 ###
472
+
473
+ 如果不再需要某個遠端分支了,比如搞定了某個特性並把它合併進了遠端的 `master` 分支(或任何其他存放穩定代碼的分支),可以用這個非常無厘頭的語法來刪除它:`git push [遠程名] :[分支名]`。如果想在伺服器上刪除 `serverfix` 分支,運行下面的命令:
474
+
475
+ $ git push origin :serverfix
476
+ To git@github.com:schacon/simplegit.git
477
+ - [deleted] serverfix
478
+
479
+ 咚!伺服器上的分支沒了。你最好特別留心這一頁,因為你一定會用到那個命令,而且你很可能會忘掉它的語法。有種方便記憶這條命令的方法:記住我們不久前見過的 `git push [遠端名] [本地分支]:[遠端分支]` 語法,如果省略 `[本地分支]`,那就等於是在說“在這裡提取空白然後把它變成`[遠端分支]`”。
480
+
481
+ ## 分支的衍合 ##
482
+
483
+ 把一個分支中的修改整合到另一個分支的辦法有兩種:`merge` 和 `rebase`(譯注:`rebase` 的翻譯暫定為“衍合”,大家知道就可以了。)。在本章我們會學習什麼是衍合,如何使用衍合,為什麼衍合操作如此富有魅力,以及我們應該在什麼情況下使用衍合。
484
+
485
+ ### 基本的衍合操作 ###
486
+
487
+ 請回顧之前有關合併的一節(見圖 3-27),你會看到開發進程分叉到兩個不同分支,又各自提交了更新。
488
+
489
+ Insert 18333fig0327.png
490
+ 圖 3-27. 最初分叉的提交歷史。
491
+
492
+ 之前介紹過,最容易的整合分支的方法是 `merge` 命令,它會把兩個分支最新的快照(C3 和 C4)以及二者最新的共同祖先(C2)進行三方合併,合併的結果是產生一個新的提交物件(C5)。如圖 3-28 所示:
493
+
494
+ Insert 18333fig0328.png
495
+ 圖 3-28. 通過合併一個分支來整合分叉了的歷史。
496
+
497
+ 其實,還有另外一個選擇:你可以把在 C3 裡產生的變化補丁在 C4 的基礎上重新打一遍。在 Git 裡,這種操作叫做_衍合(rebase)_。有了 `rebase` 命令,就可以把在一個分支裡提交的改變移到另一個分支裡重放一遍。
498
+
499
+ 在上面這個例子中,運行:
500
+
501
+ $ git checkout experiment
502
+ $ git rebase master
503
+ First, rewinding head to replay your work on top of it...
504
+ Applying: added staged command
505
+
506
+ 它的原理是回到兩個分支最近的共同祖先,根據當前分支(也就是要進行衍合的分支 `experiment`)後續的歷次提交物件(這裡只有一個 C3),生成一系列檔補丁,然後以基底分支(也就是主幹分支 `master`)最後一個提交物件(C4)為新的出發點,逐個應用之前準備好的補丁檔,最後會生成一個新的合併提交物件(C3'),從而改寫 `experiment` 的提交歷史,使它成為 `master` 分支的直接下游,如圖 3-29 所示:
507
+
508
+ Insert 18333fig0329.png
509
+ 圖 3-29. 把 C3 裡產生的改變到 C4 上重演一遍。
510
+
511
+ 現在回到 `master` 分支,進行一次快進合併(見圖 3-30):
512
+
513
+ Insert 18333fig0330.png
514
+ 圖 3-30. master 分支的快進。
515
+
516
+ 現在的 C3' 對應的快照,其實和普通的三方合併,即上個例子中的 C5 對應的快照內容一模一樣了。雖然最後整合得到的結果沒有任何區別,但衍合能產生一個更為整潔的提交歷史。如果視察一個衍合過的分支的歷史記錄,看起來會更清楚:仿佛所有修改都是在一根線上先後進行的,儘管實際上它們原本是同時並行發生的。
517
+
518
+ 一般我們使用衍合的目的,是想要得到一個能在遠端分支上乾淨應用的補丁 — 比如某些項目你不是維護者,但想幫點忙的話,最好用衍合:先在自己的一個分支裡進行開發,當準備向主專案提交補丁的時候,根據最新的 `origin/master` 進行一次衍合操作然後再提交,這樣維護者就不需要做任何整合工作(譯注:實際上是把解決分支補丁同最新主幹代碼之間衝突的責任,化轉為由提交補丁的人來解決。),只需根據你提供的倉庫位址作一次快進合併,或者直接採納你提交的補丁。
519
+
520
+ 請注意,合併結果中最後一次提交所指向的快照,無論是通過衍合,還是三方合併,都會得到相同的快照內容,只不過提交歷史不同罷了。衍合是按照每行的修改次序重演一遍修改,而合併是把最終結果合在一起。
521
+
522
+ ### 有趣的衍合 ###
523
+
524
+ 衍合也可以放到其他分支進行,並不一定非得根據分化之前的分支。以圖 3-31 的歷史為例,我們為了給伺服器端代碼添加一些功能而創建了特性分支 `server`,然後提交 C3 和 C4。然後又從 C3 的地方再增加一個 `client` 分支來對用戶端代碼進行一些相應修改,所以提交了 C8 和 C9。最後,又回到 `server` 分支提交了 C10。
525
+
526
+ Insert 18333fig0331.png
527
+ 圖 3-31. 從一個特性分支裡再分出一個特性分支的歷史。
528
+
529
+ 假設在接下來的一次軟體發佈中,我們決定先把用戶端的修改並到主線中,而暫緩併入服務端軟體的修改(因為還需要進一步測試)。這個時候,我們就可以把基於 `server` 分支而非 `master` 分支的改變(即 C8 和 C9),跳過 `server` 直接放到 `master` 分支中重演一遍,但這需要用 `git rebase` 的 `--onto` 選項指定新的基底分支 `master`:
530
+
531
+ $ git rebase --onto master server client
532
+
533
+ 這好比在說:“取出 `client` 分支,找出 `client` 分支和 `server` 分支的共同祖先之後的變化,然後把它們在 `master` 上重演一遍”。是不是有點複雜?不過它的結果如圖 3-32 所示,非常酷(譯注:雖然 `client` 裡的 C8, C9 在 C3 之後,但這僅表明時間上的先後,而非在 C3 修改的基礎上進一步改動,因為 `server` 和 `client` 這兩個分支對應的代碼應該是兩套檔,雖然這麼說不是很嚴格,但應理解為在 C3 時間點之後,對另外的檔所做的 C8,C9 修改,放到主幹重演。):
534
+
535
+ Insert 18333fig0332.png
536
+ 圖 3-32. 將特性分支上的另一個特性分支衍合到其他分支。
537
+
538
+ 現在可以快進 `master` 分支了(見圖 3-33):
539
+
540
+ $ git checkout master
541
+ $ git merge client
542
+
543
+ Insert 18333fig0333.png
544
+ 圖 3-33. 快進 master 分支,使之包含 client 分支的變化。
545
+
546
+ 現在我們決定把 `server` 分支的變化也包含進來。我們可以直接把 `server` 分支衍合到 `master`,而不用手工切換到 `server` 分支後再執行衍合操作 — `git rebase [主分支] [特性分支]` 命令會先取出特性分支 `server`,然後在主分支 `master` 上重演:
547
+
548
+ $ git rebase master server
549
+
550
+ 於是,`server` 的進度應用到 `master` 的基礎上,如圖 3-34 所示:
551
+
552
+ Insert 18333fig0334.png
553
+ 圖 3-34. 在 master 分支上衍合 server 分支。
554
+
555
+ 然後就可以快進主幹分支 `master` 了:
556
+
557
+ $ git checkout master
558
+ $ git merge server
559
+
560
+ 現在 `client` 和 `server` 分支的變化都已經集成到主幹分支來了,可以刪掉它們了。最終我們的提交歷史會變成圖 3-35 的樣子:
561
+
562
+ $ git branch -d client
563
+ $ git branch -d server
564
+
565
+ Insert 18333fig0335.png
566
+ 圖 3-35. 最終的提交歷史
567
+
568
+ ### 衍合的風險 ###
569
+
570
+ 呃,奇妙的衍合也並非完美無缺,要用它得遵守一條準則:
571
+
572
+ **一旦分支中的提交物件發佈到公共倉庫,就千萬不要對該分支進行衍合操作。**
573
+
574
+ 如果你遵循這條金科玉律,就不會出差錯。否則,人民群眾會仇恨你,你的朋友和家人也會嘲笑你,唾棄你。
575
+
576
+ 在進行衍合的時候,實際上拋棄了一些現存的提交物件而創造了一些類似但不同的新的提交物件。如果你把原來分支中的提交物件發佈出去,並且其他人更新下載後在其基礎上開展工作,而稍後你又用 `git rebase` 拋棄這些提交物件,把新的重演後的提交物件發佈出去的話,你的合作者就不得不重新合併他們的工作,這樣當你再次從他們那裡獲取內容時,提交歷史就會變得一團糟。
577
+
578
+ 下面我們用一個實際例子來說明為什麼公開的衍合會帶來問題。假設你從一個中央伺服器克隆然後在它的基礎上搞了一些開發,提交歷史類似圖 3-36 所示:
579
+
580
+ Insert 18333fig0336.png
581
+ 圖 3-36. 克隆一個倉庫,在其基礎上工作一番。
582
+
583
+ 現在,某人在 C1 的基礎上做了些改變,並合併他自己的分支得到結果 C6,推送到中央伺服器。當你抓取並合併這些資料到你本地的開發分支中後,會得到合併結果 C7,歷史提交會變成圖 3-37 這樣:
584
+
585
+ Insert 18333fig0337.png
586
+ 圖 3-37. 抓取他人提交,併入自己主幹。
587
+
588
+ 接下來,那個推送 C6 上來的人決定用衍合取代之前的合併操作;繼而又用 `git push --force` 覆蓋了伺服器上的歷史,得到 C4'。而之後當你再從伺服器上下載最新提交後,會得到:
589
+
590
+ Insert 18333fig0338.png
591
+ 圖 3-38. 有人推送了衍合後得到的 C4',丟棄了你作為開發基礎的 C4 和 C6。
592
+
593
+ 下載更新後需要合併,但此時衍合產生的提交物件 C4' 的 SHA-1 校驗值和之前 C4 完全不同,所以 Git 會把它們當作新的提交物件處理,而實際上此刻你的提交歷史 C7 中早已經包含了 C4 的修改內容,於是合併操作會把 C7 和 C4' 合併為 C8(見圖 3-39):
594
+
595
+ Insert 18333fig0339.png
596
+ 圖 3-39. 你把相同的內容又合併了一遍,生成一個新的提交 C8。
597
+
598
+ C8 這一步的合併是遲早會發生的,因為只有這樣你才能和其他協作者提交的內容保持同步。而在 C8 之後,你的提交歷史裡就會同時包含 C4 和 C4',兩者有著不同的 SHA-1 校驗值,如果用 `git log` 查看歷史,會看到兩個提交擁有相同的作者日期與說明,令人費解。而更糟的是,當你把這樣的歷史推送到伺服器後,會再次把這些衍合後的提交引入到中央伺服器,進一步困擾其他人(譯注:這個例子中,出問題的責任方是那個發佈了 C6 後又用衍合發佈 C4' 的人,其他人會因此回饋雙重歷史到共用主幹,從而混淆大家的視聽。)。
599
+
600
+ 如果把衍合當成一種在推送之前清理提交歷史的手段,而且僅僅衍合那些尚未公開的提交物件,就沒問題。如果衍合那些已經公開的提交物件,並且已經有人基於這些提交物件開展了後續開發工作的話,就會出現叫人沮喪的麻煩。
601
+
602
+ ## 小結 ##
603
+
604
+ 讀到這裡,你應該已經學會了如何創建分支並切換到新分支,在不同分支間轉換,合併本地分支,把分支推送到共用伺服器上,使用共用分支與他人協作,以及在分享之前進行衍合。