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,691 @@
1
+ # Git и другие системы контроля версий #
2
+
3
+ Наш мир несовершенен. Как правило, вы не сможете моментально перевести любой проект, в котором вы участвуете, на использование Git'а. Иногда вам придётся иметь дело с проектами, использующими другую систему контроля версий, и, в большинстве случаев, этой системой будет Subversion. Первая часть этого раздела научит вас обращаться с `git svn` — встроенным в Git двухсторонним интерфейсом обмена с Subversion.
4
+
5
+ В какой-то момент, вы, возможно, захотите перевести свой существующий проект на Git. Вторая часть раздела расскажет о том, как провести миграцию: сначала с Subversion, потом с Perforce, и наконец, с помощью написания собственного сценария для нестандартных вариантов миграции.
6
+
7
+ ## Git и Subversion ##
8
+
9
+ В настоящее время большинство проектов с открытым исходным кодом, а также большое число корпоративных проектов, используют Subversion для управления своим исходным кодом. Это самая популярная на текущий момент система контроля версий с открытым исходным кодом, история её использования насчитывает около 10 лет. Кроме того, она очень похожа на CVS, систему, которая была самой популярной до Subversion.
10
+
11
+ Одна из замечательных особенностей Git'а — возможность двустороннего обмена с Subversion через интерфейс, называемый `git svn`. Этот инструмент позволяет использовать Git в качестве корректного клиента при работе с сервером Subversion. Так что вы можете пользоваться всеми локальными возможностями Git'а, а затем сохранять изменения на сервере Subversion так, как если бы использовали Subversion локально. То есть вы можете делать локальное ветвление и слияние, использовать индекс, перемещение и отбор патчей для переноса из одной ветви в другую (cherry-picking) и т.д., в то время как ваши коллеги будут продолжать использовать в разработке подход времён каменного века. Это хороший способ протащить Git в рабочее окружение своей компании и помочь коллегам разработчикам стать более эффективными, в то время как вы будете лоббировать переход полностью на Git. Интерфейс обмена с Subversion — это ворота в мир распределённых систем контроля версий.
12
+
13
+ ### git svn ###
14
+
15
+ Базовой командой в Git'е для всех команд, работающих с мостом к Subversion, является `git svn`. Ей предваряется любая команда. Она принимает довольно порядочное число команд, поэтому мы изучим из них те, которые наиболее часто используются, рассмотрев несколько небольших вариантов работы.
16
+
17
+ Важно отметить, что при использовании `git svn` вы взаимодействуете с Subversion — системой, которая намного менее «продвинута», чем Git. Хоть вы и умеете с лёгкостью делать локальное ветвление и слияние, как правило, лучше всего держать свою историю в как можно более линейном виде, используя перемещения (rebase) и избегая таких вещей, как одновременный обмен с удалённым Git-репозиторием.
18
+
19
+ Не переписывайте свою историю, попробуйте отправить изменения ещё раз, а также не отправляйте изменения в параллельный Git-репозиторий, используемый для совместной работы, одновременно с другими разработчиками, использующими Git. Subversion может иметь только одну единственную линейную историю изменений, сбить с толку которую очень и очень просто. Если вы работаете в команде, в которой некоторые разработчики используют Git, а другие Subversion, убедитесь, что для совместной работы все используют только SVN-сервер — это сильно упростит вам жизнь.
20
+
21
+ ### Настройка ###
22
+
23
+ Для того чтобы попробовать этот функционал в действии, вам понадобится доступ с правами на запись к обычному SVN-репозиторию. Если вы хотите повторить рассматриваемые примеры, вам нужно сделать доступную на запись копию моего тестового репозитория. Это можно сделать без труда с помощью утилиты `svnsync`, входящей в состав последних версий Subversion (по крайней мере после версии 1.4). Для этих примеров я создал новый Subversion-репозиторий на Google Code, который был частичной копией проекта `protobuf` (утилита кодирования структурированных данных для их передачи по сети).
24
+
25
+ Чтобы мы могли продолжить, прежде всего создайте новый локальный репозиторий Subversion:
26
+
27
+ $ mkdir /tmp/test-svn
28
+ $ svnadmin create /tmp/test-svn
29
+
30
+ Затем разрешите всем пользователям изменять `revprops` — самым простым способом сделать это будет добавление сценария `pre-revprop-change`, который просто всегда завершается с кодом 0:
31
+
32
+ $ cat /tmp/test-svn/hooks/pre-revprop-change
33
+ #!/bin/sh
34
+ exit 0;
35
+ $ chmod +x /tmp/test-svn/hooks/pre-revprop-change
36
+
37
+ Теперь вы можете синхронизировать проект со своей локальной машиной, вызвав `svnsync init` с параметрами, задающими исходный и целевой репозиторий:
38
+
39
+ $ svnsync init file:///tmp/test-svn http://progit-example.googlecode.com/svn/
40
+
41
+ Эта команда подготовит процесс синхронизации. Затем склонируйте код, выполнив:
42
+
43
+ $ svnsync sync file:///tmp/test-svn
44
+ Committed revision 1.
45
+ Copied properties for revision 1.
46
+ Committed revision 2.
47
+ Copied properties for revision 2.
48
+ Committed revision 3.
49
+ ...
50
+
51
+ Хотя выполнение этой операции и может занять всего несколько минут, однако, если вы попробуете скопировать исходный репозиторий в другой удалённый репозиторий, а не в локальный, то процесс займёт почти час, хотя в этом проекте менее ста коммитов. Subversion вынужден клонировать ревизии по одной, а затем отправлять их в другой репозиторий — это чудовищно неэффективно, однако это единственный простой способ выполнить это действие.
52
+
53
+ ### Приступим к работе ###
54
+
55
+ Теперь, когда в вашем распоряжении имеется SVN-репозиторий, для которого вы имеете право на запись, давайте выполним типичные действия по работе с СКВ. Начнём с команды `git svn clone`, которая импортирует весь SVN-репозиторий в локальный Git-репозиторий. Помните, что если вы производите импорт из настоящего удалённого SVN-репозитория, вам надо заменить `file:///tmp/test-svn` на реальный адрес вашего SVN-репозитория:
56
+
57
+ $ git svn clone file:///tmp/test-svn -T trunk -b branches -t tags
58
+ Initialized empty Git repository in /Users/schacon/projects/testsvnsync/svn/.git/
59
+ r1 = b4e387bc68740b5af56c2a5faf4003ae42bd135c (trunk)
60
+ A m4/acx_pthread.m4
61
+ A m4/stl_hash.m4
62
+ ...
63
+ r75 = d1957f3b307922124eec6314e15bcda59e3d9610 (trunk)
64
+ Found possible branch point: file:///tmp/test-svn/trunk => \
65
+ file:///tmp/test-svn /branches/my-calc-branch, 75
66
+ Found branch parent: (my-calc-branch) d1957f3b307922124eec6314e15bcda59e3d9610
67
+ Following parent with do_switch
68
+ Successfully followed parent
69
+ r76 = 8624824ecc0badd73f40ea2f01fce51894189b01 (my-calc-branch)
70
+ Checked out HEAD:
71
+ file:///tmp/test-svn/branches/my-calc-branch r76
72
+
73
+ Эта команда эквивалентна выполнению для указанного вами URL двух команд — `git svn init`, а затем `git svn fetch`. Процесс может занять некоторое время. Тестовый проект имеет всего лишь около 75 коммитов, и кода там не очень много, так что, скорее всего, вам придётся подождать всего несколько минут. Однако, Git должен по отдельности проверить и выполнить коммит для каждой версии. Для проектов, имеющих историю с сотнями и тысячами изменений, этот процесс может занять несколько часов или даже дней.
74
+
75
+ Часть команды `-T trunk -b branches -t tags` сообщает Git'у, что этот SVN-репозиторий следует стандартным соглашениям о ветвлении и метках. Если вместо trunk, branches и tags вы используете какие-то другие, нестандартные имена, то должны изменить эти параметры соответствующим образом. В связи с тем, что такие соглашения являются общепринятыми, вы можете использовать короткий формат, заменив всю эту часть на `-s`, заменяющую собой все эти параметры. Следующая команда эквивалента предыдущей:
76
+
77
+ $ git svn clone file:///tmp/test-svn -s
78
+
79
+ Таким образом, вы должны были получить корректный Git-репозиторий с импортированными ветками и метками:
80
+
81
+ $ git branch -a
82
+ * master
83
+ my-calc-branch
84
+ tags/2.0.2
85
+ tags/release-2.0.1
86
+ tags/release-2.0.2
87
+ tags/release-2.0.2rc1
88
+ trunk
89
+
90
+ Важно отметить, что эта утилита именует ваши ссылки на удалённые ресурсы по-другому. Когда вы клонируете обычный Git-репозиторий, вы получаете все ветки с удалённого сервера на локальном компьютере в виде: `origin/[ветка]` — в пространстве имён с именем удалённого сервера. Однако, `git svn` полагает, что у вас не будет множества удалённых источников данных и сохраняет все ссылки на всякое, находящееся на удалённом сервере, без пространства имён. Для просмотра всех имён ссылок вы можете использовать служебную команду Git'а `show-ref`:
91
+
92
+ $ git show-ref
93
+ 1cbd4904d9982f386d87f88fce1c24ad7c0f0471 refs/heads/master
94
+ aee1ecc26318164f355a883f5d99cff0c852d3c4 refs/remotes/my-calc-branch
95
+ 03d09b0e2aad427e34a6d50ff147128e76c0e0f5 refs/remotes/tags/2.0.2
96
+ 50d02cc0adc9da4319eeba0900430ba219b9c376 refs/remotes/tags/release-2.0.1
97
+ 4caaa711a50c77879a91b8b90380060f672745cb refs/remotes/tags/release-2.0.2
98
+ 1c4cb508144c513ff1214c3488abe66dcb92916f refs/remotes/tags/release-2.0.2rc1
99
+ 1cbd4904d9982f386d87f88fce1c24ad7c0f0471 refs/remotes/trunk
100
+
101
+ Обычный Git-репозиторий выглядит скорее так:
102
+
103
+ $ git show-ref
104
+ 83e38c7a0af325a9722f2fdc56b10188806d83a1 refs/heads/master
105
+ 3e15e38c198baac84223acfc6224bb8b99ff2281 refs/remotes/gitserver/master
106
+ 0a30dd3b0c795b80212ae723640d4e5d48cabdff refs/remotes/origin/master
107
+ 25812380387fdd55f916652be4881c6f11600d6f refs/remotes/origin/testing
108
+
109
+ Здесь два удалённых сервера: один с именем `gitserver` и веткой `master`, и другой с именем `origin` с двумя ветками: `master` и `testing`.
110
+
111
+ Обратите внимание, что в примере, где ссылки импортированы из `git svn`, метки были добавлены в Git как удалённые ветки, а не как настоящие метки. Импортированные из Subversion данные выглядят так, как будто под именами меток с удалённого ресурса скрываются ветки.
112
+
113
+ ### Коммит в Subversion ###
114
+
115
+ Теперь, когда у вас есть рабочий репозиторий, вы можете выполнить какую-либо работу с кодом и выполнить коммит в апстрим, эффективно используя Git в качестве SVN-клиента. Если вы редактировали один из файлов и закоммитили его, то вы внесли изменение в локальный Git-репозиторий, которое пока не существует на Subversion-сервере:
116
+
117
+ $ git commit -am 'Adding git-svn instructions to the README'
118
+ [master 97031e5] Adding git-svn instructions to the README
119
+ 1 files changed, 1 insertions(+), 1 deletions(-)
120
+
121
+ После этого вам надо отправить изменения в апстрим. Обратите внимание, как Git изменяет способ работы с Subversion — вы можете сделать несколько коммитов оффлайн, а затем отправить их разом на Subversion-сервер. Для передачи изменений на Subversion-сервер требуется выполнить команду `git svn dcommit`:
122
+
123
+ $ git svn dcommit
124
+ Committing to file:///tmp/test-svn/trunk ...
125
+ M README.txt
126
+ Committed r79
127
+ M README.txt
128
+ r79 = 938b1a547c2cc92033b74d32030e86468294a5c8 (trunk)
129
+ No changes between current HEAD and refs/remotes/trunk
130
+ Resetting to the latest refs/remotes/trunk
131
+
132
+ Это действие возьмёт все коммиты, сделанные поверх того, что есть в SVN-репозитории, выполнит коммит в Subversion для каждого из них, а затем перепишет ваш локальный коммит в Git'е, чтобы добавить к нему уникальный идентификатор. Это важно, поскольку это означает, что изменятся все SHA-1 контрольные суммы ваших коммитов. В частности и поэтому работать с одним и тем же проектом одновременно и через Git, и через Subversion — это плохая идея. Взглянув на последний коммит, вы увидите, что добавился новый `git-svn-id`:
133
+
134
+ $ git log -1
135
+ commit 938b1a547c2cc92033b74d32030e86468294a5c8
136
+ Author: schacon <schacon@4c93b258-373f-11de-be05-5f7a86268029>
137
+ Date: Sat May 2 22:06:44 2009 +0000
138
+
139
+ Adding git-svn instructions to the README
140
+
141
+ git-svn-id: file:///tmp/test-svn/trunk@79 4c93b258-373f-11de-be05-5f7a86268029
142
+
143
+ Обратите внимание — контрольная сумма SHA, которая начиналась с `97031e5` когда вы делали коммит, теперь начинается с `938b1a5`. Если вы хотите отправить изменения как на Git-сервер, так и на SVN-сервер, вы должны отправить их (`dcommit`) сначала на Subversion-сервер, поскольку это действие изменит отправляемые данные.
144
+
145
+ ### Получение новых изменений ###
146
+
147
+ Если вы работаете вместе с другими разработчиками, значит, когда-нибудь вам придётся столкнуться с ситуацией, когда кто-то из вас отправит изменения на сервер, а другой, в свою очередь, будет пытаться отправить свои изменения, конфликтующие с первыми. Это изменение не будет принято до тех пор, пока вы не сольёте себе чужую работу. В `git svn` эта ситуация выглядит следующим образом:
148
+
149
+ $ git svn dcommit
150
+ Committing to file:///tmp/test-svn/trunk ...
151
+ Merge conflict during commit: Your file or directory 'README.txt' is probably \
152
+ out-of-date: resource out of date; try updating at /Users/schacon/libexec/git-\
153
+ core/git-svn line 482
154
+
155
+ Для разрешения этой проблемы вам нужно выполнить команду `git svn rebase`, которая получит все изменения, имеющиеся на сервере, которых ещё нет на вашей локальной машине, и переместит все ваши недавние изменения поверх того, что было на сервере:
156
+
157
+ $ git svn rebase
158
+ M README.txt
159
+ r80 = ff829ab914e8775c7c025d741beb3d523ee30bc4 (trunk)
160
+ First, rewinding head to replay your work on top of it...
161
+ Applying: first user change
162
+
163
+ Теперь все ваши изменения находятся сверху того, что есть на SVN-сервере, так что вы можете спокойно выполнить `dcommit`:
164
+
165
+ $ git svn dcommit
166
+ Committing to file:///tmp/test-svn/trunk ...
167
+ M README.txt
168
+ Committed r81
169
+ M README.txt
170
+ r81 = 456cbe6337abe49154db70106d1836bc1332deed (trunk)
171
+ No changes between current HEAD and refs/remotes/trunk
172
+ Resetting to the latest refs/remotes/trunk
173
+
174
+ Следует помнить, что в отличие от Git'а, который требует сливать себе изменения в апстриме, которых у вас ещё нет локально, перед тем как отправить свои изменения, `git svn` заставляет делать такое только в случае конфликта правок. Если кто-либо внесёт изменения в один файл, а вы внесёте изменения в другой, команда `dcommit` сработает без ошибок:
175
+
176
+ $ git svn dcommit
177
+ Committing to file:///tmp/test-svn/trunk ...
178
+ M configure.ac
179
+ Committed r84
180
+ M autogen.sh
181
+ r83 = 8aa54a74d452f82eee10076ab2584c1fc424853b (trunk)
182
+ M configure.ac
183
+ r84 = cdbac939211ccb18aa744e581e46563af5d962d0 (trunk)
184
+ W: d2f23b80f67aaaa1f6f5aaef48fce3263ac71a92 and refs/remotes/trunk differ, \
185
+ using rebase:
186
+ :100755 100755 efa5a59965fbbb5b2b0a12890f1b351bb5493c18 \
187
+ 015e4c98c482f0fa71e4d5434338014530b37fa6 M autogen.sh
188
+ First, rewinding head to replay your work on top of it...
189
+ Nothing to do.
190
+
191
+ Это важно помнить, поскольку последствием этих действий может стать такое состояние проекта, которого нет ни на одном из ваших компьютеров. Если изменения несовместимы, но не ведут к конфликту изменений, у вас могут возникнуть проблемы, которые трудно будет диагностировать. Это отличается от работы с Git-сервером — в Git'е вы можете полностью проверить состояние проекта на клиентских машинах до публикации, в то время как в SVN вы не можете даже быть уверены в том, что состояние проекта непосредственно перед коммитом и после него идентично.
192
+
193
+ Кроме того, вам нужно выполнить следующую команду для получения изменений с сервера Subversion, даже если вы не готовы сами сделать коммит. Вы можете выполнить `git svn fetch` для получения новых данных, но `git svn rebase` и извлечёт новые данные с сервера, и обновит ваши локальные коммиты.
194
+
195
+ $ git svn rebase
196
+ M generate_descriptor_proto.sh
197
+ r82 = bd16df9173e424c6f52c337ab6efa7f7643282f1 (trunk)
198
+ First, rewinding head to replay your work on top of it...
199
+ Fast-forwarded master to refs/remotes/trunk.
200
+
201
+ Выполняйте команду `git svn rebase` периодически, чтобы быть уверенным в том, что ваш код имеет самую свежую версию. Перед выполнением этой команды убедитесь, что ваш рабочий каталог чист. Если нет, вы должны либо «спрятать» свои изменения, либо временно закоммитить их перед выполнением `git svn rebase`, иначе выполнение этой команды прекратится, если она обнаружит возникновение конфликта слияния.
202
+
203
+ ### Проблемы с ветвлением в Git ###
204
+
205
+ После того как вы привыкли к работе с Git'ом, вы наверняка будете создавать ветки для работы над отдельными задачами, а затем сливать их. Если вы отправляете изменения на Subversion-сервер через `git svn`, вам, скорее всего, потребуется перемещать свою работу каждый раз в одну ветку, а не сливать ветки вместе. Причина, по которой предпочтение должно быть отдано именно такому подходу, заключается в том, что Subversion имеет линейную историю изменений и не может обрабатывать слияния так, как это делает Git. Поэтому `git svn` проходит только по первым родителям при конвертации снимков состояния в коммиты Subversion.
206
+
207
+ Допустим, что история изменений выглядит следующим образом: вы создали ветку `experiment`, сделали два коммита, а затем слили их в ветку `master`. Если вы выполните `dcommit`, результат будет следующим:
208
+
209
+ $ git svn dcommit
210
+ Committing to file:///tmp/test-svn/trunk ...
211
+ M CHANGES.txt
212
+ Committed r85
213
+ M CHANGES.txt
214
+ r85 = 4bfebeec434d156c36f2bcd18f4e3d97dc3269a2 (trunk)
215
+ No changes between current HEAD and refs/remotes/trunk
216
+ Resetting to the latest refs/remotes/trunk
217
+ COPYING.txt: locally modified
218
+ INSTALL.txt: locally modified
219
+ M COPYING.txt
220
+ M INSTALL.txt
221
+ Committed r86
222
+ M INSTALL.txt
223
+ M COPYING.txt
224
+ r86 = 2647f6b86ccfcaad4ec58c520e369ec81f7c283c (trunk)
225
+ No changes between current HEAD and refs/remotes/trunk
226
+ Resetting to the latest refs/remotes/trunk
227
+
228
+ Выполнение `dcommit` для ветки с объединённой историей не вызовет никаких проблем. Однако, если вы посмотрите на историю проекта в Git'е, то увидите, что ни один из коммитов, которые вы сделали в ветке `experiment` не были переписаны — вместо этого, все эти изменения появятся в SVN версии как один объединённый коммит.
229
+
230
+ Когда кто-нибудь склонирует себе эту работу, всё, что он увидит — это коммит, в котором все изменения слиты воедино; он не увидит данных о том, откуда они взялись и когда они были внесены.
231
+
232
+ ### Ветвление в Subversion ###
233
+
234
+ Работа с ветвями в Subversion отличается от таковой в Git'е; если у вас есть возможность избегать её, то это, наверное, лучший вариант. Хотя, вы можете создавать и вносить изменения в ветки в Subversion, используя `git svn`.
235
+
236
+ #### Создание новой ветки в SVN ####
237
+
238
+ Для того чтобы создать новую ветку в Subversion, выполните `git svn branch [имя ветки]`:
239
+
240
+ $ git svn branch opera
241
+ Copying file:///tmp/test-svn/trunk at r87 to file:///tmp/test-svn/branches/opera...
242
+ Found possible branch point: file:///tmp/test-svn/trunk => \
243
+ file:///tmp/test-svn/branches/opera, 87
244
+ Found branch parent: (opera) 1f6bfe471083cbca06ac8d4176f7ad4de0d62e5f
245
+ Following parent with do_switch
246
+ Successfully followed parent
247
+ r89 = 9b6fe0b90c5c9adf9165f700897518dbc54a7cbf (opera)
248
+
249
+ Эта команда эквивалентна команде Subversion `svn copy trunk branches/opera` и выполняется на Subversion-сервере. Важно отметить, что эта команда не переключает вас на указанную ветку. Так что, если вы сейчас сделаете коммит, он попадёт на сервере в `trunk`, а не в `opera`.
250
+
251
+ ### Переключение активных веток ###
252
+
253
+ Git определяет ветку, в которую он отправит ваши коммиты при выполнении `dcommit`, ища верхушку Subversion-ветки в вашей истории — она должна быть одна и она должна быть последней в текущей истории веток, имеющей метку `git-svn-id`.
254
+
255
+ Если вы хотите работать одновременно с несколькими ветками, вы можете настроить локальные ветки на внесение изменений через `dcommit` в конкретные ветки Subversion, начиная их на основе импортированного SVN-коммита для нужной ветки. Если вам нужна ветка `opera`, в которой вы можете поработать отдельно, можете выполнить:
256
+
257
+ $ git branch opera remotes/opera
258
+
259
+ Теперь, если вы захотите слить ветку `opera` в `trunk` (вашу ветку `master`), вы сможете сделать это с помощью обычной команды `git merge`. Однако вам потребуется добавить подробное описание к коммиту (через параметр `-m`), иначе при слиянии комментарий будет иметь вид «Merge branch opera» вместо чего-нибудь полезного.
260
+
261
+ Помните, что хотя вы и используете `git merge` для этой операции, и слияние, скорее всего, произойдёт намного проще, чем было бы в Subversion (потому что Git автоматически определяет подходящую основу для слияния), оно не является обычным коммитом-слиянием в Git'е. Вы должны передать данные обратно на сервер в Subversion, который не способен справиться с коммитом, имеющим более одного родителя, так что после передачи этот коммит будет выглядеть как один коммит, в который затолканы все изменения с другой ветки. После того как вы сольёте одну ветку в другую, вы не сможете просто так вернуться к работе над ней, как могли бы в Git'е. Команда `dcommit` удаляет всю информацию о том, какая ветка была влита, так что последующие вычисления базы слияния будут неверными — команда `dcommit` сделает результаты выполнения `git merge` такими же, какими они были бы после выполнения `git merge --squash`. К сожалению, избежать подобной ситуации вряд ли удастся — Subversion не способен сохранять подобную информацию, так что вы всегда будете связаны этими ограничениями. Во избежание проблем вы должны удалить локальную ветку (в нашем случае `opera`) после того, как вы вольёте её в `trunk`.
262
+
263
+ ### Команды Subversion ###
264
+
265
+ Набор утилит `git svn` предоставляет в ваше распоряжение несколько команд для облегчения перехода на Git, путём предоставления функциональности, подобной той, которую вы имеете в Subversion. Ниже приведены несколько команд, которые дают вам то, что вы имели в Subversion.
266
+
267
+ #### Просмотр истории в стиле SVN ####
268
+
269
+ Если вы привыкли к Subversion и хотите просматривать историю в стиле SVN, выполните команду `git svn log`, чтобы увидеть историю коммитов в таком же формате, как в SVN:
270
+
271
+ $ git svn log
272
+ ------------------------------------------------------------------------
273
+ r87 | schacon | 2009-05-02 16:07:37 -0700 (Sat, 02 May 2009) | 2 lines
274
+
275
+ autogen change
276
+
277
+ ------------------------------------------------------------------------
278
+ r86 | schacon | 2009-05-02 16:00:21 -0700 (Sat, 02 May 2009) | 2 lines
279
+
280
+ Merge branch 'experiment'
281
+
282
+ ------------------------------------------------------------------------
283
+ r85 | schacon | 2009-05-02 16:00:09 -0700 (Sat, 02 May 2009) | 2 lines
284
+
285
+ updated the changelog
286
+
287
+ Вы должны знать две важные вещи о команде `git svn log`. Во-первых, она работает в оффлайне, в отличие от оригинальной команды `svn log`, которая запрашивает информацию с Subversion-сервера. Во-вторых, эта команда отображает только те коммиты, которые были переданы на Subversion-сервер. Локальные Git-коммиты, которые вы ещё не отправили с помощью `dcommit`, не будут отображаться, равно как и коммиты, отправленные на Subversion-сервер другими людьми с момента последнего выполнения `dcommit`. Результат действия этой команды скорее похож на последнее известное состояние изменений на Subversion-сервере.
288
+
289
+ #### SVN-Аннотации ####
290
+
291
+ Так же как команда `git svn log` симулирует в оффлайне команду `svn log`, эквивалентом команды `svn annotate` является команда `git svn blame [ФАЙЛ]`. Её вывод выглядит следующим образом:
292
+
293
+ $ git svn blame README.txt
294
+ 2 temporal Protocol Buffers - Google's data interchange format
295
+ 2 temporal Copyright 2008 Google Inc.
296
+ 2 temporal http://code.google.com/apis/protocolbuffers/
297
+ 2 temporal
298
+ 22 temporal C++ Installation - Unix
299
+ 22 temporal =======================
300
+ 2 temporal
301
+ 79 schacon Committing in git-svn.
302
+ 78 schacon
303
+ 2 temporal To build and install the C++ Protocol Buffer runtime and the Protocol
304
+ 2 temporal Buffer compiler (protoc) execute the following:
305
+ 2 temporal
306
+
307
+ Опять же, эта команда не показывает коммиты, которые вы сделали локально в Git'е или те, которые за то время были отправлены на Subversion-сервер.
308
+
309
+ #### Информация о SVN-сервере ####
310
+
311
+ Вы можете получить ту же информацию, которую даёт выполнение команды `svn info`, выполнив команду `git svn info`:
312
+
313
+ $ git svn info
314
+ Path: .
315
+ URL: https://schacon-test.googlecode.com/svn/trunk
316
+ Repository Root: https://schacon-test.googlecode.com/svn
317
+ Repository UUID: 4c93b258-373f-11de-be05-5f7a86268029
318
+ Revision: 87
319
+ Node Kind: directory
320
+ Schedule: normal
321
+ Last Changed Author: schacon
322
+ Last Changed Rev: 87
323
+ Last Changed Date: 2009-05-02 16:07:37 -0700 (Sat, 02 May 2009)
324
+
325
+ Так же, как `blame` и `log`, эта команда выполняется оффлайн и выводит информацию, актуальную на момент последнего вашего обращения к серверу Subversion.
326
+
327
+ #### Игнорирование того, что игнорирует Subversion ####
328
+
329
+ Если вы клонируете Subversion-репозиторий, в котором где-то установлены свойства `svn:ignore`, скорее всего, вы захотите создать соответствующие им файлы `.gitignore`, чтобы ненароком не добавить в коммит те файлы, которые не стоит добавлять. Для решения этой проблемы в `git svn` имеется две команды. Первая — `git svn create-ignore` — автоматически создаст соответствующие файлы `.gitignore`, которые вы затем можете добавить в свой следующий коммит.
330
+
331
+ Вторая команда — `git svn show-ignore`, которая выводит на стандартный вывод строки, которые вы должны включить в файл `.gitignore`. Таким образом, вы можете перенаправить вывод этой команды в файл исключений вашего проекта:
332
+
333
+ $ git svn show-ignore > .git/info/exclude
334
+
335
+ Поступая таким образом, вы не захламляете проект файлами `.gitignore`. Это правильный подход, если вы являетесь единственным пользователем Git'а в команде, использующей Subversion, и ваши коллеги выступают против наличия файлов `.gitignore` в проекте.
336
+
337
+ ### Заключение по Git-Svn ###
338
+
339
+ Утилиты `git svn` полезны в том случае, если ваша разработка по каким-то причинам требует наличия рабочего Subversion-сервера. Однако, вам стоит смотреть на Git, использующий мост в Subversion, как на урезанную версию Git'а. В противном случае вы столкнётесь с проблемами в преобразованиях, которые могут сбить с толку вас и ваших коллег. Чтобы избежать неприятностей, старайтесь следовать следующим рекомендациям:
340
+
341
+ * Держите историю в Git линейной, чтобы она не содержала коммитов-слияний, сделанных с помощью `git merge`. Перемещайте всю работу, которую вы выполняете вне основной ветки обратно в неё; не выполняйте слияний.
342
+ * Не устанавливайте отдельный Git-сервер для совместной работы. Можно иметь один такой сервер для того, чтобы ускорить клонирование для новых разработчиков, но не отправляйте на него ничего, не имеющего записи `git-svn-id`. Возможно, стоит даже добавить перехватчик `pre-receive`, который будет проверять каждый коммит на наличие `git-svn-id` и отклонять `git push`, если коммиты не имеют такой записи.
343
+
344
+ При следовании этим правилам, работа с Subversion-сервером может быть более-менее сносной. Однако, если возможен перенос проекта на реальный Git-сервер, преимущества от этого перехода дадут вашему проекту намного больше.
345
+
346
+ ## Миграция на Git ##
347
+
348
+ Если вы решили начать использовать Git, а у вас уже есть база исходного кода в другой СКВ, вам придётся как-то мигрировать свой проект. Этот раздел описывает некоторые из включённых в состав Git'а инструментов для импортирования проектов из самых распространённых систем, в конце описывается создание вашего собственного инструмента для импортирования.
349
+
350
+ ### Импортирование ###
351
+
352
+ Вы научитесь импортировать данные из двух самых популярных систем контроля версий — Subversion и Perforce — поскольку они охватывают большинство пользователей, которые переходят на Git, а также потому, что для обеих систем созданы высококлассные инструменты, которые поставляются в составе Git'а.
353
+
354
+ ### Subversion ###
355
+
356
+ Если вы прочли предыдущий раздел об использовании `git svn`, можете с лёгкостью воспользоваться имеющимися там инструкциями для клонирования репозитория через `git svn clone`. Затем можете отказаться от использования Subversion-сервера и отправлять изменения на новый Git-сервер, и использовать уже его. Вытащить историю изменений можно так же быстро, как получить данные с Subversion-сервера (что, однако, может занять какое-то время).
357
+
358
+ Однако, импортирование не будет безупречным. И так как оно занимает много времени, стоит сделать его правильно. Первая проблема — это информация об авторах. В Subversion каждый коммитер имеет свою учётную запись в системе, и его имя пользователя отображается в информации о коммите. В примерах из предыдущего раздела выводилось `schacon` в некоторых местах, например, в выводе команд `blame` и `git svn log`. Если вы хотите преобразовать эту информацию для лучшего соответствия данным об авторах в Git'е, вам потребуется отобразить пользователей Subversion в авторов в Git'е. Создайте файл `users.txt`, в котором будут содержаться данные об этом отображении в таком формате:
359
+
360
+ schacon = Scott Chacon <schacon@geemail.com>
361
+ selse = Someo Nelse <selse@geemail.com>
362
+
363
+ Для того чтобы получить список авторов, который использует SVN, можно выполнить следующее:
364
+
365
+ $ svn log ^/ --xml | grep -P "^<author" | sort -u | \
366
+ perl -pe 's/<author>(.*?)<\/author>/$1 = /'
367
+
368
+ Эта команда выдаст журнал в формате XML — мы можем найти в нём информацию об авторах, создать из неё список с уникальными записями и избавиться от XML-разметки. (Разумеется, эта команда сработает только на машине с установленными `grep`, `sort` и `perl`). Затем перенаправьте вывод этой команды в файл `users.txt`, чтобы потом можно было добавить к каждой записи данные о соответствующих пользователях Git'а.
369
+
370
+ Вы можете передать этот файл как параметр команде `git svn` для более точного преобразования данных об авторах. Кроме того, можно дать указание `git svn` не включать метаданные, обычно импортируемые Subversion, передав параметр `--no-metadata` команде `clone` или `init`. Таким образом, команда для импортирования будет выглядеть так:
371
+
372
+ $ git svn clone http://my-project.googlecode.com/svn/ \
373
+ --authors-file=users.txt --no-metadata -s my_project
374
+
375
+ Теперь в вашем каталоге `my_project` будут находиться более приятно выглядящие данные после импортирования. Вместо коммитов, которые выглядят так:
376
+
377
+ commit 37efa680e8473b615de980fa935944215428a35a
378
+ Author: schacon <schacon@4c93b258-373f-11de-be05-5f7a86268029>
379
+ Date: Sun May 3 00:12:22 2009 +0000
380
+
381
+ fixed install - go to trunk
382
+
383
+ git-svn-id: https://my-project.googlecode.com/svn/trunk@94 4c93b258-373f-11de-
384
+ be05-5f7a86268029
385
+
386
+ они будут выглядеть так:
387
+
388
+ commit 03a8785f44c8ea5cdb0e8834b7c8e6c469be2ff2
389
+ Author: Scott Chacon <schacon@geemail.com>
390
+ Date: Sun May 3 00:12:22 2009 +0000
391
+
392
+ fixed install - go to trunk
393
+
394
+ Теперь не только поле Author выглядит намного лучше, но и строк с `git-svn-id` больше нет.
395
+
396
+ Вам потребуется сделать небольшую «уборку» после импорта. Сначала вам нужно убрать странные ссылки, оставленные `git svn`. Сначала мы переставим все метки так, чтобы они были реальными метками, а не странными удалёнными ветками. А затем мы переместим остальные ветки так, чтобы они стали локальными.
397
+
398
+ Для приведения меток к корректному виду Git-меток выполните:
399
+
400
+ $ cp -Rf .git/refs/remotes/tags/* .git/refs/tags/
401
+ $ rm -Rf .git/refs/remotes/tags
402
+
403
+ Эти действия переместят ссылки, которые были удалёнными ветками начинающимися с `tag/`, и сделают их настоящими (легковесными) метками.
404
+
405
+ Затем, переместите остальные ссылки в `refs/remotes` так, чтобы они стали локальными ветками:
406
+
407
+ $ cp -Rf .git/refs/remotes/* .git/refs/heads/
408
+ $ rm -Rf .git/refs/remotes
409
+
410
+ Теперь все старые ветки стали реальными Git-ветками, а все старые метки — реальными Git-метками. Последнее, что осталось сделать, это добавить свой Git-сервер в качестве удалённого ресурса и отправить на него данные. Вот пример добавления сервера как удалённого источника:
411
+
412
+ $ git remote add origin git@my-git-server:myrepository.git
413
+
414
+ Так как вы хотите, чтобы все ваши ветви и метки были переданы на этот сервер, выполните:
415
+
416
+ $ git push origin --all
417
+
418
+ Теперь все ваши ветки и метки должны быть импортированы на новый Git-сервер в чистом и опрятном виде.
419
+
420
+ ### Perforce ###
421
+
422
+ Следующей системой, для которой мы рассмотрим процедуру импортирования, будет Perforce. Утилита импортирования для Perforce также распространяется в составе Git'а. Если вы используете Git версии старее 1.7.11, то сценарий доступен только в секции `contrib` исходного кода — он не доступен по умолчанию, как `git svn`. В этом случае вам потребуется получить исходный код Git'а, располагающийся на git.kernel.org:
423
+
424
+ $ git clone git://git.kernel.org/pub/scm/git/git.git
425
+ $ cd git/contrib/fast-import
426
+
427
+ В каталоге `fast-import` вы найдёте исполняемый сценарий на языке Python с названием `git-p4`. У вас на компьютере должен быть установлен Python и утилита `p4` для того, чтобы этот сценарий смог осуществить импортирование. Допустим, например, что вы импортируете проект Jam из Perforce Public Depot. Для настройки вашей клиентской машины необходимо установить переменную окружения P4PORT, указывающую на депо Perforce:
428
+
429
+ $ export P4PORT=public.perforce.com:1666
430
+
431
+ Запустите команду `git-p4 clone` для импортирования проекта Jam с Perforce-сервера, передав в качестве параметров депо и путь к проекту, а также путь к каталогу, в который вы хотите импортировать проект:
432
+
433
+ $ git-p4 clone //public/jam/src@all /opt/p4import
434
+ Importing from //public/jam/src@all into /opt/p4import
435
+ Reinitialized existing Git repository in /opt/p4import/.git/
436
+ Import destination: refs/remotes/p4/master
437
+ Importing revision 4409 (100%)
438
+
439
+ Если вы теперь перейдёте в каталог `/opt/p4import` и выполните команду `git log`, вы увидите импортированную информацию:
440
+
441
+ $ git log -2
442
+ commit 1fd4ec126171790efd2db83548b85b1bbbc07dc2
443
+ Author: Perforce staff <support@perforce.com>
444
+ Date: Thu Aug 19 10:18:45 2004 -0800
445
+
446
+ Drop 'rc3' moniker of jam-2.5. Folded rc2 and rc3 RELNOTES into
447
+ the main part of the document. Built new tar/zip balls.
448
+
449
+ Only 16 months later.
450
+
451
+ [git-p4: depot-paths = "//public/jam/src/": change = 4409]
452
+
453
+ commit ca8870db541a23ed867f38847eda65bf4363371d
454
+ Author: Richard Geiger <rmg@perforce.com>
455
+ Date: Tue Apr 22 20:51:34 2003 -0800
456
+
457
+ Update derived jamgram.c
458
+
459
+ [git-p4: depot-paths = "//public/jam/src/": change = 3108]
460
+
461
+ Как видите, в каждом коммите есть идентификатор `git-p4`. Оставить этот идентификатор будет хорошим решением, если позже вам понадобится узнать номер изменения в Perforce. Однако, если вы всё же хотите удалить этот идентификатор — теперь самое время это сделать, до того, как вы начнёте работать в новом репозитории. Можно воспользоваться командой `git filter-branch` для одновременного удаления всех строк с идентификатором:
462
+
463
+ $ git filter-branch --msg-filter '
464
+ sed -e "/^\[git-p4:/d"
465
+ '
466
+ Rewrite 1fd4ec126171790efd2db83548b85b1bbbc07dc2 (123/123)
467
+ Ref 'refs/heads/master' was rewritten
468
+
469
+ Если вы теперь выполните `git log`, то увидите, что все контрольные суммы SHA-1 изменились, и что строки содержащие `git-p4` больше не появляются в сообщениях коммитов:
470
+
471
+ $ git log -2
472
+ commit 10a16d60cffca14d454a15c6164378f4082bc5b0
473
+ Author: Perforce staff <support@perforce.com>
474
+ Date: Thu Aug 19 10:18:45 2004 -0800
475
+
476
+ Drop 'rc3' moniker of jam-2.5. Folded rc2 and rc3 RELNOTES into
477
+ the main part of the document. Built new tar/zip balls.
478
+
479
+ Only 16 months later.
480
+
481
+ commit 2b6c6db311dd76c34c66ec1c40a49405e6b527b2
482
+ Author: Richard Geiger <rmg@perforce.com>
483
+ Date: Tue Apr 22 20:51:34 2003 -0800
484
+
485
+ Update derived jamgram.c
486
+
487
+ Ваш импортируемый репозиторий готов к отправке на новый Git-сервер.
488
+
489
+ ### Собственная утилита для импорта ###
490
+
491
+ Если вы используете систему, отличную от Subversion или Perforce, вы можете поискать утилиту для импорта под свою систему в интернете — для CVS, Clear Case, Visual Source Safe и даже для простого каталога с архивами уже существуют качественные инструменты для импортирования. Если ни один из этих инструментов не подходит для ваших целей, либо если вам нужен больший контроль над процессом импортирования, вам стоит использовать утилиту `git fast-import`. Эта команда принимает простые инструкции со стандартного ввода для управления процессом записи нужных данных в базу Git'а. Намного проще создать необходимые объекты в Git'е так, чем запуская базовые команды Git'а либо пытаясь записать сырые объекты (см. главу 9). При использовании `git fast-import` вы можете создать сценарий для импортирования, который считывает всю необходимую информацию из импортируемой системы и выводит простые понятные инструкции на стандартный вывод. Затем вы просто запускаете этот сценарий и, используя конвейер (pipe), передаёте результаты его работы на вход `git fast-import`.
492
+
493
+ Чтобы быстро продемонстрировать суть этого подхода, напишем простую утилиту для импорта. Положим, что вы работаете в каталоге `current` и время от времени делаете резервную копию этого каталога, добавляя к имени дату — `back_YYYY_MM_DD`, и вы хотите импортировать это всё в Git. Допустим, ваше дерево каталогов выглядит таким образом:
494
+
495
+ $ ls /opt/import_from
496
+ back_2009_01_02
497
+ back_2009_01_04
498
+ back_2009_01_14
499
+ back_2009_02_03
500
+ current
501
+
502
+ Для того чтобы импортировать всё это в Git, надо вспомнить, как Git хранит данные. Как вы помните, Git в своей основе представляет собой связный список объектов-коммитов, указывающих на снимки состояния их содержимого. Всё, что вам требуется, это сообщить команде `fast-import` что является данными снимков состояния, какие данные коммитов указывают на них и порядок их следования. Стратегией наших действий будет обход всех снимков состояния по очереди и создание соответствующих коммитов с содержимым каждого каталога, с привязкой каждого коммита к предыдущему.
503
+
504
+ Так же как и в главе 7 в разделе «Пример создания политики в Git», мы напишем сценарий на Ruby, поскольку это то, с чем я обычно работаю, и, кроме того, он легко читается. Но вы можете создать его на любом другом языке, которым владеете — он просто должен выводить необходимую информацию на стандартный вывод. Если вы работаете под Windows, то должны особым образом позаботиться о том, чтобы в конце строк не содержались символы возврата каретки — `git fast-import` принимает только символ перевода строки (LF), а не символ перевода строки и возврата каретки (CRLF), который используется в Windows.
505
+
506
+ Для того чтобы начать, вы должны перейти в целевой каталог и идентифицировать каждый подкаталог, являющийся снимком состояния, который вы хотите импортировать в виде коммита. Основной цикл будет выглядеть следующим образом:
507
+
508
+ last_mark = nil
509
+
510
+ # loop through the directories
511
+ Dir.chdir(ARGV[0]) do
512
+ Dir.glob("*").each do |dir|
513
+ next if File.file?(dir)
514
+
515
+ # move into the target directory
516
+ Dir.chdir(dir) do
517
+ last_mark = print_export(dir, last_mark)
518
+ end
519
+ end
520
+ end
521
+
522
+ Вы запускаете функцию `print_export` внутри каждого каталога, она берёт запись и отметку предыдущего снимка состояния и возвращает запись и отметку текущего; так вы сможете их правильно между собой соединить. «Отметка» — это термин утилиты `fast-import`, обозначающий идентификатор, который вы даёте коммиту; когда вы создаёте коммиты, вы назначаете каждому коммиту отметку, по которой на него можно сослаться из других коммитов. Таким образом, первая операция, которую надо включить в метод `print_export`, это генерация отметки из имени каталога:
523
+
524
+ mark = convert_dir_to_mark(dir)
525
+
526
+ Мы сделаем это путём создания массива каталогов и используя значение порядкового номера каталога в массиве как его отметку, поскольку отметка должна быть целым числом:
527
+
528
+ $marks = []
529
+ def convert_dir_to_mark(dir)
530
+ if !$marks.include?(dir)
531
+ $marks << dir
532
+ end
533
+ ($marks.index(dir) + 1).to_s
534
+ end
535
+
536
+ Теперь, когда мы имеем целочисленное представление нашего коммита, нам нужны даты, чтобы указывать их в метаданных коммитов. Поскольку дата записана в имени каталога, мы выделяем её оттуда. Следующей строкой в сценарии `print_export` будет:
537
+
538
+ date = convert_dir_to_date(dir)
539
+
540
+ где метод `convert_dir_to_date` определён как:
541
+
542
+ def convert_dir_to_date(dir)
543
+ if dir == 'current'
544
+ return Time.now().to_i
545
+ else
546
+ dir = dir.gsub('back_', '')
547
+ (year, month, day) = dir.split('_')
548
+ return Time.local(year, month, day).to_i
549
+ end
550
+ end
551
+
552
+ Этот метод возвращает целочисленное значение даты для каждого каталога. Последняя часть метаданных, которая нам нужна для всех коммитов это данные о коммитере, которые мы жёстко задаём в глобальной переменной:
553
+
554
+ $author = 'Scott Chacon <schacon@example.com>'
555
+
556
+ Теперь мы готовы приступить к выводу данных коммита в своём сценарии импорта. Дадим начальную информацию говорящую, что мы задаём объект коммита, ветку, на которой он находится, затем отметку, которую мы ранее сгенерировали, информацию о коммитере и сообщение коммита, а затем предыдущий коммит, если он есть. Код выглядит следующим образом:
557
+
558
+ # print the import information
559
+ puts 'commit refs/heads/master'
560
+ puts 'mark :' + mark
561
+ puts "committer #{$author} #{date} -0700"
562
+ export_data('imported from ' + dir)
563
+ puts 'from :' + last_mark if last_mark
564
+
565
+ Мы жёстко задаём часовой пояс (-0700), поскольку так проще. Если вы импортируете данные из другой системы, вы должны указать часовой пояс в виде смещения.
566
+ Сообщение коммита должно быть представлено в особом формате:
567
+
568
+ data (size)\n(contents)
569
+
570
+ Формат состоит из слова `data`, размера данных, которые требуется прочесть, символа переноса строки и, наконец, самих данных. Поскольку нам потребуется использовать такой же формат позже для описания содержимого файла, создадим вспомогательный метод `export_data`:
571
+
572
+ def export_data(string)
573
+ print "data #{string.size}\n#{string}"
574
+ end
575
+
576
+ Всё что нам осталось, это описать содержимое файла для каждого снимка состояния. Это просто, поскольку каждый из них содержится в каталоге: мы можем вывести команду `deleteall`, за которой следует содержимое каждого файла в каталоге. После этого Git соответствующим образом позаботится о регистрации каждого снимка:
577
+
578
+ puts 'deleteall'
579
+ Dir.glob("**/*").each do |file|
580
+ next if !File.file?(file)
581
+ inline_data(file)
582
+ end
583
+
584
+ Примечание: поскольку многие системы рассматривают свои ревизии как изменения от одного коммита до другого, `fast-import` также может принимать команды, задающие для каждого коммита, какие файлы были добавлены, удалены или модифицированы, а также что является новым содержимым файлов. В нашем примере вы могли бы вычислить разность между снимками состояния и предоставить только эти данные, но это сложнее. С таким же успехом можно предоставить Git'у все данные для того, чтобы он сам вычислил разницу. Если с вашими данными проще предоставлять разницу между снимками состояния, обратитесь к странице руководства `fast-import` для получения подробностей о том, как предоставлять данные таким способом.
585
+
586
+ Формат для задания содержимого нового файла либо указания нового содержимого изменённого файла следующий:
587
+
588
+ M 644 inline path/to/file
589
+ data (size)
590
+ (file contents)
591
+
592
+ Здесь, 644 — это права доступа (если в проекте есть исполняемые файлы, вам надо выявить их и назначить им права доступа 755), а параметр `inline` говорит о том, что содержимое будет выводиться непосредственно после этой строки. Метод `inline_data` выглядит следующим образом:
593
+
594
+ def inline_data(file, code = 'M', mode = '644')
595
+ content = File.read(file)
596
+ puts "#{code} #{mode} inline #{file}"
597
+ export_data(content)
598
+ end
599
+
600
+ Мы повторно используем метод `export_data`, определённый ранее, поскольку он работает тут так же, как и при задании сообщений коммитов.
601
+
602
+ Последнее, что вам осталось сделать, это вернуть текущую отметку, чтобы её можно было передать для использования в следующую итерацию:
603
+
604
+ return mark
605
+
606
+ ПРИМЕЧАНИЕ: Если вы работаете под Windows, то должны убедиться, что добавили ещё один дополнительный шаг. Мы уже упоминали, что Windows использует CRLF для перехода на новую строку, тогда как `git fast-import` ожидает только LF. Для того чтобы избежать этой проблемы и сделать процесс импорта безошибочным, вам нужно сказать Ruby использовать LF вместо CRLF:
607
+
608
+ $stdout.binmode
609
+
610
+ Это всё. Если вы теперь запустите этот сценарий, то получите примерно следующее содержимое:
611
+
612
+ $ ruby import.rb /opt/import_from
613
+ commit refs/heads/master
614
+ mark :1
615
+ committer Scott Chacon <schacon@geemail.com> 1230883200 -0700
616
+ data 29
617
+ imported from back_2009_01_02deleteall
618
+ M 644 inline file.rb
619
+ data 12
620
+ version two
621
+ commit refs/heads/master
622
+ mark :2
623
+ committer Scott Chacon <schacon@geemail.com> 1231056000 -0700
624
+ data 29
625
+ imported from back_2009_01_04from :1
626
+ deleteall
627
+ M 644 inline file.rb
628
+ data 14
629
+ version three
630
+ M 644 inline new.rb
631
+ data 16
632
+ new version one
633
+ (...)
634
+
635
+ Для того чтобы запустить утилиту импорта, перенаправьте этот вывод на вход `git fast-import`, находясь в Git-репозитории, в который хотите совершить импортирование. Вы можете создать новый каталог, а затем выполнить в нём `git init` и потом запустить свой сценарий:
636
+
637
+ $ git init
638
+ Initialized empty Git repository in /opt/import_to/.git/
639
+ $ ruby import.rb /opt/import_from | git fast-import
640
+ git-fast-import statistics:
641
+ ---------------------------------------------------------------------
642
+ Alloc'd objects: 5000
643
+ Total objects: 18 ( 1 duplicates )
644
+ blobs : 7 ( 1 duplicates 0 deltas)
645
+ trees : 6 ( 0 duplicates 1 deltas)
646
+ commits: 5 ( 0 duplicates 0 deltas)
647
+ tags : 0 ( 0 duplicates 0 deltas)
648
+ Total branches: 1 ( 1 loads )
649
+ marks: 1024 ( 5 unique )
650
+ atoms: 3
651
+ Memory total: 2255 KiB
652
+ pools: 2098 KiB
653
+ objects: 156 KiB
654
+ ---------------------------------------------------------------------
655
+ pack_report: getpagesize() = 4096
656
+ pack_report: core.packedGitWindowSize = 33554432
657
+ pack_report: core.packedGitLimit = 268435456
658
+ pack_report: pack_used_ctr = 9
659
+ pack_report: pack_mmap_calls = 5
660
+ pack_report: pack_open_windows = 1 / 1
661
+ pack_report: pack_mapped = 1356 / 1356
662
+ ---------------------------------------------------------------------
663
+
664
+ Как видите, после успешного завершения Git выдаёт большое количество информации о проделанной работе. В нашем случае мы импортировали в общей сложности 18 объектов для 5 коммитов в одной ветке. Теперь выполните `git log`, чтобы увидеть свою новую историю изменений:
665
+
666
+ $ git log -2
667
+ commit 10bfe7d22ce15ee25b60a824c8982157ca593d41
668
+ Author: Scott Chacon <schacon@example.com>
669
+ Date: Sun May 3 12:57:39 2009 -0700
670
+
671
+ imported from current
672
+
673
+ commit 7e519590de754d079dd73b44d695a42c9d2df452
674
+ Author: Scott Chacon <schacon@example.com>
675
+ Date: Tue Feb 3 01:00:00 2009 -0700
676
+
677
+ imported from back_2009_02_03
678
+
679
+ Ну вот, вы получили чистый и красивый Git-репозиторий. Важно отметить, что пока что у вас нет никаких файлов в рабочем каталоге — вы должны сбросить свою ветку на ветку `master`:
680
+
681
+ $ ls
682
+ $ git reset --hard master
683
+ HEAD is now at 10bfe7d imported from current
684
+ $ ls
685
+ file.rb lib
686
+
687
+ С помощью утилиты `fast-import` можно делать намного больше — манипулировать разными правами доступа, двоичными данными, несколькими ветками, совершать слияния, назначать метки, отображать индикаторы прогресса и многое другое. Некоторое количество примеров более сложных сценариев содержится в каталоге `contrib/fast-import` в исходном коде Git'а; один из самых лучших из них — сценарий `git-p4`, о котором я уже рассказывал.
688
+
689
+ ## Итоги ##
690
+
691
+ После всего вышесказанного вы должны чувствовать себя уверенно, используя Git в связке с Subversion или импортируя практически любой существующий репозиторий в Git-репозиторий, не теряя при этом данных. Следующая глава раскроет перед вами внутреннюю механику Git'а, так что вы будете способны создать каждый необходимый байт данных, если потребуется.