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,688 @@
1
+ # Git으로 이전하기 #
2
+
3
+ Git은 완벽하지 않다. 프로젝트를 전부 Git으로 옮기기는 어렵다. 프로젝트가 특정 VCS 시스템에 매우 의존적으로 개발 됐을 수도 있다. 보통은 Subversion에 의존적이다. 이번 장은 `git svn`이라는 Git과 Subversion을 양방향으로 이어 주는 도구를 알아 보며 시작한다.
4
+
5
+ 언젠가 이미 존재하는 프로젝트 환경을 Git으로 변경하고 싶게 될 것이다. 이 장의 나머지 부분에서 프로젝트를 Git으로 변경하는 방법에 대해 다룰 것이다. 먼저 Subversion에서 프로젝트를 옮겨 오는 방법을 설명하고 그 다음에는 Perforce, 그리고 스크립트를 직접 만들어서 잘 쓰지 않는 VCS에서도 프로젝트를 옮기는 방법을 다룰 것이다.
6
+
7
+ ## Git과 Subversion ##
8
+
9
+ 현재도 많은 오픈소스 프로젝트와 수 많은 기업 프로젝트는 Subversion으로 소스코드를 관리한다. 10여년간 Subversion이 가장 인기있는 오픈소스 VCS 도구였다. Subversion은 그 이전 시대에서 가장 많이 사용하던 CVS와 많이 닮았다.
10
+
11
+ Git이 자랑하는 또 하나의 기능은 `git svn`이라는 양방향 Subversion 지원 도구이다. Git을 Subversion 클라이언트로 사용할 수 있기 때문에 로컬에서는 Git의 기능을 활용하고 Push 할 때는 Subversion 서버에 Push한다. 로컬 브랜치와 Merge, Staging Area, Rebase, Cherry-pick 등의 Git 기능을 충분히 사용할 수 있다. 같이 일하는 동료는 빛 한줄기 없는 선사시대 동굴에서 일하겠지만 말이다. `git svn`은 기업에서 git을 사용할 수 있도록 돕는 출발점이다. 우리가 Git을 도입하기 위해 기업내에서 노력하는 동안 동료가 효율적으로 환경을 바꿀 수 있도록 도움을 줄 수 잇다. Subversion 지원 도구는 우리를 DVCS 세상으로 인도하는 붉은 알약과 같은 것이다.
12
+
13
+ ### git svn ###
14
+
15
+ Git과 Subversion을 이어주는 명령은 `git svn` 으로 시작한다. 이 명령 뒤에 추가하는 명령이 몇 가지 더 있으며 간단한 예제를 보여주고 설명한다.
16
+
17
+ `git svn` 명령을 사용할 때는 절름발이인 Subversion을 사용하고 있다는 점을 염두하자. 우리가 로컬 브랜치와 Merge를 맘대로 쓸 수 있다고 하더라도 최대한 일직선으로 히스토리를 유지하는것이 좋다. Git 저장소처럼 사용하지 않는다.
18
+
19
+ 히스토리를 재작성해서 Push하지 말아야 한다. Git을 사용하는 동료들끼리 따로 Git 저장소에 Push하지도 말아야 한다. Subversion은 단순하게 일직선 히스토리만 가능하다. 팀원중 일부는 SVN을 사용하고 일부는 Git을 사용하는 팀이라면 SVN Server를 사용해서 협업하는 것이 좋다. 그래야 삶이 편해진다.
20
+
21
+ ### 설정하기 ###
22
+
23
+ `git svn`을 사용하려면 SVN 저장소가 하나 필요하다. 저장소에 쓰기 권한이 있어야 한다. 필자의 test 저장소를 복사한다. Subversion(1.4 이상)에 포함된 `svnsync`라는 도구를 사용하여 SVN 저장소를 복사한다. 테스트용 저장소가 필요해서 Google Code에 새로 Subversion 저장소를 하나 만들었다. `protobuf` 라는 프로젝트의 일부 코드를 복사했다. `protobuf`는 네트워크 전송에 필요한 구조화된 데이터(프로토콜 같은 것들)의 인코딩을 도와주는 도구이다.
24
+
25
+ 로컬 Subversion 저장소를 하나 만든다:
26
+
27
+ $ mkdir /tmp/test-svn
28
+ $ svnadmin create /tmp/test-svn
29
+
30
+ 그리고 모든 사용자가 revprops 속성을 변경할 수 있도록 항상 0을 반환하는 pre-revprop-change 스크립트를 준비한다(역주: 파일이 없거나, 다른 이름으로 되어있을 수 있다. 이 경우 아래 내용으로 새로 파일을 만들고 실행 권한을 준다):
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` 명령으로 다른 Subversion 저장소를 로컬로 복사할 수 있도록 지정한다:
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
+ 이 명령은 몇 분 걸리지 않는다. 저장하는 위치가 로컬이 아니라 리모트 서버라면 오래 걸린다. 커밋이 100개 이하라고 해도 오래 걸린다. Subversion은 한번에 커밋을 하나씩 받아서 Push하기 때문에 엄청나게 비효율적이다. 하지만, 저장소를 복사하는 다른 방법은 없다.
52
+
53
+ ### 시작하기 ###
54
+
55
+ 이제 갖고 놀 Subversion 저장소를 하나 준비했다. `git svn clone` 명령으로 Subversion 저장소 전체를 Git 저장소로 가져온다. 만약 Subversion 저장소가 로컬에 있는 것이 아니라 리모트 서버에 있으면 `file:///tmp/test-svn` 부분에 서버 저장소의 URL을 적어 준다.
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
+ 이 명령은 사실 SVN 저장소 주소를 주고 `git svn init`과 `git svn fetch` 명령을 순서대로 실행한 것과 같다. 이 명령은 시간이 좀 걸린다. 테스트용 프로젝트는 커밋이 75개 정도 밖에 안되서 시간이 많이 걸리지 않는다. Git은 커밋을 한번에 하나씩 일일이 기록해야 한다. 커밋이 수천개인 프로젝트라면 몇 시간 혹은 몇 일이 걸릴 수도 있다.
74
+
75
+ `-T trunk -b branches -t tags` 부분은 Subversion이 어떤 브랜치 구조를 가지고 있는지 Git에게 알려주는 부분이다. Subversion 표준 형식과 다르면 이 옵션 부분에서 알맞은 이름을 지정해준다. 표준 형식을 사용한다면 간단하게 `-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 svn` 도구가 리모트 브랜치의 이름을 어떻게 짓는지 알아야 한다. Git 저장소를 Clone할 때는 보통 `origin/[branch]`처럼 리모트 저장소 이름이 들어간 브랜치 이름으로 만들어진다. `git svn`은 우리가 리모트 저장소를 딱 하나만 사용한다고 가정한다. 그래서 리모트 저장소의 이름을 붙여서 브랜치를 관리하지 않는다. Plumbing 명령어인 `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`으로 저장소를 가져오면 Subversion 태그는 Git 태그가 아니라 리모트 브랜치로 등록되는 점을 잘 기억하자. `git svn`은 Subversion 태그를 tags라는 리모트 서버에 있는 브랜치처럼 만든다.
112
+
113
+ ### Subversion 서버에 커밋하기 ###
114
+
115
+ 자 작업할 Git 저장소는 준비했다. 무엇인가 수정하고 서버로 고친 내용을 Push해야 할 때가 왔다. Git을 Subversion의 클라이언트로 사용해서 수정한 내용을 전송한다. 어떤 파일을 수정하고 커밋을 하면 그 수정한 내용은 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 서버로 보낸다는 점을 잘 살펴보자. `git svn dcommit` 명령으로 서버에 Push한다.
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
+ 이 명령은 새로 추가한 커밋을 모두 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
+ 원래 `97031e5`로 시작하는 SHA 체크섬이 지금은 `938b1a5`로 시작한다. 만약 Git 서버와 Subversion 서버에 함께 Push하고 싶으면 우선 Subversion 서버에 `dcommit`으로 Push를 하고 그 다음에 Git 서버에 Push해야 한다.
144
+
145
+ ### 새로운 변경사항 받아오기 ###
146
+
147
+ 다른 개발자와 함께 일하는 과정에서 다른 개발자가 Push한 상태에서 Push를 하면 충돌이 날 수 있다. 충돌을 해결하지 않으면 서버로 Push할 수 없다. 충돌이 나면 `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
+ 그러면 서버 코드 위에 변경사항을 적용하기 때문에 성공적으로 `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
+ Push하기 전에 서버의 내용을 Merge하는 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
+ Push하고 나면 프로젝트 상태가 달라진다는 점을 기억해야 한다. 충돌이 없으면 변경사항이 바램대로 적용되지 않아도 알려주지 않는다. 이 부분이 Git과 다른 점이다. Git에서는 서버로 보내기 전에 프로젝트 상태를 전부 테스트할 수 있다. SVN은 서버로 커밋하기 전과 후의 상태가 동일하다는 것이 보장되지 않는다.
192
+
193
+ `git svn rebase` 명령으로도 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` 명령을 사용하면 로컬 코드를 항상 최신 버전으로 유지할 수 있다. 이 명령을 사용하기 전에 워킹 디렉토리를 깨끗하게 만드는 것이 좋다. 깨끗하지 못하면 Stash를 하거나 임시로 커밋하고 나서 `git svn rebase` 명령을 실행하는 것이 좋다. 깨끗하지 않으면 충돌이 나서 Rebase가 중지될 수 있다.
202
+
203
+ ### Git 브랜치 문제 ###
204
+
205
+ Git에 익숙한 사람이면 일을 할 때 먼저 토픽 브랜치를 만들고, 일을 끝낸 다음에, Merge하는 방식을 쓰려고 할 것이다. 하지만, `git svn`으로 Subversion 서버에 Push할 때에는 브랜치를 Merge하지 않고 Rebase해야 한다. Subversion은 일직선 히스토리 밖에 모르고 Git의 Merge도 알지 못한다. 그래서 `git svn`은 첫 번째 부모 정보만 사용해서 Git 커밋을 Subversion 커밋으로 변경한다.
206
+
207
+ 예제를 하나 살펴보자. `experiment` 브랜치를 하나 만들고 2개의 변경사항을 커밋한다. 그리고 `master` 브랜치로 Merge하고 나서 `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
+ Merge 커밋이 들어 있는 히스토리에서 `dcommit` 명령을 실행한다. 그리고 나서 Git 히스토리를 살펴보면 `experiment` 브랜치의 커밋은 재작성되지 않았다. 대신 Merge 커밋만 SVN 서버로 전송됐을 뿐이다.
229
+
230
+ 누군가 이 것을 내려 받으면 결과가 합쳐진 Merge 커밋 하나만 볼 수 있다. 다른 사람은 언제 어디서 커밋한 것인지 알 수 없다.
231
+
232
+ ### Subversion의 브랜치 ###
233
+
234
+ Subversion의 브랜치는 Git의 브랜치와 달라서 가능한 사용을 하지 않는 것이 좋다. 하지만 `git svn`으로도 Subversion 브랜치를 관리할 수 있다.
235
+
236
+ #### SVN 브랜치 만들기 ####
237
+
238
+ Subversion 브랜치를 만들려면 `git svn branch [branchname]` 명령을 사용한다:
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` 명령과 동일하다. 이 명령은 브랜치를 Checkout해주지 않는다는 것을 주의해야 한다. 여기서 커밋하면 `opera` 브랜치가 아니라 `trunk` 브랜치에 커밋된다.
250
+
251
+ ### Subversion 브랜치 넘나들기 ###
252
+
253
+ `dcommit` 명령은 어떻게 커밋 할 브랜치를 결정할까? Git은 히스토리에 있는 커밋중에서 가장 마지막으로 기록된 Subversion 브랜치를 찾는다. 즉, 현 브랜치 히스토리의 커밋 메시지에 있는 `git-svn-id` 항목을 읽는 것이기 때문에 오직 한 브랜치에만 전송할 수 있다.
254
+
255
+ 동시에 여러 브랜치에서 작업하려면 Subversion 브랜치에 `dcommit`할 수 있는 로컬 브랜치가 필요하다. 이 브랜치는 Subversion 커밋에서 시작하는 브랜치다. 아래와 같이 `opera` 브랜치를 만들면 독립적으로 일 할 수 있다:
256
+
257
+ $ git branch opera remotes/opera
258
+
259
+ `git merge` 명령으로 `opera` 브랜치를 `trunk` 브랜치(`master` 브랜치 역할)에 Merge한다. 하지만 `-m` 옵션을 주고 적절한 커밋 메시지를 작성하지 않으면 아무짝에 쓸모없는 "Merge branch opera" 같은 메시지가 커밋된다.
260
+
261
+ `git merge` 명령으로 Merge한다는 것에 주목하자. Git은 자동으로 공통 커밋을 찾아서 Merge에 참고하기 때문에 Subversion에서 하는 것보다 Merge가 더 잘된다. 여기서 생성되는 Merge 커밋은 일반적인 Merge 커밋과 다르다. 이 커밋을 Subversion 서버에 Push해야 하지만 Subversion에서는 부모가 2개인 커밋이 있을 수 없다. 그래서 Push하면 브랜치에서 만들었던 커밋 여러개가 하나로 합쳐진(squash된) 것처럼 Push된다. 그래서 일단 Merge하면 취소하거나 해당 브랜치에서 계속 작업하기 어렵다. `dcommit` 명령을 수행하면 Merge한 브랜치의 정보를 어쩔 수 없이 잃어버리게 된다. Merge Base도 찾을 수 없게 된다. `dcommit` 명령은 Merge한 것을 `git merge --squash`로 Merge한 것과 똑 같이 만들어 버린다. Branch를 Merge한 정보는 저장되지 않기 때문에 이 문제를 해결할 방법이 없다. 문제를 최소화하려면 trunk에 Merge하자마자 해당 브랜치를(여기서는 `opera`) 삭제하는 것이 좋다.
262
+
263
+ ### Subversion 명령 ###
264
+
265
+ `git svn` 명령은 Git으로 전향하기 쉽도록 Subversion에 있는 것과 비슷한 명령어를 지원한다. 아마 여기서 설명하는 명령은 익숙할 것이다.
266
+
267
+ #### SVN 형식의 히스토리 ####
268
+
269
+ Subversion에 익숙한 사람은 Git 히스토리를 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의 `svn log` 명령어는 히스토리 데이터를 조회할 때 서버가 필요하다. 둘째로 이미 서버로 전송한 커밋만 출력해준다. 아직 `dcommit` 명령으로 서버에 전송하지 않은 로컬 Git 커밋은 보여주지 않는다. Subversion 서버에는 있지만 아직 내려받지 않은 변경사항도 보여주지 않는다. 즉, 현재 알고있는 Subversion 서버의 상태만 보여준다.
288
+
289
+ #### SVN 어노테이션 ####
290
+
291
+ `git svn log` 명령이 `svn log` 명령을 흉내내는 것처럼 `git svn blame [FILE]` 명령으로 `svn annotate` 명령을 흉내낼 수 있다. 실행한 결과는 아래와 같다:
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
+ 다시 한번 말하지만 이 명령도 아직 서버로 전송하지 않은 커밋은 보여주지 않는다.
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`명령이 오프라인으로 동작하듯이 이 명령도 오프라인으로 동작한다. 서버에서 가장 최근에 내려받은 정보를 출력한다.
326
+
327
+ #### Subversion에서 무시하는것 무시하기 ####
328
+
329
+ Subversion 저장소를 클론하면 쓸데 없는 파일을 커밋하지 않도록 `svn:ignore` 속성을 `.gitignore` 파일로 만들고 싶을 것이다. `git svn`에는 이 문제와 관련된 명령이 두 가지 있다. 하나는 `git svn create-ignore` 명령이다. 해당 위치에 커밋할 수 있는 `.gitignore` 파일을 생성해준다.
330
+
331
+ 두 번째 방법은 `git svn show-ignore` 명령이다. `.gitignore`에 추가할 목록을 출력해 준다. 프로젝트의 exclude 파일로 결과를 리다이렉트할 수 있다:
332
+
333
+ $ git svn show-ignore > .git/info/exclude
334
+
335
+ 이렇게 하면 `.gitignore` 파일로 프로젝트를 더럽히지 않아도 된다. 혼자서만 Git을 사용하는 거라면 다른 팀원들은 프로젝트에 `.gitignore` 파일이 있는 것을 싫어 할 수 있다.
336
+
337
+ ### Git-Svn 요약 ###
338
+
339
+ `git svn` 도구는 여러가지 이유로 Subversion 서버를 사용해야만 하는 상황에서 빛을 발한다. 하지만 Git의 모든 장점을 이용할 수는 없다. Git과 Subversion은 다르기 때문에 혼란이 빚어질 수도 있다. 이런 문제에 빠지지 않기 위해서 다음 가이드라인을 지켜야 한다:
340
+
341
+ * Git 히스토리를 일직선으로 유지하라. `git merge`로 Merge 커밋이 생기지 않도록 하라. Merge 말고 Rebase로 변경사항을 Master 브랜치에 적용하라.
342
+ * 따로 Git 저장소 서버를 두지 말라. 클론을 빨리 하기 위해서 잠깐 하나 만들어 쓰는 것은 무방하나 절대로 Git 서버에 Push하지는 말아야 한다. `pre-receive` 훅에서 `git-svn-id`가 들어 있는 커밋 메시지는 거절하는 방법도 괜찮다.
343
+
344
+ 이러한 가이드라인을 잘 지키면 Subversion 서버도 쓸만하다. 그래도 Git 서버를 사용할 수 있으면 Git 서버를 사용하는 것이 훨씬 좋다.
345
+
346
+ ## Git으로 옮기기 ##
347
+
348
+ 다른 VCS를 사용하는 프로젝트를 Git으로 옮기고 싶다면 우선 프로젝트를 Git으로 이전(Migrate)해야 한다. 이번 절에서는 Git에 들어 있는 Importer를 살펴보고 직접 Importer를 만드는 방법을 알아본다.
349
+
350
+ ### 가져오기 ###
351
+
352
+ 많이 사용하는 Subversion과 Perforce 프로젝트를 이전하는 방법을 살펴보자. 이 두 VCS에서 Git으로 이전하고자 하는 사람이 많고 Importer도 이미 Git에 들어 있다.
353
+
354
+ ### Subversion ###
355
+
356
+ `git svn`을 설명하는 절을 읽었으면 쉽게 `git svn clone` 명령으로 저장소를 가져올 수 있다. 가져오고 나서 Subversion 서버는 중지하고 Git 서버를 만들고 사용하면 된다. 만약 히스토리 정보가 필요하면 (느린) Subversion 서버 없이 로컬에서 조회할 수 있다.
357
+
358
+ 우선 가져오기에 시간이 많이 드니까 일단 가져오기를 시작하자. 이 가져오기 기능에 문제가 좀 있다. 첫 번째 문제는 Author 정보이다. Subversion에서는 커밋하려면 해당 시스템 계정이 있어야 한다. `blame`이나 `git svn log` 같은 명령에서 `schacon`이라는 이름을 봤을 것이다. 이 정보를 Git 형식의 정보로 변경하려면 Subversion 사용자와 Git Author를 연결시켜줘야 한다. Subversion 사용자 이름과 Git Author 간에 연결을 해줘서 이 Author 정보를 Git 스타일의 Author 정보로 변경한다. `users.txt`라는 파일을 아래와 같이 만든다:
359
+
360
+ schacon = Scott Chacon <schacon@geemail.com>
361
+ selse = Someo Nelse <selse@geemail.com>
362
+
363
+ SVN에 기록된 Author 이름을 아래 명령으로 조회한다:
364
+
365
+ $ svn log ^/ --xml | grep -P "^<author" | sort -u | \
366
+ perl -pe 's/<author>(.*?)<\/author>/$1 = /' > users.txt
367
+
368
+ 우선 XML 형식으로 SVN 로그를 출력하고, 거기서 Author 정보만 찾고, 중복된 것을 제거하고, XML 태그는 버린다. 물론 `grep`, `sort`, `perl` 명령이 동작하는 시스템에서만 이 명령을 사용할 수 있다. 이 결과에 Git Author 정보를 더해서 `users.txt`를 만든다.
369
+
370
+ 이 파일을 `git svn` 명령에 전달하면 보다 정확한 Author 정보를 Git 저장소에 남길 수 있다. 그리고 `git svn`의 `clone`이나 `init` 명령에 `--no-metadata` 옵션을 주면 Subversion의 메타데이터를 저장하지 않는다. 해당 명령은 아래와 같다:
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` 디렉토리에 진짜 Git 저장소가 생성된다. 결과는 아래와 같지 않고:
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답고 `git-svn-id` 항목도 기록되지 않았다.
395
+
396
+ 이제 뒷 정리를 해야 한다. `git svn`이 만들어 준 이상한 브랜치나 태그를 제거한다. 우선 이상한 리모트 태그를 모두 진짜 Git 태그로 옮긴다. 그리고 리모트 브랜치도 로컬 브랜치로 옮긴다.
397
+
398
+ 아래와 같이 태그를 진정한 Git 태그로 만든다:
399
+
400
+ $ git for-each-ref refs/remotes/tags | cut -d / -f 4- | grep -v @ | while read tagname; do git tag "$tagname" "tags/$tagname"; git branch -r -d "tags/$tagname"; done
401
+
402
+ `tags/` 로 시작하는 리모트 브랜치를 가져다 (Lightweight) 태그로 만들었다.
403
+
404
+ `refs/remotes` 밑에 있는 레퍼런스는 전부 로컬 브랜치로 만든다:
405
+
406
+ $ git for-each-ref refs/remotes | cut -d / -f 3- | grep -v @ | while read branchname; do git branch "$branchname" "refs/remotes/$branchname"; git branch -r -d "$branchname"; done
407
+
408
+ 이제 모든 태그와 브랜치는 진짜 Git 태그와 브랜치가 됐다. Git 서버를 새로 추가를 하고 지금까지 작업한 것을 Push하는 일이 남았다. 아래처럼 리모트 서버를 추가한다:
409
+
410
+ $ git remote add origin git@my-git-server:myrepository.git
411
+
412
+ 분명 모든 브랜치와 태그를 Push하고 싶을 것이다:
413
+
414
+ $ git push origin --all
415
+
416
+ 모든 브랜치와 태그를 Git 서버로 깔끔하게 잘 옮겼다.
417
+
418
+ ### Perforce ###
419
+
420
+ 이제 Perforce 차례다. Preforce Importer도 Git에 들어 있다. Git 1.7.11 이전 버전을 사용한다면 소스코드의 `contrib` 에 포함되어 있다.이런 경우라면 Perforce Importer를 사용하기 위해 우선 git.kernel.org에서 Git 소스코드를 가져와야 한다:
421
+
422
+ $ git clone git://git.kernel.org/pub/scm/git/git.git
423
+ $ cd git/contrib/fast-import
424
+
425
+ `git-p4` 라는 Python 스크립트는 `fast-import` 디렉토리에 있다. 그리고 Python과 `p4`가 설치돼 있어야 이 스크립트가 동작한다. Perforce Public Depot에 있는 Jam 프로젝트를 Git으로 옮겨보자. 우선 Perfoce Depot의 주소를 P4PORT 환경변수에 설정한다:
426
+
427
+ $ export P4PORT=public.perforce.com:1666
428
+
429
+ `git-p4 clone` 명령으로 Perforce 서버에서 Jam 프로젝트를 가져온다. 이 명령에 Depot, 프로젝트 경로, 프로젝트를 가져올 경로를 주면 된다:
430
+
431
+ $ git-p4 clone //public/jam/src@all /opt/p4import
432
+ Importing from //public/jam/src@all into /opt/p4import
433
+ Reinitialized existing Git repository in /opt/p4import/.git/
434
+ Import destination: refs/remotes/p4/master
435
+ Importing revision 4409 (100%)
436
+
437
+ `/opt/p4import` 디렉토리로 이동해서 `git log` 명령을 실행하면 프로젝트 정보를 볼 수 있다:
438
+
439
+ $ git log -2
440
+ commit 1fd4ec126171790efd2db83548b85b1bbbc07dc2
441
+ Author: Perforce staff <support@perforce.com>
442
+ Date: Thu Aug 19 10:18:45 2004 -0800
443
+
444
+ Drop 'rc3' moniker of jam-2.5. Folded rc2 and rc3 RELNOTES into
445
+ the main part of the document. Built new tar/zip balls.
446
+
447
+ Only 16 months later.
448
+
449
+ [git-p4: depot-paths = "//public/jam/src/": change = 4409]
450
+
451
+ commit ca8870db541a23ed867f38847eda65bf4363371d
452
+ Author: Richard Geiger <rmg@perforce.com>
453
+ Date: Tue Apr 22 20:51:34 2003 -0800
454
+
455
+ Update derived jamgram.c
456
+
457
+ [git-p4: depot-paths = "//public/jam/src/": change = 3108]
458
+
459
+ 커밋마다 `git-p4` 라는 ID 항목이 들어가 있다. 나중에 Perforce Change Number가 필요해질 수도 있으니 커밋에 그대로 유지하는 편이 좋다. 하지만 ID를 지우고자 한다면 지금 하는 것이 가장 좋다. `git filter-branch` 명령으로 한방에 삭제한다:
460
+
461
+ $ git filter-branch --msg-filter '
462
+ sed -e "/^\[git-p4:/d"
463
+ '
464
+ Rewrite 1fd4ec126171790efd2db83548b85b1bbbc07dc2 (123/123)
465
+ Ref 'refs/heads/master' was rewritten
466
+
467
+ `git log` 명령을 실행하면 모든 SHA-1 체크섬이 변경됐고 커밋 메시지에서 `git-p4` 항목도 삭제된 것을 확인할 수 있다.
468
+
469
+ $ git log -2
470
+ commit 10a16d60cffca14d454a15c6164378f4082bc5b0
471
+ Author: Perforce staff <support@perforce.com>
472
+ Date: Thu Aug 19 10:18:45 2004 -0800
473
+
474
+ Drop 'rc3' moniker of jam-2.5. Folded rc2 and rc3 RELNOTES into
475
+ the main part of the document. Built new tar/zip balls.
476
+
477
+ Only 16 months later.
478
+
479
+ commit 2b6c6db311dd76c34c66ec1c40a49405e6b527b2
480
+ Author: Richard Geiger <rmg@perforce.com>
481
+ Date: Tue Apr 22 20:51:34 2003 -0800
482
+
483
+ Update derived jamgram.c
484
+
485
+ 이제 새 Git 서버에 Push하면 된다.
486
+
487
+ ### 직접 Importer 만들기 ###
488
+
489
+ 사용하는 VCS가 Subversion이나 Perforce가 아니면 인터넷에서 적당한 Importer를 찾아봐야 한다. CVS, Clear Case, Visual Source Safe 같은 시스템용 Importer가 좋은게 많다. 심지어 단순히 디렉토리 아카이브용 Importer에도 좋은게 있다. 사람들이 잘 안쓰는 시스템을 사용하고 있는데 적당한 Importer를 못 찾았거나 부족해서 좀 더 고쳐야 한다면 `git fast-import`를 사용한다. 이 명령은 표준입력으로 데이터를 입력받는데, *9장*에서 배우는 저수준 명령어와 내부 객체를 직접 다루는 것보다 훨씬 쉽다. 먼저 사용하는 VCS에서 필요한 정보를 수집해서 표준출력으로 출력하는 스크립트를 만든다. 그리고 그 결과를 `git fast-import`의 표준입력으로 보낸다(pipe).
490
+
491
+ 간단한 Importer를 작성해보자. `back_YYYY_MM_DD` 라는 디렉토리에 백업하면서 프로젝트를 진행하는 예제를 보자. Importer를 만들 때 디렉토리 상태는 아래와 같다:
492
+
493
+ $ ls /opt/import_from
494
+ back_2009_01_02
495
+ back_2009_01_04
496
+ back_2009_01_14
497
+ back_2009_02_03
498
+ current
499
+
500
+ Importer를 만들기 전에 우선 Git이 어떻게 데이터를 저장하는지 알아야 한다. 이미 알고 있듯이 Git은 기본적으로 스냅샷을 가리키는 커밋 개체가 연결된 리스트이다. 스냅샷이 뭐고, 그걸 가리키는 커밋은 또 뭐고, 그 커밋의 순서가 어떻게 되는지 `fast-import`에 알려 줘야 한다. 이 것이 해야할 일의 전부다. 그러면 디렉토리마다 스냅샷을 만들고, 그 스냅샷을 가리키는 커밋 개체를 만들고, 이전 커밋과 연결 시킨다.
501
+
502
+ *7장*의 "정책 구현하기" 절에서 했던 것 처럼 Ruby로 스크립트를 작성한다. 필자는 Ruby를 많이 사용하기도 하고 Ruby가 읽기도 쉽다. 하지만 자신에게 익숙한 것을 사용해서 표준출력으로 적절한 정보만 출력할 수 있으면 된다. 그리고 윈도에서는 줄바꿈 문자에 CR(Carriage Return) 문자가 들어가지 않도록 주의해야 한다. `git fast-import` 명령은 윈도에서도 줄바꿈 문자로 CRLF 문자가 아니라 LF(Line Feed) 문자만 허용한다.
503
+
504
+ 우선 해당 디렉토리로 이동해서 어떤 디렉토리가 있는지 살펴본다. 하위 디렉토리마다 스냅샷 하나가 되고 커밋 하나가 된다. 하위 디렉토리를 이동하면서 필요한 정보를 출력한다. 기본적인 로직은 아래와 같다:
505
+
506
+ last_mark = nil
507
+
508
+ # loop through the directories
509
+ Dir.chdir(ARGV[0]) do
510
+ Dir.glob("*").each do |dir|
511
+ next if File.file?(dir)
512
+
513
+ # move into the target directory
514
+ Dir.chdir(dir) do
515
+ last_mark = print_export(dir, last_mark)
516
+ end
517
+ end
518
+ end
519
+
520
+ 각 디렉토리에서 `print_export`를 호출하는데 이 함수는 아규먼트로 디렉토리와 이전 스냅샷 Mark를 전달받고 현 스냅샷 Mark를 반환한다. 그래서 적절히 연결 시킬 수 있다. `fast-import`에서 "Mark"는 커밋의 식별자를 말한다. 커밋을 하나 만들면 Mark도 같이 만들어 이 Mark로 다른 커밋과 연결 시킨다. 그래서 `print_export`에서 우선 해야 하는 일은 각 디렉토리 이름으로 Mark를 생성하는 것이다:
521
+
522
+ mark = convert_dir_to_mark(dir)
523
+
524
+ Mark는 정수 값을 사용해야 하기 때문에 디렉토리를 배열에 담고 그 인덱스를 Mark로 사용한다. 아래와 같이 작성한다:
525
+
526
+ $marks = []
527
+ def convert_dir_to_mark(dir)
528
+ if !$marks.include?(dir)
529
+ $marks << dir
530
+ end
531
+ ($marks.index(dir) + 1).to_s
532
+ end
533
+
534
+ 각 커밋을 가리키는 정수 Mark를 만들었고 다음은 커밋 메타데이터에 넣을 날짜 정보가 필요하다. 이 날짜는 디렉토리 이름에 있는 것을 가져다 사용한다. `print_export`의 두 번째 줄은 아래와 같다:
535
+
536
+ date = convert_dir_to_date(dir)
537
+
538
+ `convert_dir_to_date`는 아래와 같이 정의한다:
539
+
540
+ def convert_dir_to_date(dir)
541
+ if dir == 'current'
542
+ return Time.now().to_i
543
+ else
544
+ dir = dir.gsub('back_', '')
545
+ (year, month, day) = dir.split('_')
546
+ return Time.local(year, month, day).to_i
547
+ end
548
+ end
549
+
550
+ 시간는 정수 형태로 반환한다. 마지막으로 메타정보에 필요한 것은 Author인데 이 것은 전역 변수 하나로 설정해서 사용한다:
551
+
552
+ $author = 'Scott Chacon <schacon@example.com>'
553
+
554
+ 이제 Importer에서 출력할 커밋 데이터는 다 준비했다. 이제 출력해보자. 사용할 브랜치, 해당 커밋과 관련된 Mark, 커미터 정보, 커밋 메시지, 이전 커밋을 출력한다. 코드로 만들면 아래와 같다:
555
+
556
+ # print the import information
557
+ puts 'commit refs/heads/master'
558
+ puts 'mark :' + mark
559
+ puts "committer #{$author} #{date} -0700"
560
+ export_data('imported from ' + dir)
561
+ puts 'from :' + last_mark if last_mark
562
+
563
+ 우선 시간대(-0700) 정보는 편의상 하드코딩으로 처리했다. 각자의 시간대에 맞는 오프셋을 설정해야 한다. 커밋 메시지는 아래와 같은 형식을 따라야 한다:
564
+
565
+ data (size)\n(contents)
566
+
567
+ 이 형식은 'data'라는 단어, 읽을 데이터의 크기, 줄바꿈 문자, 실 데이터로 구성된다. 이 형식을 여러 곳에서 사용해야 하므로 `export_data`라는 메소드로 만들어 놓는게 좋다:
568
+
569
+ def export_data(string)
570
+ print "data #{string.size}\n#{string}"
571
+ end
572
+
573
+ 이제 남은 것은 스냅샷에 파일 내용를 포함시키는 것 뿐이다. 디렉토리로 구분돼 있기 때문에 어렵지 않다. 우선 `deleteall`이라는 명령을 출력하고 그 뒤에 모든 파일의 내용을 출력한다. 그런면 Git은 스냅샷을 잘 저장한다:
574
+
575
+ puts 'deleteall'
576
+ Dir.glob("**/*").each do |file|
577
+ next if !File.file?(file)
578
+ inline_data(file)
579
+ end
580
+
581
+ 중요: 대부분의 VCS는 리비전을 커밋간의 변화로 생각하기 때문에 `fast-import`에 추가/삭제/변경된 부분만 입력할 수도 있다. 스냅샷 사이의 차이를 구해서 `fast-import`에 넘길 수도 있지만 훨씬 복잡하다. 줄 수 있는 데이터는 전부 Git에 줘서 Git이 계산하게 해야 한다. 꼭 이렇게 해야 한다면 어떻게 데이터를 전달해야 하는지 `fast-import`의 ManPage를 참고하라.
582
+
583
+ 파일 정보와 내용은 아래와 같은 형식으로 출력한다:
584
+
585
+ M 644 inline path/to/file
586
+ data (size)
587
+ (file contents)
588
+
589
+ 644는 파일의 모드를 나타낸다(실행파일이라면 755로 지정해줘야 한다). `inline`은 다음 줄 부터는 파일 내용이라는 말하는 것이다. `inline_data` 메소드는 아래와 같다:
590
+
591
+ def inline_data(file, code = 'M', mode = '644')
592
+ content = File.read(file)
593
+ puts "#{code} #{mode} inline #{file}"
594
+ export_data(content)
595
+ end
596
+
597
+ 파일 내용은 커밋 메시지랑 같은 방법을 사용하기 때문에 앞서 만들어 놓은 `export_data` 메소드를 다시 이용한다.
598
+
599
+ 마지막으로 다음 커밋에 사용할 현 Mark 값을 반환한다:
600
+
601
+ return mark
602
+
603
+ 중요: 윈도에서 실행할 때는 추가 작업이 하나 더 필요하다. 앞에서 얘기했지만 윈도는 CRLF를 사용하지만 `git fast-import`는 LF를 사용한다. 이 문제를 해결 하려면 Ruby가 CRLF 대신 LF를 사용하도록 알려 줘야 한다:
604
+
605
+ $stdout.binmode
606
+
607
+ 모든게 끝났다. 스크립트를 실행하면 아래와 같이 출력된다:
608
+
609
+ $ ruby import.rb /opt/import_from
610
+ commit refs/heads/master
611
+ mark :1
612
+ committer Scott Chacon <schacon@geemail.com> 1230883200 -0700
613
+ data 29
614
+ imported from back_2009_01_02deleteall
615
+ M 644 inline file.rb
616
+ data 12
617
+ version two
618
+ commit refs/heads/master
619
+ mark :2
620
+ committer Scott Chacon <schacon@geemail.com> 1231056000 -0700
621
+ data 29
622
+ imported from back_2009_01_04from :1
623
+ deleteall
624
+ M 644 inline file.rb
625
+ data 14
626
+ version three
627
+ M 644 inline new.rb
628
+ data 16
629
+ new version one
630
+ (...)
631
+
632
+ 디렉토리를 하나 만들고 `git init` 명령을 실행해서 옮길 Git 프로젝트를 만든다. 그리고 그 프로젝트 디렉토리로 이동해서 이 명령의 표준출력을 `git fast-import` 명령의 표준입력으로 연결한다(pipe).
633
+
634
+ $ git init
635
+ Initialized empty Git repository in /opt/import_to/.git/
636
+ $ ruby import.rb /opt/import_from | git fast-import
637
+ git-fast-import statistics:
638
+ ---------------------------------------------------------------------
639
+ Alloc'd objects: 5000
640
+ Total objects: 18 ( 1 duplicates )
641
+ blobs : 7 ( 1 duplicates 0 deltas)
642
+ trees : 6 ( 0 duplicates 1 deltas)
643
+ commits: 5 ( 0 duplicates 0 deltas)
644
+ tags : 0 ( 0 duplicates 0 deltas)
645
+ Total branches: 1 ( 1 loads )
646
+ marks: 1024 ( 5 unique )
647
+ atoms: 3
648
+ Memory total: 2255 KiB
649
+ pools: 2098 KiB
650
+ objects: 156 KiB
651
+ ---------------------------------------------------------------------
652
+ pack_report: getpagesize() = 4096
653
+ pack_report: core.packedGitWindowSize = 33554432
654
+ pack_report: core.packedGitLimit = 268435456
655
+ pack_report: pack_used_ctr = 9
656
+ pack_report: pack_mmap_calls = 5
657
+ pack_report: pack_open_windows = 1 / 1
658
+ pack_report: pack_mapped = 1356 / 1356
659
+ ---------------------------------------------------------------------
660
+
661
+ 성공적으로 끝나면 여기서 보여주는 것처럼 어떻게 됐는지 통계를 보여준다. 이 경우엔 브랜치 1개와 커밋 5개 그리고 개체 18개가 임포트됐다. `git log` 명령으로 히스토리 조회가 가능하다:
662
+
663
+ $ git log -2
664
+ commit 10bfe7d22ce15ee25b60a824c8982157ca593d41
665
+ Author: Scott Chacon <schacon@example.com>
666
+ Date: Sun May 3 12:57:39 2009 -0700
667
+
668
+ imported from current
669
+
670
+ commit 7e519590de754d079dd73b44d695a42c9d2df452
671
+ Author: Scott Chacon <schacon@example.com>
672
+ Date: Tue Feb 3 01:00:00 2009 -0700
673
+
674
+ imported from back_2009_02_03
675
+
676
+ 이 시점에서는 아무것도 Checkout하지 않았기 때문에 워킹 디렉토리에 아직 아무 파일도 없다. `master` 브랜치로 Reset해서 파일을 Checkout한다:
677
+
678
+ $ ls
679
+ $ git reset --hard master
680
+ HEAD is now at 10bfe7d imported from current
681
+ $ ls
682
+ file.rb lib
683
+
684
+ `fast-import` 명령으로 많은 일을 할 수 있다. 모드를 설정하고, 바이너리 데이터를 다루고, 브랜치를 여러 개 다루고, Merge하고, 태그를 달고, 진행상황을 보여 주고, 등등 무수히 많은 일을 할 수 있다. Git 소스의 `contrib/fast-import` 디렉토리에 복잡한 상황을 다루는 예제가 많다. 그 중 여기서 설명한 `git-p4` 스크립트가 좋은 예제이다.
685
+
686
+ ## 요약 ##
687
+
688
+ Subversion 프로젝트에서 Git을 사용하거나, 다른 VCS 저장소를 Git 저장소로 손실 없이 옮기는 방법에 대해 알아 봤다. 다음장에서는 Git 내부를 까본다. 필요하다면 바이트 하나하나 다루는 것도 가능하다.