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,58 @@
1
+ 書籍「Pro Git」のコンテンツ
2
+ ===========================
3
+
4
+ (トップディレクトリにあるREADMEの日本語訳です)
5
+
6
+ これは、書籍「Pro Git」のコンテンツのソースコードです。
7
+ Creative Commons Attribution-Non Commercial-Share Alike 3.0 license のもとで公開
8
+ しています。お楽しみください。本書が Git を学ぶ手助けとなることを期待します。また、
9
+ Apress や私を支援してくださる意味でも、ぜひ書籍版を Amazon からご購入ください。
10
+
11
+ http://tinyurl.com/amazonprogit
12
+
13
+ 訳注: 上のtinyurlは、amazon.comのアフィリエイトIDつきのURLにリダイレクトされます。
14
+
15
+ このコンテンツは以下のURLでも公開されており、翻訳版も10ヶ国語分公開されています。
16
+
17
+ http://git-scm.com/book/
18
+
19
+ Ebookのつくりかた
20
+ =====================
21
+
22
+ Fedora なら、たとえばこのようにします。
23
+
24
+ $ yum install ruby calibre rubygems ruby-devel rubygem-ruby-debug rubygem-rdiscount
25
+ $ gem install rdiscount
26
+ $ makeebooks en # これで mobi ファイルができあがります
27
+
28
+ Mac OSなら、このようにできます。
29
+
30
+ 1. rubyとrubygems をインストールします。
31
+ 2. `$ gem install rdiscount`
32
+ 3. Calibre for MacOSをダウンロードし、コマンドラインツールをインストールします。
33
+ 4. `$ makeebooks zh` #こうするとmobiファイルができあがります。
34
+
35
+ 不具合
36
+ =====================
37
+ 技術的な間違いやその他の修正を要する点を発見した場合は、[issueを作成](https://github.com/progit/progit/issues)してください。
38
+ そうすればメンテナーの誰かが確認してくれるでしょう。
39
+
40
+ 訳注: 当然、issueは英語で書いてください :-) 日本語訳に関する指摘は、日本語版の
41
+ 翻訳に参加しているメンバーの誰かにメッセージを送っていただけるとありがたいです。
42
+
43
+ 翻訳
44
+ =====================
45
+ この本を翻訳してくだされば、その翻訳を git-scm.com のサイトで公開させて
46
+ いただきます。このプロジェクトの適切なサブディレクトリ( [ISO 639](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) で命名してください。)に翻訳を保存し、
47
+ pull requestを送ってください。
48
+
49
+ 訳注: 日本語訳はjaサブディレクトリを使用してください。
50
+
51
+ pull requestの送り方
52
+ =====================
53
+ - 翻訳ファイルの文字コードはUTF-8にしてください。
54
+ - 原文の変更と翻訳の変更、pull requestは分けてください。
55
+ - 翻訳の変更をpull requestにして送る場合、pull requestのタイトルとコミットメッセージに国別の接頭詞をつけてください。 例) [ja] Update chapter 2.
56
+ - 翻訳の変更は、マージ時にコンフリクトが発生しないよう注意してください。メンテナーはコンフリクトの解消を行いません。
57
+ - ファイルが変更されてもPDF/電子書籍への変換、git-scm.comの更新がうまくいくよう、可能な限り確認してください。
58
+
@@ -0,0 +1,33 @@
1
+ # UTF-8でっせ
2
+ (vt)store 格納
3
+ (n)change 変更
4
+ (n)modify 修正
5
+ (vt)stage ステージする
6
+ (n)staging area ステージング・エリア
7
+ (n)GIT directory Gitディレクトリ
8
+ (n)working directory 作業ディレクトリ
9
+ (n)workflow ワークフロー
10
+ (a)comitted コミット済
11
+ (a)modified 修正済
12
+ (a)staged ステージ済
13
+ (n)non-linear development ノンリニア開発
14
+ (n)chapter 章
15
+ # カタカナ用語末尾の長音関連
16
+ # 参考: マイクロソフト日本語スタイルガイド
17
+ # http://www.microsoft.com/language/ja/jp/download.mspx
18
+ # http://www.microsoft.com/japan/presspass/detail.aspx?newsid=3491
19
+ (n)browser ブラウザー
20
+ (n)computer コンピューター
21
+ (n)community コミュニティ
22
+ (n)data データ
23
+ (n)database データベース
24
+ (n)designer デザイナー
25
+ (n)directory ディレクトリ
26
+ (n)installer インストーラー
27
+ (n)interface インターフェイス
28
+ (n)member メンバー
29
+ (n)nonlinear ノンリニア
30
+ (n)programmer プログラマ
31
+ (n)repository リポジトリ
32
+ (n)server サーバー
33
+ (n)user ユーザー
@@ -0,0 +1,258 @@
1
+ # 시작하기 #
2
+
3
+ 이 장에서는 Git을 처음 접하는 사람에게 필요한 내용을 다룬다. 버전 관리 도구에 대한 약간의 배경지식, Git의 특징, Git을 설치하는 법 그리고 Git을 시작하기에 앞서 필요한 설정을 하는 방법을 설명한다. 이 장을 다 읽고 나면 Git의 탄생 배경과 Git이 사용되는 이유를 이해하고, Git을 시작하기 위한 준비가 되어있을 것이다.
4
+
5
+ ## 버전 관리란? ##
6
+
7
+ 버전 관리란 무엇이며, 왜 이것을 알아야 할까? 버전 관리 시스템은 파일의 변화를 시간에 따라 기록하여 과거 특정 시점의 버전을 다시 불러올 수 있는 시스템이다. 이 책에는 소프트웨어의 소스 코드를 버전 관리하는 예만 나오지만 실제로는 모든 컴퓨터 파일이 버전 관리의 대상이 될 수 있다.
8
+
9
+ 이미지나 레이아웃을 수정할 때마다 각각의 형태를 모두 보존하고 싶은 그래픽 디자이너나 웹 디자이너라면 버전 관리 시스템(Version Control System; VCS)을 사용하는 것이 현명할 수 있다. VCS를 사용하면 개별 파일 혹은 프로젝트 전체를 이전 상태로 되돌리거나 시간에 따른 변경 사항을 검토할 수 있으며, 문제가 되는 부분을 누가 마지막으로 수정했는지, 누가 언제 이슈를 만들어냈는지 등을 알 수 있다. 또한 파일을 잃어버리거나 무언가 잘못되어도 대개 쉽게 복구할 수 있다. 그리고 이 모든 장점을 누리는 데는 큰 노력이 들지 않는다.
10
+
11
+ ### 로컬 버전 관리 시스템 ###
12
+
13
+ 대부분의 사람들이 버전 관리를 위해 쓰는 방법은 파일을 다른 디렉토리에 복사하는 것이다(똑똑한 사람이라면 디렉토리 이름에 시간을 넣을 것이다). 이 방법은 간단하고 자주 사용되는 방법이지만 실수가 발생하기 쉽다. 어느 디렉토리에서 작업하고 있었는지 잊어버리고 엉뚱한 파일을 덮어쓰거나 의도하지 않았던 위치로 복사할 수도 있다.
14
+
15
+ 이 문제를 해결하기 위해 오래전에 프로그래머들은 간단한 데이터베이스에 파일의 변경 사항을 기록하는 로컬 버전 관리 시스템을 만들었다(그림 1-1 참조).
16
+
17
+ Insert 18333fig0101.png
18
+ 그림 1-1. 로컬 버전 관리 다이어그램
19
+
20
+ 유명했던 VCS 도구들 중 현재에도 널리 쓰이는 것으로 RCS라 불리는 시스템이 있다. 그 예로 Mac OS X 운영체제에서는 개발 도구를 설치하면 RCS가 딸려온다. RCS의 기본적인 동작 방식은 각 리비전들 간의 패치 세트(patch set)라고 하는 데이터의 차이점들을 특별한 형식의 파일에 저장, 특정 시점의 파일 내용을 보고 싶을 때 해당 시점까지의 패치들을 모두 더하여 파일을 만들어내는 것이다.
21
+
22
+ ### 중앙집중식 버전 관리 시스템 ###
23
+
24
+ 또 다른 문제는 시스템 외부에 있는 개발자들과 함께 작업하는 것이다. 중앙집중식 버전 관리 시스템(Centralized Version Control System; CVCS)은 이 문제를 해결하기 위해 개발됐다. CVS, Subversion, Perforce와 같은 시스템들이 여기에 속한다. CVCS에서는 버전 관리되는 모든 파일을 저장하는 하나의 서버와, 이 중앙 서버에서 파일들을 가져오는(checkout) 다수의 클라이언트가 존재한다. 오랫동안 사용된 이 방식은 지금까지도 버전 관리의 대표적인 방식이다(그림 1-2 참조).
25
+
26
+ Insert 18333fig0102.png
27
+ 그림 1-2. 중앙집중식 버전 관리 다이어그램
28
+
29
+ CVCS는 로컬 VCS에 비해 장점이 많다. 누구나 다른 사람들이 무엇을 하고 있는지 알 수 있고, 관리자는 누가 무엇을 할 수 있는지 꼼꼼하게 관리할 수 있다. CVCS를 관리하는 것은 수많은 클라이언트의 로컬 데이터베이스를 관리하는 것보다 훨씬 쉽다.
30
+
31
+ 그러나 CVCS는 심각한 단점이 있다. 중앙 서버가 잘못되면 모든 것이 잘못된다는 점이다. 서버가 다운될 경우 서버가 다시 복구될 때까지 다른 사람과의 협업도, 진행 중이던 작업을 버전 관리하는 것도 불가능해진다. 중앙 데이터베이스가 저장된 하드디스크에 오류가 발생하고 백업도 없다면, 사람들이 각자 자신의 컴퓨터에 가지고 있던 스냅샷 외에는 그동안 쌓인 프로젝트의 이력을 모두 잃게 된다. 로컬 VCS 시스템도 같은 문제가 있다. 프로젝트의 모든 이력이 한곳에만 있을 경우 이것은 피할 수 없는 문제다.
32
+
33
+ ### 분산 버전 관리 시스템 ###
34
+
35
+ 분산 버전 관리 시스템(Distributed Version Control System; DVCS)은 앞서 말한 문제를 해결하기 위해 개발되었다. Git, Mecurial, Bazaar, Darcs 등 DVCS에서는 클라이언트가 파일들의 마지막 스냅샷을 가져오는 대신 저장소(repository)를 통째로 복제한다. 따라서 서버에 문제가 생겨도 어느 클라이언트든 복제된 저장소를 다시 서버로 복사하면 서버가 복구된다. 체크아웃(checkout)을 할 때마다 전체 백업이 일어나는 셈이다(그림 1-3 참조).
36
+
37
+ Insert 18333fig0103.png
38
+ 그림 1-3. 분산 버전 관리 시스템 다이어그램
39
+
40
+ 게다가 대부분의 DVCS에서는 다수의 원격 저장소(remote repository)를 갖는 것이 가능하기 때문에 동시에 여러 그룹과 여러 방법으로 함께 작업할 수 있다. 이로 인해 계층 모델(hierarchical model) 등 중앙집중 시스템에서는 할 수 없는 다양한 작업 방식(workflow)들을 사용해볼 수 있다.
41
+
42
+ ## 짧게 보는 Git의 역사 ##
43
+
44
+ 인생을 살다 보면 여러 가지 일들이 벌어지듯이 Git의 삶 또한 창조적인 파괴와 모순 속에서 시작되었다. 리눅스 커널은 굉장히 규모가 큰 오픈소스 프로젝트다. 리눅스 커널의 일생에서 대부분 시절은 패치와 단순 압축 파일로만 관리했다. 2002년에 드디어 리눅스 커널은 BitKeeper라고 불리는 상용 DVCS를 사용하기 시작했다.
45
+
46
+ 2005년에 커뮤니티가 만드는 리눅스 커널과 이익을 추구하는 회사가 개발한 BitKeeper의 관계는 틀어졌다. BitKeeper의 무료 사용이 제고된 것이다. 이 사건은 리눅스 개발 커뮤니티(특히 리눅스 창시자 리누스 토발즈)가 자체 도구를 만드는 계기가 됐다. Git은 BitKeeper를 사용하면서 배운 교훈을 기초로 아래와 같은 목표를 세웠다:
47
+
48
+ * 빠른 속도
49
+ * 단순한 구조
50
+ * 비선형적인 개발(수천 개의 동시 다발적인 브랜치)
51
+ * 완벽한 분산
52
+ * 리눅스 커널 같은 대형 프로젝트에도 유용할 것(속도나 데이터 크기 면에서)
53
+
54
+ Git은 2005년 탄생하고 나서 아직도 초기 목표를 그대로 유지하고 있다. 그러면서도 사용하기 쉽게 진화하고 성숙했다. Git은 미친 듯이 빨라서 대형 프로젝트에 사용하기도 좋다. Git은 동시다발적인 브랜치에도 끄떡없는 슈퍼 울트라 브랜칭 시스템이다(*3장* 참고).
55
+
56
+ ## Git 기초 ##
57
+
58
+ Git의 핵심은 뭘까? 이 질문은 Git을 이해하는데 굉장히 중요하다. Git이 무엇이고 어떻게 동작하는지 이해한다면 쉽게 Git을 효과적으로 사용할 수 있다. Git을 배우려면 Subversion이나 Perforce 같은 다른 VCS를 사용하던 경험을 지워버려야 한다. Git은 미묘하게 달라서 다른 VCS에서 쓰던 개념으로는 헷갈릴 거다. 사용자 인터페이스는 매우 비슷하지만, 정보를 취급하는 방식이 다르다. 이런 차이점을 이해하면 Git을 사용하는 것이 어렵지 않다.
59
+
60
+ ### 델타가 아니라 스냅샷 ###
61
+
62
+ Subversion과 Subversion 비슷한 놈들과 Git의 가장 큰 차이점은 데이터를 다루는 방법에 있다. 큰 틀에서 봤을 때 대부분의 VCS 시스템이 관리하는 정보는 파일들의 목록이다. CVS, Subversion, Perforce, Bazaar 등의 시스템은 파일의 집합으로 정보를 관리한다. 각 파일의 변화를 그림 1-4처럼 시간순으로 관리한다.
63
+
64
+ Insert 18333fig0104.png
65
+ 그림 1-4. 각 파일에 대한 변화(델타)를 저장하는 시스템들
66
+
67
+ Git은 이런 식으로 데이터를 저장하지도 취급하지도 않는다. 대신 Git의 데이터는 파일 시스템의 스냅샷이라 할 수 있으며 크기가 아주 작다. Git은 커밋하거나 프로젝트의 상태를 저장할 때마다 파일이 존재하는 그 순간을 중요하게 여긴다. 파일이 달라지지 않았으면 Git은 성능을 위해서 파일을 저장하지 않는다. 단지 이전 상태의 파일에 대한 링크만 저장한다. Git은 그림 1-5처럼 동작한다.
68
+
69
+ Insert 18333fig0105.png
70
+ 그림 1-5. Git은 시간순으로 프로젝트의 스냅샷을 저장한다
71
+
72
+ 이것이 Git이 다른 VCS와 구분되는 점이다. 이점 때문에 Git는 다른 시스템들이 과거로부터 답습해왔던 버전 컨트롤의 개념과 다르다는 것이고 많은 부분을 새로운 관점에서 바라본다. Git은 강력한 도구를 지원하는 작은 파일시스템이다. Git은 단순한 VCS가 아니다. 이제 3장에서 설명할 Git 브랜치를 사용하면 얻게 되는 이득이 무엇인지 설명한다.
73
+
74
+ ### 거의 모든 명령을 로컬에서 실행 ###
75
+
76
+ 거의 모든 명령이 로컬 파일과 데이터만 사용하기 때문에 네트워크에 있는 다른 컴퓨터는 필요 없다. 대부분의 명령어가 네트워크의 속도에 영향을 받는 CVCS에 익숙하다면 Git이 매우 놀라울 것이다. Git의 이런 특징에서 나오는 미칠듯한 속도는 오직 Git느님만이 구사할 수 있는 초인적인 능력이다. 프로젝트의 모든 히스토리가 로컬 디스크에 있기 때문에 모든 명령을 순식간에 실행된다.
77
+
78
+ 예를 들어 Git은 프로젝트의 히스토리를 조회할 때 서버 없이 조회한다. 그냥 로컬 데이터베이스에서 히스토리를 읽어서 보여 준다. 그래서 눈 깜짝할 사이에 히스토리를 조회할 수 있다. 어떤 파일의 현재 버전과 한 달 전의 상태를 비교해보고 싶을 때도 Git은 그냥 한 달 전의 파일과 지금의 파일을 로컬에서 찾는다. 파일을 비교하기 위해 리모트에 있는 서버에 접근하고 나서 예전 버전을 가져올 필요가 없다.
79
+
80
+ 즉 오프라인 상태에서도 비교할 수 있다. 비행기나 기차 등에서 작업하고 네트워크에 접속하고 있지 않아도 커밋할 수 있다. 다른 VCS 시스템에서는 불가능한 일이다. Perforce는 서버에 연결할 수 없을 때 할 수 있는 일이 별로 없다. Subversion이나 CVS에서도 마찬가지다. 데이터베이스에 접근할 수 없어서 파일을 편집할 수는 있지만, 커밋할 수 없다. 매우 사소해 보이지만 실제로 이 상황에 부닥쳐보면 느껴지는 차이가 매우 크다.
81
+
82
+ ### Git의 무결성 ###
83
+
84
+ Git은 모든 데이터를 저장하기 전에 체크섬(또는 해시)을 구하고 그 체크섬으로 데이터를 관리한다. 체크섬 없이 어떠한 파일이나 디렉토리도 변경할 수 없다. 체크섬은 Git에서 사용하는 가장 기본적인(Atomic) 데이터 단위이자 Git의 기본 철학이다. Git 없이는 체크섬을 다룰 수 없어서 파일의 상태도 알 수 없고 심지어 데이터를 잃어버릴 수도 없다.
85
+
86
+ Git은 SHA-1 해시를 사용하여 체크섬을 만든다. 만든 체크섬은 40자 길이의 16진수 문자열이다. 파일의 내용이나 디렉토리 구조를 이용하여 체크섬을 구한다. SHA-1은 아래처럼 생겼다:
87
+
88
+ 24b9da6552252987aa493b52f8696cd6d3b00373
89
+
90
+ Git은 모든 것을 해시로 식별하기 때문에 이런 값은 여기저기서 보인다. 실제로 Git은 파일을 이름으로 저장하지 않고 해당 파일의 해시로 저장한다.
91
+
92
+ ### Git은 데이터를 추가할 뿐 ###
93
+
94
+ Git으로 무얼 하든 데이터를 추가한다. 되돌리거나 데이터를 삭제할 방법이 없다. 다른 VCS처럼 Git도 커밋하지 않으면 변경사항을 잃어버릴 수 있다. 하지만, 일단 스냅샷을 커밋하고 나면 데이터를 잃어버리기 어렵다.
95
+
96
+ Git을 사용하면 프로젝트가 심각하게 망가질 걱정 없이 매우 즐겁게 여러 가지 실험을 해 볼 수 있다. *9장*을 보면 Git이 데이터를 어떻게 저장하고 손실을 어떻게 복구해야 할지 알 수 있다.
97
+
98
+ ### 세 가지 상태 ###
99
+
100
+ 이 부분은 중요하기에 집중해서 읽어야 한다. Git을 공부하기 위해 반드시 짚고 넘어가야 할 부분이다. Git은 파일을 Committed, Modified, Staged 이렇게 세 가지 상태로 관리한다. Committed란 데이터가 로컬 데이터베이스에 안전하게 저장됐다는 것을 의미한다. Modified는 수정한 파일을 아직 로컬 데이터베이스에 커밋하지 않은 것을 말한다. Staged란 현재 수정한 파일을 곧 커밋할 것이라고 표시한 상태를 의미한다.
101
+
102
+ 이 세 가지 상태는 Git 프로젝트의 세 가지 단계와 연결돼 있다. Git 디렉토리, 워킹 디렉토리, Staging Area 이렇게 세 가지 단계를 이해하고 넘어가자.
103
+
104
+ Insert 18333fig0106.png
105
+ 그림 1-6. 워킹 디렉토리, Staging Area, Git 디렉토리
106
+
107
+ Git 디렉토리는 Git이 프로젝트의 메타데이터와 객체 데이터베이스를 저장하는 곳을 말한다. Git 디렉토리가 Git의 핵심이다. 다른 컴퓨터에 있는 저장소를 Clone 할 때 Git 디렉토리가 만들어진다.
108
+
109
+ 워킹 디렉토리는 프로젝트의 특정 버전을 Checkout한 것이다. Git 디렉토리는 지금 작업하는 디스크에 있고 그 디렉토리에 압축된 데이터베이스에서 파일을 가져와서 워킹 디렉토리를 만든다.
110
+
111
+ Staging Area는 Git 디렉토리에 있다. 단순한 파일이고 곧 커밋할 파일에 대한 정보를 저장한다. 종종 인덱스라고 불리기도 하지만, Staging Area라는 명칭이 표준이 되어가고 있다.
112
+
113
+ Git으로 하는 일은 기본적으로 아래와 같다:
114
+
115
+ - 워킹 디렉토리에서 파일을 수정한다.
116
+ - Staging Area에 파일을 Stage해서 커밋할 스냅샷을 만든다.
117
+ - Staging Area에 있는 파일들을 커밋해서 Git 디렉토리에 영구적인 스냅샷으로 저장한다.
118
+
119
+ Git 디렉토리에 있는 파일들은 Committed 상태이다. 파일을 수정하고 Staging Area에 추가했다면 Staged이다. 그리고 Checkout하고 나서 수정했지만, 아직 Staging Area에 추가하지 않았으면 Modified이다. *2장*에서 이 상태에 대해 좀 더 자세히 배운다. 특히 Staging Area를 어떻게 이용하는지 혹은 아예 생략하는 방법도 설명한다.
120
+
121
+ ## Git 설치 ##
122
+
123
+ Git을 사용하려면 우선 설치해야 한다. 다양한 방법으로 Git을 설치할 수 있지만 두 가지 방법이 가장 일반적이다. 하나는 소스코드로 컴파일하여 설치하는 방법이고 다른 하나는 각 운영체제(혹은 플랫폼)의 패키지를 사용하여 설치하는 방법이다.
124
+
125
+ ### 소스코드로 설치하기 ###
126
+
127
+ 소스코드로 설치하면 Git의 가장 최신 버전을 설치할 수 있기 때문에 컴파일하여 설치할 시간이 있으면 소스코드로 Git을 설치하는 것이 좋다. Git은 계속 UI를 개선하고 있기 때문에 최신 버전을 사용하면 좋은 기능을 빨리 사용할 수 있다. 리눅스 패키지는 보통 최신 버전이 아니고 예전 버전이다. 그래서 Backport를 사용하거나 소스코드로 설치하는 것도 좋은 대안이다.
128
+
129
+ Git을 설치하려면 아래와 같은 라이브러리들이 필요하다. Git은 curl, zlib, openssl, expat, libiconv를 필요로 한다. 예를 들어 Fedora처럼 yum을 사용하는 시스템이나 apt-get이 있는 데비안류 시스템이면 아래 명령어를 실행하여 의존 패키지를 설치할 수 있다:
130
+
131
+ $ yum install curl-devel expat-devel gettext-devel \
132
+ openssl-devel zlib-devel
133
+
134
+ $ apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \
135
+ libz-dev libssl-dev
136
+
137
+ 필요한 라이브러리를 모두 설치하고 다음 단계를 진행한다. Git 웹 사이트에서 최신 스냅샷을 가져온다:
138
+
139
+ http://git-scm.com/download
140
+
141
+ 그리고 컴파일하고 설치한다:
142
+
143
+ $ tar -zxf git-1.7.2.2.tar.gz
144
+ $ cd git-1.7.2.2
145
+ $ make prefix=/usr/local all
146
+ $ sudo make prefix=/usr/local install
147
+
148
+ 설치한 다음부터는 Git을 사용하여 Git 소스코드를 수정할 수 있다:
149
+
150
+ $ git clone git://git.kernel.org/pub/scm/git/git.git
151
+
152
+ ### 리눅스에 설치 ###
153
+
154
+ 리눅스에서 패키지로 Git을 설치할 때에는 보통 각 배포판에서 사용하는 패키지 관리도구를 사용하여 설치한다. Fedora에서는 아래와 같이 한다:
155
+
156
+ $ yum install git-core
157
+
158
+ Ubuntu같은 데비안류 배포판에서는 apt-get을 사용한다:
159
+
160
+ $ apt-get install git
161
+
162
+ ### Mac에 설치하기 ###
163
+
164
+ Mac에 Git을 쉽게 설치하는 방법은 두 가지가 있다. GUI 인스톨러가 가장 쉽게 사용할 수 있다. SourceForge 페이지에서 내려받는다:
165
+
166
+ http://sourceforge.net/projects/git-osx-installer/
167
+
168
+ Insert 18333fig0107.png
169
+ 그림 1-7. OS X Git 인스톨러
170
+
171
+ MacPorts(`http://www.macports.org`)를 사용하는 방법도 있다. MacPorts가 설치돼 있으면 아래와 같이 Git을 설치한다:
172
+
173
+ $ sudo port install git-core +svn +doc +bash_completion +gitweb
174
+
175
+ 이제 설치는 했다. 만약 Subversion 저장소를 Git과 함께 사용해야 하면 svn도 필요하다.
176
+
177
+ ### 윈도에 설치 ###
178
+
179
+ 윈도에서도 Git을 쉽게 설치할 수 있다. 그저 구글 코드 페이지에서 msysGit 인스톨러를 내려받고 실행하면 된다:
180
+
181
+ http://msysgit.github.com/
182
+
183
+ 설치가 완료되면 CLI 프로그램과 GUI 프로그램을 둘 다 사용할 수 있다. CLI 프로그램에는 SSH 클라이언트가 포함돼 있기 때문에 유용하다.
184
+
185
+ Windows 사용자 필독:이 책에서 소개하는 다양한 명령어를 사용하려면 유닉스 스타일의 msysGit 쉘을 사용하는 것이 좋다. 어쩔 수 없이 Windows에 포함된 기본 쉘(Command Prompt, 명령 프롬프트)을 꼭 써야 하면 공백이 포함된 파라미터를 Git 명령어에 넘길 때 작은 따옴표(' ') 대신 큰 따옴표(" ")를 사용해야 한다. 파라미터 끝에 `^` 기호가 있을 때도 큰 따옴표로 파라미터를 감싸야 한다. Windows 쉘에서 `^` 기호는 다음 줄로 명령어가 이어짐을 나타낸다.
186
+
187
+ ## Git 최초 설정 ##
188
+
189
+ Git을 설치하고 나면 Git의 사용 환경을 적절하게 설정해 주어야 한다. 한 번만 설정하면 된다. 설정한 내용은 Git을 업그레이드해도 유지된다. 언제든지 다시 바꿀 수 있는 명령어가 있다.
190
+
191
+ 'git config'라는 도구로 설정 내용을 확인하고 변경할 수 있다. Git은 이 설정에 따라 동작한다. 이때 사용하는 설정 파일은 세 가지나 된다.
192
+
193
+ * `/etc/gitconfig` 파일: 시스템의 모든 사용자와 모든 저장소에 적용되는 설정이다. `git config --system` 옵션으로 이 파일을 읽고 쓸 수 있다.
194
+ * `~/.gitconfig` 파일: 특정 사용자에게만 적용되는 설정이다. `git config --global` 옵션으로 이 파일을 읽고 쓸 수 있다.
195
+ * `.git/config`: 이 파일은 Git 디렉토리에 있고 특정 저장소(혹은 현재 작업 중인 프로젝트)에만 적용된다. 각 설정은 역순으로 우선시 된다. 그래서 `.git/config`가 `/etc/gitconfig`보다 우선한다.
196
+
197
+ 윈도용 Git은 `$HOME` 디렉토리(`%USERPROFILE%` 환경변수)에 있는 `.gitconfig` 파일을 찾는다. 보통 `C:\Documents and Settings\$USER` 또는 `C:\Users\$USER` 이다(윈도우에서는 `$USER` 대신 `%USERNAME%`를 사용한다). 그리고 msysGit도 /etc/gitconfig를 가지고 있다. 경로는 MSys 루트에 따른 상대 경로다. 인스톨러로 msysGit을 설치할 때 설치 경로를 선택할 수 있다.
198
+
199
+ ### 사용자 정보 ###
200
+
201
+ Git을 설치하고 나서 가장 먼저 해야 하는 것은 사용자 이름과 이메일 주소를 설정하는 것이다. Git은 커밋할 때마다 이 정보를 사용한다. 한 번 커밋한 후에는 정보를 변경할 수 없다:
202
+
203
+ $ git config --global user.name "John Doe"
204
+ $ git config --global user.email johndoe@example.com
205
+
206
+ 다시 말하자면 `--global` 옵션으로 설정한 것은 딱 한 번만 하면 된다. 해당 시스템에서 해당 사용자가 사용할 때에는 이 정보를 사용한다. 만약 프로젝트마다 다른 이름과 이메일 주소를 사용하고 싶으면 `--global` 옵션을 빼고 명령을 실행한다.
207
+
208
+ ### 편집기 ###
209
+
210
+ 사용자 정보를 설정하고 나면 Git에서 사용할 텍스트 편집기를 고른다. 기본적으로 Git은 시스템의 기본 편집기를 사용하고 보통 Vi나 Vim이다. 하지만, Emacs 같은 다른 텍스트 편집기를 사용할 수 있고 아래와 같이 실행하면 된다:
211
+
212
+ $ git config --global core.editor emacs
213
+
214
+ ### Diff 도구 ###
215
+
216
+ Merge 충돌을 해결하기 위해 사용하는 Diff 도구를 설정할 수 있다. vimdiff를 사용하고 싶으면 아래와 같이 실행한다:
217
+
218
+ $ git config --global merge.tool vimdiff
219
+
220
+ 이렇게 kdiff3, tkdiff, meld, xxdif, emerge, vimdiff, gvimdiff, ecmerge, opendiff를 사용할 수 있다. 물론 다른 도구도 사용할 수 있다. 자세한 내용은 *7장*에서 다룬다.
221
+
222
+ ### 설정 확인 ###
223
+
224
+ `git config --list` 명령을 실행하면 설정한 모든 것을 보여준다:
225
+
226
+ $ git config --list
227
+ user.name=Scott Chacon
228
+ user.email=schacon@gmail.com
229
+ color.status=auto
230
+ color.branch=auto
231
+ color.interactive=auto
232
+ color.diff=auto
233
+ ...
234
+
235
+ Git은 같은 키를 여러 파일(`/etc/gitconfig`와 `~/.gitconfig` 같은)에서 읽기 때문에 같은 키가 여러개 있을 수도 있다. 이러면 Git은 나중 값을 사용한다.
236
+
237
+ `git config {key}` 명령으로 Git이 특정 Key에 대해 어떤 값을 사용하는지 확인할 수 있다:
238
+
239
+ $ git config user.name
240
+ Scott Chacon
241
+
242
+ ## 도움말 보기 ##
243
+
244
+ 명령어에 대한 도움말이 필요할 때 도움말을 보는 방법은 세 가지다:
245
+
246
+ $ git help <verb>
247
+ $ git <verb> --help
248
+ $ man git-<verb>
249
+
250
+ 예를 들어 아래와 같이 실행하면 config 명령에 대한 도움말을 볼 수 있다:
251
+
252
+ $ git help config
253
+
254
+ 도움말은 언제 어디서나 볼 수 있다. 오프라인으로도 볼 수 있다. 도움말과 이 책으로 부족하면 다른 사람의 도움을 받는 것이 필요하다. Freenode IRC 서버(irc.freenode.net)에 있는 `#git`이나 `#github` 채널로 찾아가라. 이 채널에는 보통 수백 명의 사람이 접속해 있다. 이 사람들은 모두 Git에 대해 잘 알고 있다. 기꺼이 도와줄 것이다.
255
+
256
+ ## 요약 ##
257
+
258
+ 우리는 Git이 무엇이고 지금까지 사용해 온 다른 CVCS와 어떻게 다른지 배웠다. 시스템에 Git을 설치하고 사용자 정보도 설정했다. 다음 장에서는 Git의 사용법을 배운다.
@@ -0,0 +1,1181 @@
1
+ # Git의 기초 #
2
+
3
+ Git을 사용하는 방법을 알고 싶은데 한 챕터밖에 읽을 시간이 없다면 2장을 읽어야 한다. Git에서 자주 사용하는 명령어는 모두 2장에 등장한다. 2장을 다 읽으면 저장소를 만들고 설정하는 방법, 파일을 추적하거나(Track) 추적을 그만두는 방법, 변경 내용을 Stage하고 커밋하는 방법을 알게 된다. 그리고 또 파일이나 파일 패턴을 무시하도록 Git을 설정하는 방법, 실수를 쉽고 빠르게 만회하는 방법, 프로젝트 히스토리를 조회하고 커밋을 비교하는 방법, 리모트 저장소에 Push하고 Pull하는 방법을 살펴본다.
4
+
5
+ ## Git 저장소 만들기 ##
6
+
7
+ Git 저장소를 만드는 방법은 두 가지다. 기존 프로젝트를 Git 저장소로 만드는 방법이 있고 다른 서버에 있는 저장소를 Clone하는 방법이 있다.
8
+
9
+ ### 기존 디렉토리를 Git 저장소로 만들기 ###
10
+
11
+ 기존 프로젝트를 Git으로 관리하고 싶을 때, 프로젝트의 디렉토리로 이동해서 아래과 같은 명령을 실행한다.
12
+
13
+ $ git init
14
+
15
+ 이 명령은 `.git`이라는 하위 디렉토리를 만든다. `.git` 디렉토리에는 저장소에 필요한 뼈대 파일(Skeleton)이 들어 있다(`.git` 디렉토리가 막 만들어진 직후에 어떤 파일이 있는지에 대한 내용은 *9장*에서 다룬다). 이 명령만으로는 아직 프로젝트의 어떤 파일도 관리하지 않는다.
16
+
17
+ Git이 파일을 관리하게 하려면 저장소에 파일을 추가하고 커밋해야 한다. `git add` 명령으로 파일을 추가하고 커밋한다:
18
+
19
+ $ git add *.c
20
+ $ git add README
21
+ $ git commit -m 'initial project version'
22
+
23
+ 매우 짧은 시간에 명령어를 몇개 실행해서 Git 저장소를 만들고 파일이 관리되게 했다.
24
+
25
+ ### 기존 저장소를 Clone하기 ###
26
+
27
+ 다른 프로젝트에 참여하거나(Contribute) Git 저장소를 복사하고 싶을 때 `git clone` 명령을 사용한다. 이미 Subversion 같은 VCS에 익숙한 사용자에게는 `checkout`이 아니라 `clone`이라는 점이 도드라져 보일 것이다. Git이 Subversion과 다른 가장 큰 차이점은 서버에 있는 모든 데이터를 복사한다는 것이다. `git clone`을 실행하면 프로젝트 히스토리를 전부 받아온다. 실제로 서버의 디스크가 망가져도 클라이언트 저장소 중에서 아무거나 하나 가져다가 복구하면 된다(서버에만 적용했던 설정은 복구하지 못하지만 모든 데이터는 복구된다 - *4장*에서 좀 더 자세히 다룬다).
28
+
29
+ `git clone [url]` 명령으로 저장소를 Clone한다. Ruby용 Git 라이브러리인 Grit을 Clone하려면 아래과 같이 실행한다:
30
+
31
+ $ git clone git://github.com/schacon/grit.git
32
+
33
+ 이 명령은 "grit"이라는 디렉토리를 만들고 그 안에 `.git` 디렉토리를 만든다. 그리고 저장소의 데이터를 모두 가져와서 자동으로 가장 최신 버전을 Checkout해 놓는다. `grit` 디렉토리로 이동하면 Checkout으로 생성한 파일을 볼 수 있고 당장 하고자 하는 일을 시작할 수 있다. 아래과 같은 명령을 사용하여 저장소를 Clone하면 "grit"이 아니라 다른 디렉토리 이름으로 Clone할 수 있다:
34
+
35
+ $ git clone git://github.com/schacon/grit.git mygrit
36
+
37
+ 디렉토리 이름이 `mygrit`이라는 것만 빼면 이 명령의 결과와 앞선 명령의 결과는 같다.
38
+
39
+ Git은 다양한 프로토콜을 지원한다. 이제까지는 `git://` 프로토콜을 사용했지만 `http(s)://`를 사용할 수도 있고 `user@server:/path.git`처럼 SSH 프로토콜을 사용할 수도 있다. 자세한 내용은 *4장*에서 다룬다. *4장*에서는 각 프로토콜의 장단점과 Git 저장소에 접근하는 방법을 설명한다.
40
+
41
+ ## 수정하고 저장소에 저장하기 ##
42
+
43
+ 만질 수 있는 Git 저장소를 하나 만들었고 워킹 디렉토리에 Checkout도 했다. 이제는 파일을 수정하고 파일의 스냅샷을 커밋해 보자. 파일을 수정하다가 저장하고 싶으면 스냅샷을 커밋한다.
44
+
45
+ 워킹 디렉토리의 모든 파일은 크게 *Tracked*(관리대상임)와 *Untracked*(관리대상이 아님)로 나눈다. *Tracked* 파일은 이미 스냅샷에 포함돼 있던 파일이다. *Tracked* 파일은 또 *Unmodified*(수정하지 않음)와 *Modified*(수정함) 그리고 *Staged*(커밋하면 저장소에 기록되는) 상태 중 하나이다. 그리고 나머지 파일은 모두 *Untracked* 파일이다. *Untracked* 파일은 워킹 디렉토리에 있는 모든 파일이 스냅샷에 포함돼 있는 것은 아니고 Staging Area에 있는 것도 아니다. 처음 저장소를 Clone하면 모든 파일은 *Tracked*이면서 *Unmodified* 상태가 된다. 파일을 Checkout하고 나서 아무것도 수정하지 않았기 때문에 그렇다.
46
+
47
+ 마지막 커밋 이후 아직 아무것도 수정하지 않은 상태에서 어떤 파일이 수정되면 Git은 그 즉시 파일을 *Modified* 상태로 인식한다. 그리고 이 수정한 파일을 Stage하고 *Staged* 상태인 파일을 커밋한다. 이 라이프사이클을 그림 2-1처럼 계속 반복한다.
48
+
49
+ Insert 18333fig0201.png
50
+ 그림 2-1. 파일의 라이프사이클
51
+
52
+ ### 파일의 상태 확인하기 ###
53
+
54
+ 파일의 상태를 확인하려면 보통 `git status` 명령을 사용한다. Clone한 후에 바로 이 명령을 실행하면 아래과 같은 메시지를 볼 수 있다:
55
+
56
+ $ git status
57
+ On branch master
58
+ nothing to commit, working directory clean
59
+
60
+ 위의 내용은 파일을 하나도 수정하지 않았다는 것을 말해준다. Tracked나 Modified 상태인 파일이 없다는 의미다. Untracked 파일은 아직 없어서 목록에 나타나지 않는다. 그리고 현재 작업 중인 브랜치를 알려준다. 기본 브랜치가 master이기 때문에 현재 master로 나오는 것이다. 브랜치 관련 내용은 차차 알아가자. 다음 장에서 브랜치와 레퍼런스에 대해 자세히 다룬다.
61
+
62
+ 프로젝트에 `README` 파일을 만들어보자. `README` 파일은 새로 만든 파일이기 때문에 `git status`를 실행하면 'Untracked files'에 들어 있다:
63
+
64
+ $ vim README
65
+ $ git status
66
+ On branch master
67
+ Untracked files:
68
+ (use "git add <file>..." to include in what will be committed)
69
+
70
+ README
71
+
72
+ nothing added to commit but untracked files present (use "git add" to track)
73
+
74
+ `README` 파일은 `Untracked files` 부분에 속해 있는데 이것은 `README` 파일이 Untracked 상태라는 것을 말한다. Git은 Untracked 파일을 아직 스냅샷(커밋)에 넣어지지 않은 파일이라고 본다. 파일이 Tracked 상태가 되기 전까지는 Git은 절대 그 파일을 커밋하지 않는다. 그래서 일하면서 생성하는 바이너리 파일 같은 것을 커밋하는 실수는 하지 않게 된다. README 파일을 추가해서 직접 Tracked 상태로 만들어 보자.
75
+
76
+ ### 파일을 새로 추적하기 ###
77
+
78
+ `git add` 명령으로 파일을 새로 추적할 수 있다. 아래 명령을 실행하면 Git은 `README` 파일을 추적한다:
79
+
80
+ $ git add README
81
+
82
+ `git status` 명령을 다시 실행하면 README 파일이 Tracked 상태이면서 Staged 상태라는 것을 확인할 수 있다:
83
+
84
+ $ git status
85
+ On branch master
86
+ Changes to be committed:
87
+ (use "git reset HEAD <file>..." to unstage)
88
+
89
+ new file: README
90
+
91
+
92
+ 'Changes to be committed' 에 들어 있는 파일은 Staged 상태라는 것을 의미한다. 커밋하면 `git add`를 실행한 시점의 파일이 커밋되어 저장소 히스토리에 남는다. 앞에서 `git init` 명령을 실행했을 때, 그 다음 `git add (files)` 명령을 실행했던 걸 기억할 것이다. 이것은 작업 디렉토리에 있는 파일들을 추적하기 시작하게 하였다. `git add` 명령은 파일 또는 디렉토리의 경로명을 아규먼트로 받는다; 만일 디렉토리를 아규먼트로 줄 경우, 그 디렉토리 아래에 있는 모든 파일들을 재귀적으로 추가한다.
93
+
94
+ ### Modified 상태의 파일을 Stage하기 ###
95
+
96
+ 이미 Tracked 상태인 파일을 수정하는 법을 알아보자. `benchmarks.rb`라는 파일을 수정하고 나서 `git status` 명령을 다시 실행하면 결과는 아래와 같다:
97
+
98
+ $ git status
99
+ On branch master
100
+ Changes to be committed:
101
+ (use "git reset HEAD <file>..." to unstage)
102
+
103
+ new file: README
104
+
105
+ Changes not staged for commit:
106
+ (use "git add <file>..." to update what will be committed)
107
+ (use "git checkout -- <file>..." to discard changes in working directory)
108
+
109
+ modified: benchmarks.rb
110
+
111
+
112
+ 이 `benchmarks.rb` 파일은 `Changes not staged for commit`에 있다. 이것은 수정한 파일이 Tracked 상태이지만 아직 Staged 상태는 아니라는 것이다. Staged 상태로 만들려면 `git add` 명령을 실행해야 한다. `git add`는 파일을 새로 추적할 때도 사용하고 수정한 파일을 Staged 상태로 만들 때도 사용한다. `git add`를 실행하여 benchmarks.rb 파일을 Staged 상태로 만들고 `git status` 명령으로 결과를 확인해보자:
113
+
114
+ $ git add benchmarks.rb
115
+ $ git status
116
+ On branch master
117
+ Changes to be committed:
118
+ (use "git reset HEAD <file>..." to unstage)
119
+
120
+ new file: README
121
+ modified: benchmarks.rb
122
+
123
+
124
+ 두 파일 모두 Staged 상태이므로 다음 커밋에 포함된다. 하지만, 아직 더 수정해야 한다는 것을 알게 되어 바로 커밋하지 못하는 상황이 되었다고 하자. 이 상황에서 benchmark.rb 파일을 열고 수정한다. 아마 당신은 커밋할 준비가 다 됐다고 생각할 테지만, Git은 그렇지 않다. `git status` 명령으로 파일의 상태를 다시 확인해보자:
125
+
126
+ $ vim benchmarks.rb
127
+ $ git status
128
+ On branch master
129
+ Changes to be committed:
130
+ (use "git reset HEAD <file>..." to unstage)
131
+
132
+ new file: README
133
+ modified: benchmarks.rb
134
+
135
+ Changes not staged for commit:
136
+ (use "git add <file>..." to update what will be committed)
137
+
138
+ modified: benchmarks.rb
139
+
140
+
141
+ 헉! benchmarks.rb가 Staged 상태이면서 동시에 Unstaged 상태로 나온다. 어떻게 이런 일이 가능할까? `git add` 명령을 실행하면 Git은 파일을 바로 Staged 상태로 만든다. 지금 이 시점에서 커밋을 하면 `git commit` 명령을 실행하는 시점의 버전이 커밋되는 것이 아니라 마지막으로 `git add` 명령을 실행했을 때의 버전이 커밋된다. 그러니까 `git add` 명령을 실행한 후에 또 파일을 수정하면 `git add` 명령을 다시 실행해서 최신 버전을 Staged 상태로 만들어야 한다:
142
+
143
+ $ git add benchmarks.rb
144
+ $ git status
145
+ On branch master
146
+ Changes to be committed:
147
+ (use "git reset HEAD <file>..." to unstage)
148
+
149
+ new file: README
150
+ modified: benchmarks.rb
151
+
152
+
153
+ ### 파일 무시하기 ###
154
+
155
+ 어떤 파일은 Git이 자동으로 추가하거나 Untracked 파일이라고 보여줄 필요가 없다. 보통 로그 파일이나 빌드 시스템이 자동으로 생성한 파일이 그렇다. 그런 파일을 무시하려면 `.gitignore` 파일을 만들고 그 안에 무시할 파일 패턴을 적는다. 아래는 `.gitignore` 파일의 예이다:
156
+
157
+ $ cat .gitignore
158
+ *.[oa]
159
+ *~
160
+
161
+ 첫번째 줄은 확장자가 `.o` 나 `.a`인 파일을 Git이 무시하라는 것이고 둘째 줄은 `~`로 끝나는 모든 파일을 무시하라는 것이다. `.o`와 `.a`는 각각 빌드 시스템이 만들어내는 오브젝트와 아카이브 파일이고 `~`로 끝나는 파일은 Emacs나 VI 같은 텍스트 편집기가 임시로 만들어내는 파일이다. 또 log, tmp, pid 같은 디렉토리나, 자동으로 생성하는 문서 같은 것들도 추가할 수 있다. `.gitignore` 파일은 보통 처음에 만들어 두는 것이 편리하다. 그래서 Git 저장소에 커밋하고 싶지 않은 파일을 실수로 커밋하는 일을 방지할 수 있다.
162
+
163
+ .gitignore 파일에 입력하는 패턴은 아래 규칙을 따른다:
164
+
165
+ * 아무것도 없는 줄이나, `#`로 시작하는 줄은 무시한다.
166
+ * 표준 Glob 패턴을 사용한다.
167
+ * 디렉토리는 슬래시(`/`)를 끝에 사용하는 것으로 표현한다.
168
+ * 느낌표(`!`)로 시작하는 패턴의 파일은 무시하지 않는다.
169
+
170
+ Glob 패턴은 정규표현식을 단순하게 만든 것으로 생각하면 되고 보통 쉘에서 많이 사용한다. 애스터리스크(`*`)는 문자가 하나도 없거나 하나 이상을 의미하고, `[abc]`는 중괄호 안에 있는 문자 중 하나를 의미한다(그러니까 이 경우에는 a, b, c). 물음표(`?`)는 문자 하나를 말하고, `[0-9]`처럼 중괄호 안의 캐릭터 사이에 하이픈(`-`)을 사용하면 그 캐릭터 사이에 있는 문자 하나를 말한다.
171
+
172
+ 다음은 .gitignore 파일의 예이다:
173
+
174
+ # a comment - 이 줄은 무시한다.
175
+ # 확장자가 .a인 파일 무시
176
+ *.a
177
+ # 윗 줄에서 확장자가 .a인 파일은 무시하게 했지만 lib.a는 무시하지 않는다.
178
+ !lib.a
179
+ # 루트 디렉토리에 있는 TODO파일은 무시하고 subdir/TODO처럼 하위디렉토리에 있는 파일은 무시하지 않는다.
180
+ /TODO
181
+ # build/ 디렉토리에 있는 모든 파일은 무시한다.
182
+ build/
183
+ # `doc/notes.txt`같은 파일은 무시하고 doc/server/arch.txt같은 파일은 무시하지 않는다.
184
+ doc/*.txt
185
+ # `doc` 디렉토리 아래의 모든 .txt 파일을 무시한다.
186
+ doc/**/*.txt
187
+
188
+ `**/` 스타일의 문법은 Git 1.8.2 버전부터 사용할 수 있다.
189
+
190
+ ### Staged와 Unstaged 상태의 변경 내용을 보기 ###
191
+
192
+ 단순히 파일이 변경됐다는 사실이 아니라 어떤 내용이 변경됐는지 살펴보기엔 `git status` 명령이 아니라 `git diff` 명령을 사용해야 한다. 보통우리는 '수정했지만, 아직 Staged 파일이 아닌것?'과 '어떤 파일이 Staged 상태인지?'가 궁금하기 때문에 `git status` 명령으로도 충분하다. `git diff`는 Patch처럼 어떤 라인을 추가했고 삭제했는지가 궁금할 때에 사용한다. `git diff`는 나중에 더 자세히 다룬다.
193
+
194
+ README 파일을 수정해서 Staged 상태로 만들고 benchmarks.rb 파일은 그냥 수정만 해둔다. 이 상태에서 `git status` 명령을 실행하면 아래와 같은 메시지를 볼 수 있다:
195
+
196
+ $ git status
197
+ On branch master
198
+ Changes to be committed:
199
+ (use "git reset HEAD <file>..." to unstage)
200
+
201
+ new file: README
202
+
203
+ Changes not staged for commit:
204
+ (use "git add <file>..." to update what will be committed)
205
+ (use "git checkout -- <file>..." to discard changes in working directory)
206
+
207
+ modified: benchmarks.rb
208
+
209
+
210
+ `git diff` 명령을 실행하면 수정했지만 아직 staged 상태가 아닌 파일을 비교해 볼 수 있다:
211
+
212
+ $ git diff
213
+ diff --git a/benchmarks.rb b/benchmarks.rb
214
+ index 3cb747f..da65585 100644
215
+ --- a/benchmarks.rb
216
+ +++ b/benchmarks.rb
217
+ @@ -36,6 +36,10 @@ def main
218
+ @commit.parents[0].parents[0].parents[0]
219
+ end
220
+
221
+ + run_code(x, 'commits 1') do
222
+ + git.commits.size
223
+ + end
224
+ +
225
+ run_code(x, 'commits 2') do
226
+ log = git.commits('master', 15)
227
+ log.size
228
+
229
+ 이 명령은 워킹 디렉토리에 있는 것과 Staging Area에 있는 것을 비교한다. 그래서 수정하고 아직 Stage하지 않은 것을 보여준다.
230
+
231
+ 만약 커밋하려고 Staging Area에 넣은 파일의 변경 부분을 보고 싶으면 `git diff --cached` 옵션을 사용한다(Git 버전 1.6.1부터는 좀 더 기억하기 쉽게 `git diff --staged`로도 사용할 수 있다). 이 명령은 저장소에 커밋한 것과 Staging Area에 있는 것을 비교한다:
232
+
233
+ $ git diff --cached
234
+ diff --git a/README b/README
235
+ new file mode 100644
236
+ index 0000000..03902a1
237
+ --- /dev/null
238
+ +++ b/README2
239
+ @@ -0,0 +1,5 @@
240
+ +grit
241
+ + by Tom Preston-Werner, Chris Wanstrath
242
+ + http://github.com/mojombo/grit
243
+ +
244
+ +Grit is a Ruby library for extracting information from a Git repository
245
+
246
+ 꼭 잊지 말아야 할 것이 있는데 `git diff` 명령은 마지막으로 커밋한 후에 수정한 것들 전부를 보여주지 않는다. `git diff`는 Unstaged 상태인 것들만 보여준다. 이 부분이 조금 헷갈릴 수 있다. 수정한 파일을 모두 Staging Area에 넣었다면 `git diff` 명령은 아무것도 출력하지 않는다.
247
+
248
+ benchmarks.rb 파일을 Stage한 후에 다시 수정해도 `git diff` 명령을 사용할 수 있다. 이때는 Staged 상태인 것과 Unstaged 상태인 것을 비교한다:
249
+
250
+ $ git add benchmarks.rb
251
+ $ echo '# test line' >> benchmarks.rb
252
+ $ git status
253
+ On branch master
254
+ Changes to be committed:
255
+ (use "git reset HEAD <file>..." to unstage)
256
+
257
+ modified: benchmarks.rb
258
+
259
+ Changes not staged for commit:
260
+ (use "git add <file>..." to update what will be committed)
261
+ (use "git checkout -- <file>..." to discard changes in working directory)
262
+
263
+ modified: benchmarks.rb
264
+
265
+
266
+ `git diff` 명령으로 Unstaged 상태인 변경 부분을 확인해 볼 수 있다:
267
+
268
+ $ git diff
269
+ diff --git a/benchmarks.rb b/benchmarks.rb
270
+ index e445e28..86b2f7c 100644
271
+ --- a/benchmarks.rb
272
+ +++ b/benchmarks.rb
273
+ @@ -127,3 +127,4 @@ end
274
+ main()
275
+
276
+ ##pp Grit::GitRuby.cache_client.stats
277
+ +# test line
278
+
279
+ Staged 상태인 파일은 `git diff --cached` 옵션으로 확인한다:
280
+
281
+ $ git diff --cached
282
+ diff --git a/benchmarks.rb b/benchmarks.rb
283
+ index 3cb747f..e445e28 100644
284
+ --- a/benchmarks.rb
285
+ +++ b/benchmarks.rb
286
+ @@ -36,6 +36,10 @@ def main
287
+ @commit.parents[0].parents[0].parents[0]
288
+ end
289
+
290
+ + run_code(x, 'commits 1') do
291
+ + git.commits.size
292
+ + end
293
+ +
294
+ run_code(x, 'commits 2') do
295
+ log = git.commits('master', 15)
296
+ log.size
297
+
298
+ ### 변경사항 커밋하기 ###
299
+
300
+ 수정한 것을 커밋하기 위해 Staging Area에 파일을 정리했다. Unstaged 상태의 파일은 커밋되지 않는다는 것을 기억해야 한다. Git은 생성하거나 수정하고 나서 `git add` 명령으로 추가하지 않은 파일은 커밋하지 않는다. 그 파일은 여전히 Modified 상태로 남아 있다.
301
+ 커밋하기 전에 `git status` 명령으로 모든 것이 Staged 상태인지 확인할 수 있다. 그리고 `git commit`을 실행하여 커밋한다:
302
+
303
+ $ git commit
304
+
305
+ Git 설정에 지정된 편집기가 실행되고, 아래와 같은 텍스트가 자동으로 포함된다(아래 예제는 Vim 편집기의 화면이다). 이 편집기는 쉘의 $EDITOR 환경 변수에 등록된 편집기이고 보통은 Vim이나 Emacs을 사용한다. 또 *1장*에서 설명했듯이 `git config --global core.editor` 명령으로 어떤 편집기를 사용할지 설정할 수 있다:
306
+
307
+ 편집기는 아래와 같은 내용을 표시한다(아래 예제는 Vim 편집기):
308
+
309
+ # Please enter the commit message for your changes. Lines starting
310
+ # with '#' will be ignored, and an empty message aborts the commit.
311
+ # On branch master
312
+ # Changes to be committed:
313
+ # new file: README
314
+ # modified: benchmarks.rb
315
+ #
316
+ ~
317
+ ~
318
+ ~
319
+ ".git/COMMIT_EDITMSG" 10L, 283C
320
+
321
+ 자동으로 생성되는 커밋 메시지의 첫 줄은 비어 있고 둘째 줄부터 `git status` 명령의 결과가 채워진다. 커밋한 내용을 쉽게 기억할 수 있도록 이 메시지를 포함할 수도 있고 메시지를 전부 지우고 새로 작성할 수 있다(수정한 내용을 좀 더 구체적으로 남겨 둘 수 있다. `git commit`에 -v 옵션을 추가하면 편집기에 diff 메시지도 추가된다).
322
+
323
+ 메시지를 인라인으로 첨부할 수도 있다. `commit` 명령을 실행할 때 아래와 같이 `-m` 옵션을 사용한다:
324
+
325
+ $ git commit -m "Story 182: Fix benchmarks for speed"
326
+ [master 463dc4f] Story 182: Fix benchmarks for speed
327
+ 2 files changed, 3 insertions(+)
328
+ create mode 100644 README
329
+
330
+ `commit` 명령은 몇 가지 정보를 출력하는데 위 예제는 master 브랜치에 커밋했고 체크섬은 `463dc4f`이라고 알려준다. 그리고 수정한 파일이 몇 개이고 삭제됐거나 추가된 줄이 몇 줄인지 알려준다.
331
+
332
+ Git은 Staging Area에 속한 스냅샷을 커밋한다는 것을 기억해야 한다. 수정은 했지만, 아직 Staging Area에 넣지 않은 것은 다음에 커밋할 수 있다. 커밋할 때마다 프로젝트의 스냅샷을 기록하기 때문에 나중에 스냅샷끼리 비교하거나 예전 스냅샷으로 되돌릴 수 있다.
333
+
334
+ ### Staging Area 생략하기 ###
335
+
336
+ Staging Area는 커밋할 파일을 정리한다는 점에서 매우 유용하지만 복잡하기만 하고 필요하지 않은 때도 있다. 아주 쉽게 Staging Area를 생략할 수 있다. `git commit` 명령을 실행할 때 `-a` 옵션을 추가하면 Git은 Tracked 상태의 파일을 자동으로 Staging Area에 넣는다. 그래서 `git add` 명령을 실행하는 수고를 덜 수 있다:
337
+
338
+ $ git status
339
+ On branch master
340
+ Changes not staged for commit:
341
+ (use "git add <file>..." to update what will be committed)
342
+ (use "git checkout -- <file>..." to discard changes in working directory)
343
+
344
+ modified: benchmarks.rb
345
+
346
+ no changes added to commit (use "git add" and/or "git commit -a")
347
+ $ git commit -a -m 'added new benchmarks'
348
+ [master 83e38c7] added new benchmarks
349
+ 1 files changed, 5 insertions(+)
350
+
351
+ 이 예제에서는 커밋하기 전에 `git add` 명령으로 benchmarks.rb 파일을 추가하지 않았다는 점을 눈여겨보자.
352
+
353
+ ### 파일을 삭제하기 ###
354
+
355
+ Git에서 파일을 제거하려면 `git rm` 명령으로 Tracked 상태의 파일을 삭제한 후에(정확하게는 Staging Area에서 삭제하는 것) 커밋해야 한다. 이 명령은 워킹 디렉토리에 있는 파일도 삭제하기 때문에 실제로 지워진다.
356
+
357
+ 만약 Git없이 그냥 파일을 삭제하고 `git status` 명령으로 상태를 확인하면 `Changes not staged for commit`(즉, Unstaged) 에 속한다는 것을 확인할 수 있다:
358
+
359
+ $ rm grit.gemspec
360
+ $ git status
361
+ On branch master
362
+ Changes not staged for commit:
363
+ (use "git add/rm <file>..." to update what will be committed)
364
+ (use "git checkout -- <file>..." to discard changes in working directory)
365
+
366
+ deleted: grit.gemspec
367
+
368
+ no changes added to commit (use "git add" and/or "git commit -a")
369
+
370
+ 그리고 `git rm` 명령을 실행하면 삭제한 파일은 staged 상태가 된다:
371
+
372
+ $ git rm grit.gemspec
373
+ rm 'grit.gemspec'
374
+ $ git status
375
+ On branch master
376
+ Changes to be committed:
377
+ (use "git reset HEAD <file>..." to unstage)
378
+
379
+ deleted: grit.gemspec
380
+
381
+
382
+ 커밋하면 파일은 삭제되고 Git은 이 파일을 더는 추적하지 않는다. 이미 파일을 수정했거나 Index에(역주, Staging Area을 Git Index라고도 부른다) 추가했다면 `-f`옵션을 주어 강제로 삭제해야 한다. 이 점은 실수로 데이터를 삭제하지 못하도록 하는 안전장치다. 한 번도 커밋한적 없는 데이터는 Git으로 복구할 수 없다.
383
+
384
+ 또 Staging Area에서만 제거하고 워킹 디렉토리에 있는 파일은 지우지 않고 남겨둘 수 있다. 다시 말해서 하드디스크에 있는 파일은 그대로 두고 Git만 추적하지 않게 한다. 이것은 `.gitignore` 파일에 추가하는 것을 빼먹었거나 대용량 로그 파일이나 컴파일된 파일인 `.a` 파일 같은 것을 실수로 추가했을 때 쓴다. `--cached` 옵션을 사용하여 명령을 실행한다:
385
+
386
+ $ git rm --cached readme.txt
387
+
388
+ 여러 개의 파일이나 디렉토리를 한꺼번에 삭제할 수도 있다. 아래와 같이 `git rm` 명령에 file-glob 패턴을 사용한다:
389
+
390
+ $ git rm log/\*.log
391
+
392
+ `*`앞에 `\`을 사용한 것을 기억하자. 파일명 확장 기능은 쉘에만 있는 것이 아니라 Git 자체에도 있기 때문에 필요하다. Windows 기본 쉘을 쓸 때는 `\` 기호를 붙이지 않는다. 이 명령은 `log/` 디렉토리에 있는 `.log` 파일을 모두 삭제한다. 아래의 예제처럼 할 수도 있다:
393
+
394
+ $ git rm \*~
395
+
396
+ 이 명령은 `~`로 끝나는 파일을 모두 삭제한다.
397
+
398
+ ### 파일 이름 변경하기 ###
399
+
400
+ Git은 다른 VCS 시스템과는 달리 파일 이름의 변경이나 파일의 이동을 명시적으로 관리하지 않는다. 다시 말해서 파일 이름이 변경됐다는 별도의 정보를 저장하지 않는다. Git은 똑똑해서 굳이 파일 이름이 변경되었다는 것을 추적하지 않아도 아는 방법이 있다. 파일의 이름이 변경된 것을 Git이 어떻게 알아내는지 살펴보자.
401
+
402
+ 이렇게 말하고 Git에 `mv` 명령이 있는 게 좀 이상하겠지만, 아래와 같이 파일이름을 변경할 수 있다:
403
+
404
+ $ git mv file_from file_to
405
+
406
+ 잘 동작한다. 이 명령을 실행하고 Git의 상태를 확인해보면 Git은 이름이 바뀐 사실을 알고 있다:
407
+
408
+ $ git mv README.txt README
409
+ $ git status
410
+ On branch master
411
+ Changes to be committed:
412
+ (use "git reset HEAD <file>..." to unstage)
413
+
414
+ renamed: README.txt -> README
415
+
416
+
417
+ 사실 `git mv` 명령은 아래 명령어들을 수행한 것과 완전히 똑같다:
418
+
419
+ $ mv README.txt README
420
+ $ git rm README.txt
421
+ $ git add README
422
+
423
+ `git mv`는 일종의 단축 명령어이다. 이 명령으로 파일이름을 바꿔도 되고 `mv` 명령으로 파일이름을 직접 바꿔도 된다. 단지 Git의 `mv`명령은 편리하게 명령을 세 번 실행해주는 것뿐이다. 어떤 도구로 이름을 바꿔도 상관없다. 중요한 것은 이름을 변경하고 나서 꼭 rm/add 명령을 실행해야 한다는 것뿐이다.
424
+
425
+ ## 커밋 히스토리 조회하기 ##
426
+
427
+ 새로 저장소를 만들어서 몇 번 커밋을 했을 수도 있고, 커밋 히스토리가 있는 저장소를 Clone했을 수도 있다. 어쨌든 가끔 저장소의 히스토리를 보고 싶을 때가 있다. Git에는 히스토리를 조회하는 명령어인 `git log`가 있다.
428
+
429
+ 이 예제에서는 simplegit이라는 매우 단순한 프로젝트를 사용한다. simplegit은 Git을 설명하는데 자주 사용하는 예제다. 아래와 같이 이 프로젝트를 Clone한다:
430
+
431
+ git clone git://github.com/schacon/simplegit-progit.git
432
+
433
+ 이 프로젝트 디렉토리에서 `git log` 명령을 실행하면 아래와 같이 출력된다:
434
+
435
+ $ git log
436
+ commit ca82a6dff817ec66f44342007202690a93763949
437
+ Author: Scott Chacon <schacon@gee-mail.com>
438
+ Date: Mon Mar 17 21:52:11 2008 -0700
439
+
440
+ changed the version number
441
+
442
+ commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
443
+ Author: Scott Chacon <schacon@gee-mail.com>
444
+ Date: Sat Mar 15 16:40:33 2008 -0700
445
+
446
+ removed unnecessary test code
447
+
448
+ commit a11bef06a3f659402fe7563abf99ad00de2209e6
449
+ Author: Scott Chacon <schacon@gee-mail.com>
450
+ Date: Sat Mar 15 10:31:28 2008 -0700
451
+
452
+ first commit
453
+
454
+ 특별한 아규먼트 없이 `git log` 명령을 실행하면 저장소의 커밋 히스토리를 시간순으로 보여준다. 즉, 가장 최근의 커밋이 가장 먼저 나온다. 그리고 이어서 각 커밋의 SHA-1 체크섬, 저자 이름, 저자 이메일, 커밋한 날짜, 커밋 메시지를 보여준다.
455
+
456
+ 원하는 히스토리를 검색할 수 있도록 `git log` 명령은 매우 다양한 옵션을 지원한다. 여기에서는 자주 사용하는 옵션을 설명한다.
457
+
458
+ `-p`가 가장 유용한 옵션 중 하나다. `-p`는 각 커밋의 diff 결과를 보여준다. 게다가 `-2`는 최근 두 개의 결과만 보여주는 옵션이다:
459
+
460
+ $ git log -p -2
461
+ commit ca82a6dff817ec66f44342007202690a93763949
462
+ Author: Scott Chacon <schacon@gee-mail.com>
463
+ Date: Mon Mar 17 21:52:11 2008 -0700
464
+
465
+ changed the version number
466
+
467
+ diff --git a/Rakefile b/Rakefile
468
+ index a874b73..8f94139 100644
469
+ --- a/Rakefile
470
+ +++ b/Rakefile
471
+ @@ -5,7 +5,5 @@ require 'rake/gempackagetask'
472
+ spec = Gem::Specification.new do |s|
473
+ s.name = "simplegit"
474
+ - s.version = "0.1.0"
475
+ + s.version = "0.1.1"
476
+ s.author = "Scott Chacon"
477
+ s.email = "schacon@gee-mail.com"
478
+
479
+ commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
480
+ Author: Scott Chacon <schacon@gee-mail.com>
481
+ Date: Sat Mar 15 16:40:33 2008 -0700
482
+
483
+ removed unnecessary test code
484
+
485
+ diff --git a/lib/simplegit.rb b/lib/simplegit.rb
486
+ index a0a60ae..47c6340 100644
487
+ --- a/lib/simplegit.rb
488
+ +++ b/lib/simplegit.rb
489
+ @@ -18,8 +18,3 @@ class SimpleGit
490
+ end
491
+
492
+ end
493
+ -
494
+ -if $0 == __FILE__
495
+ - git = SimpleGit.new
496
+ - puts git.show
497
+ -end
498
+
499
+
500
+ 이 옵션은 직접 diff를 실행한 것과 같은 결과를 출력하기 때문에 동료가 무엇을 커밋했는지 리뷰하고 빨리 조회하는데 유용하다.
501
+
502
+ 가끔은 diff 결과를 줄 단위로 보기보다는 단어 단위로 보는 것이 좋을 때도 있다. `git log -p`와 같은 명령에 `--word-diff` 옵션을 사용하면 줄 단위 대신 단어 단위로 변경사항을 보여준다. 단어 단위로 다른 부분을 확인하는 것은 소스코드에는 별로 유용하지 않다. 책이나 에세이 같이 문장이 긴 글을 쓸 때는 단어 단위로 보는 것이 편하다. `--word-diff` 옵션은 다음과 같이 사용한다:
503
+
504
+ $ git log -U1 --word-diff
505
+ commit ca82a6dff817ec66f44342007202690a93763949
506
+ Author: Scott Chacon <schacon@gee-mail.com>
507
+ Date: Mon Mar 17 21:52:11 2008 -0700
508
+
509
+ changed the version number
510
+
511
+ diff --git a/Rakefile b/Rakefile
512
+ index a874b73..8f94139 100644
513
+ --- a/Rakefile
514
+ +++ b/Rakefile
515
+ @@ -7,3 +7,3 @@ spec = Gem::Specification.new do |s|
516
+ s.name = "simplegit"
517
+ s.version = [-"0.1.0"-]{+"0.1.1"+}
518
+ s.author = "Scott Chacon"
519
+
520
+ 위의 예제는 줄 단위로 보여주는 일반적인 diff와 좀 다르다. 줄 안에서 변경한 부분을 단어 단위로 표시한다. 추가한 단어는 `{+ +}` 기호가 둘러싸고 삭제한 단어는 `[- -]` 기호가 둘러싼다. diff는 기본적으로 다른 줄과 위아래 줄을 포함해서 3줄을 보여준다. 줄 단위가 아니라 단어 단위로 비교해서 볼 때는 굳이 3줄을 다 볼 필요가 없다. 예제에서 처럼 `-U1` 옵션을 주면 해당 줄만 보여준다.
521
+
522
+ 또 `git log` 명령에는 히스토리의 통계를 보여주는 옵션도 있다. `--stat` 옵션으로 각 커밋의 통계 정보를 조회할 수 있다:
523
+
524
+ $ git log --stat
525
+ commit ca82a6dff817ec66f44342007202690a93763949
526
+ Author: Scott Chacon <schacon@gee-mail.com>
527
+ Date: Mon Mar 17 21:52:11 2008 -0700
528
+
529
+ changed the version number
530
+
531
+ Rakefile | 2 +-
532
+ 1 file changed, 1 insertion(+), 1 deletion(-)
533
+
534
+ commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
535
+ Author: Scott Chacon <schacon@gee-mail.com>
536
+ Date: Sat Mar 15 16:40:33 2008 -0700
537
+
538
+ removed unnecessary test code
539
+
540
+ lib/simplegit.rb | 5 -----
541
+ 1 file changed, 5 deletions(-)
542
+
543
+ commit a11bef06a3f659402fe7563abf99ad00de2209e6
544
+ Author: Scott Chacon <schacon@gee-mail.com>
545
+ Date: Sat Mar 15 10:31:28 2008 -0700
546
+
547
+ first commit
548
+
549
+ README | 6 ++++++
550
+ Rakefile | 23 +++++++++++++++++++++++
551
+ lib/simplegit.rb | 25 +++++++++++++++++++++++++
552
+ 3 files changed, 54 insertions(+)
553
+
554
+ 이 결과에서 `--stat` 옵션은 어떤 파일이 수정됐는지, 얼마나 많은 파일이 변경됐는지, 또 얼마나 많은 줄을 추가하거나 삭제했는지 보여준다. 요약정보는 가장 뒤쪽에 보여준다.
555
+
556
+ 다른 또 유용한 옵션은 `--pretty` 옵션이다. 이 옵션을 통해 log의 내용을 보여줄 때 기본 형식 이외에 여러 가지 중에 하나를 선택할 수 있다. `oneline` 옵션은 각 커밋을 한 줄로 보여준다. 이 옵션은 많은 커밋을 한 번에 조회할 때 유용하다. 추가로 `short`, `full`, `fuller` 옵션도 있는데 이것은 정보를 조금씩 가감해서 보여준다:
557
+
558
+ $ git log --pretty=oneline
559
+ ca82a6dff817ec66f44342007202690a93763949 changed the version number
560
+ 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test code
561
+ a11bef06a3f659402fe7563abf99ad00de2209e6 first commit
562
+
563
+ 가장 재밌는 옵션은 `format` 옵션이다. 나만의 포맷으로 결과를 출력하고 싶을 때 사용한다. 특히 결과를 다른 프로그램으로 파싱하고자 할 때 유용하다. 이 옵션을 사용하면 포맷을 정확하게 일치시킬 수 있기 때문에 Git을 새 버전으로 바꿔도 결과 포맷이 바뀌지 않는다:
564
+
565
+ $ git log --pretty=format:"%h - %an, %ar : %s"
566
+ ca82a6d - Scott Chacon, 11 months ago : changed the version number
567
+ 085bb3b - Scott Chacon, 11 months ago : removed unnecessary test code
568
+ a11bef0 - Scott Chacon, 11 months ago : first commit
569
+
570
+ <!-- Attention to translators: this is a table declaration.
571
+ The lines must be formatted as follows
572
+ <TAB><First column text><TAB><Second column text>
573
+ -->
574
+
575
+ 표 2-1 형식에서 사용하는 유용한 옵션들.
576
+
577
+ Option Description of Output
578
+ %H Commit hash
579
+ %h Abbreviated commit hash
580
+ %T Tree hash
581
+ %t Abbreviated tree hash
582
+ %P Parent hashes
583
+ %p Abbreviated parent hashes
584
+ %an Author name
585
+ %ae Author e-mail
586
+ %ad Author date (format respects the --date= option)
587
+ %ar Author date, relative
588
+ %cn Committer name
589
+ %ce Committer email
590
+ %cd Committer date
591
+ %cr Committer date, relative
592
+ %s Subject
593
+
594
+ _저자(Author)_ 와 _커미터(Committer)_ 를 구분하는 것이 조금 이상해 보일 수 있다. 저자는 원래 작업을 수행한 원작자이고 커밋터는 마지막으로 이 작업을 적용한 사람이다. 만약 당신이 어떤 프로젝트에 패치를 보냈고 그 프로젝트의 담당자가 패치를 적용했다면 두 명의 정보를 모두 알 필요가 있다. 그래서 이 경우 당신이 저자고 그 담당자가 커미터다. *5장*에서 이 주제에 대해 자세히 다룰 것이다.
595
+
596
+ `oneline`과 `format` 옵션은 `--graph` 옵션과 함께 사용할 때 더 빛난다. 이 명령은 브랜치와 머지 히스토리를 보여주는 아스키 그래프를 출력한다. 이 명령을 Grit 프로젝트 저장소에서 사용해보면 아래와 같다:
597
+
598
+ $ git log --pretty=format:"%h %s" --graph
599
+ * 2d3acf9 ignore errors from SIGCHLD on trap
600
+ * 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
601
+ |\
602
+ | * 420eac9 Added a method for getting the current branch.
603
+ * | 30e367c timeout code and tests
604
+ * | 5a09431 add timeout protection to grit
605
+ * | e1193f8 support for heads with slashes in them
606
+ |/
607
+ * d6016bc require time for xmlschema
608
+ * 11d191e Merge branch 'defunkt' into local
609
+
610
+ `git log` 명령의 기본적인 옵션과 출력물의 형식에 관련된 옵션을 살펴보았다. `git log` 명령은 앞서 살펴본 것보다 더 많은 옵션을 지원한다. 표 2-2 는 지금 설명한 것과 함께 유용하게 사용할 수 있는 옵션이다. 각 옵션으로 어떻게 `log` 명령을 제어할 수 있는지 보여준다.
611
+
612
+ <!-- Attention to translators: this is a table declaration.
613
+ The lines must be formatted as follows
614
+ <TAB><First column text><TAB><Second column text>
615
+ -->
616
+
617
+ 옵션 설명
618
+ -p 각 커밋에 적용된 패치를 보여준다.
619
+ --word-diff diff 결과를 단어 단위로 보여준다.
620
+ --stat 각 커밋에서 수정된 파일의 통계정보를 보여준다.
621
+ --shortstat `--stat` 명령의 결과 중에서 수정한 파일, 추가된 줄, 삭제된 줄만 보여준다.
622
+ --name-only 커밋 정보중에서 수정된 파일의 목록만 보여준다.
623
+ --name-status 수정된 파일의 목록을 보여줄 뿐만 아니라 파일을 추가한 것인지, 수정한 것인지, 삭제한 것인지도 보여준다.
624
+ --abbrev-commit 40자 짜리 SHA-1 체크섬을 전부 보여주는 것이 아니라 처음 몇 자만 보여준다.
625
+ --relative-date 정확한 시간을 보여주는 것이 아니라 `2 주전`처럼 상대적인 형식으로 보여준다.
626
+ --graph 브랜치와 머지 히스토리 정보까지 아스키 그래프로 보여준다.
627
+ --pretty 지정한 형식으로 보여준다. 이 옵션에는 oneline, short, full, fuller, format이 있다. format은 원하는 형식으로 출력하고자 할 때 사용한다.
628
+ --oneline `--pretty=oneline --abbrev-commit` 옵션을 함께 사용한 것과 동일하다.
629
+
630
+ ### 조회 제한조건 ###
631
+
632
+ 출력 형식과 관련된 옵션을 살펴봤지만 `git log` 명령은 조회 범위를 제한하는 옵션들도 있다. 히스토리 전부가 아니라 부분만 조회한다. 이미 최근 두 개만 조회하는 `-2` 옵션은 살펴봤다. 실제 사용법은 `-<n>`이고 n은 최근 n개의 커밋을 의미한다. 사실 이 옵션은 잘 쓰이지 않는다. Git은 기본적으로 출력을 pager류의 프로그램을 거쳐서 내보내므로 한 번에 한 페이지씩 보여준다.
633
+
634
+ 반면 `--since`나 `--until`같은 시간을 기준으로 조회하는 옵션은 매우 유용하다. 지난 2주 동안 만들어진 커밋들만 조회하는 명령은 아래와 같다:
635
+
636
+ $ git log --since=2.weeks
637
+
638
+ 이 옵션은 다양한 형식을 지원한다. `2008-01-15`같이 정확한 날짜도 사용할 수 있고 `2 years 1 day 3 minutes ago`같이 상대적인 기간을 사용할 수도 있다.
639
+
640
+ 또 다른 기준도 있다. `--author` 옵션으로 저자를 지정하여 검색할 수도 있고 `--grep` 옵션으로 커밋 메시지에서 키워드를 검색할 수도 있다(author와 grep 옵션을 함께 사용하면 모두 만족하는 커밋을 찾는다).
641
+
642
+ grep 옵션을 여러개 사용하면 그중 하나이상 만족하는 커밋을 찾는다. 모두 만족하는 커밋을 찾으려면 `--all-match` 옵션을 추가해야 한다.
643
+
644
+ 마지막으로 파일 경로로 검색하는 옵션이 있는데 이것도 정말 유용하다. 디렉토리나 파일 이름을 사용하여 그 파일이 변경된 log의 결과를 검색할 수 있다. 이 옵션은 `--`와 함께 경로 이름을 사용하는데 명령어 끝 부분에 쓴다(역주, `git log -- path1 path2`).
645
+
646
+ 표 2-3은 조회 범위를 제한하는 옵션들이다.
647
+
648
+ <!-- Attention to translators: this is a table declaration.
649
+ The lines must be formatted as follows
650
+ <TAB><First column text><TAB><Second column text>
651
+ -->
652
+
653
+ 옵션 설명
654
+ -(n) 최근 n 개의 커밋만 조회한다.
655
+ --since, --after 명시한 날짜 이후의 커밋만 검색한다.
656
+ --until, --before 명시한 날짜 이전의 커밋만 조회한다.
657
+ --author 입력한 저자의 커밋만 보여준다.
658
+ --committer 입력한 커미터의 커밋만 보여준다.
659
+
660
+ 아래 예제는 2008년 10월에 Junio Hamano가 커밋한 히스토리를 조회하는 것이다. 그 중에서 테스트 파일을 수정한 커밋 중에서 머지 커밋이 아닌 것들만 조회한다:
661
+
662
+ $ git log --pretty="%h - %s" --author=gitster --since="2008-10-01" \
663
+ --before="2008-11-01" --no-merges -- t/
664
+ 5610e3b - Fix testcase failure when extended attribute
665
+ acd3b9e - Enhance hold_lock_file_for_{update,append}()
666
+ f563754 - demonstrate breakage of detached checkout wi
667
+ d1a43f2 - reset --hard/read-tree --reset -u: remove un
668
+ 51a94af - Fix "checkout --track -b newbranch" on detac
669
+ b0ad11e - pull: allow "git pull origin $something:$cur
670
+
671
+ 총 2만여 개의 커밋 히스토리에서 이 명령의 검색 조건에 만족하는 것은 단 6개였다.
672
+
673
+ ### GUI 도구로 히스토리를 시각화하기 ###
674
+
675
+ GUI 도구로 커밋 히스토리를 시각화하고 싶다면 gitk를 사용할 수 있다. gitk는 Tcl/Tk 프로그램이고 `git log` 명령을 시각화해주는 도구다. gitk는 `git log` 명령이 지원하는 필터링 옵션을 거의 모두 지원한다. 프로젝트 디렉토리에서 gitk를 실행하면 그림 2-2처럼 보일 것이다.
676
+
677
+ Insert 18333fig0202.png
678
+ 그림 2-2. gitk의 히스토리
679
+
680
+ 위쪽 반을 차지하는 윈도에서는 히스토리를 그래프로 예쁘게 보여준다. 아래쪽 반을 차지하는 윈도는 diff 결과를 보여주는데 위쪽 윈도에서 선택한 커밋에 대한 diff 결과를 보여준다.
681
+
682
+ ## 되돌리기 ##
683
+
684
+ 일을 하다보면 모든 단계에서 어떤 것은 되돌리고(Undo) 싶을 때가 있다. 이번에는 우리가 한 일을 되돌리는 방법을 살펴볼 것이다. 한 번 되돌리면 복구할 수 없어서 주의해야 한다. Git을 사용하면 우리가 한 실수를 복구하지 못할 것은 거의 없지만 되돌리기는 복구할 수 없다.
685
+
686
+ ### 커밋 수정하기 ###
687
+
688
+ 종종 완료한 커밋을 수정해야 할 때가 있다. 너무 일찍 커밋했거나 어떤 파일을 빼먹었을 때 그리고 커밋 메시지를 잘못 적었을 때 하게 된다. 다시 커밋하고 싶으면 `--amend` 옵션을 사용한다:
689
+
690
+ $ git commit --amend
691
+
692
+ 이 명령은 Staging Area를 사용하여 커밋한다. 만약 마지막으로 커밋하고 나서 수정한 것이 없다면(커밋하자마자 바로 이 명령을 실행하는 경우) 조금 전에 한 커밋과 모든 것이 같다. 이때는 커밋 메시지만 수정한다.
693
+
694
+ 편집기가 실행되면 이전 커밋 메시지가 자동으로 포함된다. 메시지를 수정하지 않고 그대로 커밋해도 기존의 커밋을 덮어쓴다.
695
+
696
+ 커밋을 했는데 Stage하는 것을 깜빡하고 빠트린 파일이 있으면 아래와 같이 고칠 수 있다:
697
+
698
+ $ git commit -m 'initial commit'
699
+ $ git add forgotten_file
700
+ $ git commit --amend
701
+
702
+ 여기서 실행한 명령어 3개는 모두 하나의 커밋으로 기록된다. 두 번째 커밋은 첫 번째 커밋을 덮어쓴다.
703
+
704
+ ### 파일 상태를 Unstage로 변경하기 ###
705
+
706
+ 다음은 Staging Area와 워킹 디렉토리 사이를 넘나드는 방법을 설명한다. 두 영역의 상태를 확인할 때마다 변경된 상태를 되돌리는 방법을 알려주기 때문에 매우 편리하다. 예를 들어 파일을 두 개 수정하고서 따로따로 커밋하려고 했지만, 실수로 `git add *` 라고 실행해 버렸다. 두 파일 모두 Staging Area에 들어 있다. 이제 둘 중 하나를 어떻게 꺼낼까? 우선 `git status` 명령으로 확인해보자:
707
+
708
+ $ git add .
709
+ $ git status
710
+ On branch master
711
+ Changes to be committed:
712
+ (use "git reset HEAD <file>..." to unstage)
713
+
714
+ modified: README.txt
715
+ modified: benchmarks.rb
716
+
717
+
718
+ `Changes to be commited` 밑에 `git reset HEAD <file>...`이라는 문장을 볼 수 있다. 이 명령으로 Unstage 상태로 변경할 수 있다. benchmarks.rb 파일을 Unstage 상태로 변경해보자:
719
+
720
+ $ git reset HEAD benchmarks.rb
721
+ Unstaged changes after reset:
722
+ M benchmarks.rb
723
+ $ git status
724
+ On branch master
725
+ Changes to be committed:
726
+ (use "git reset HEAD <file>..." to unstage)
727
+
728
+ modified: README.txt
729
+
730
+ Changes not staged for commit:
731
+ (use "git add <file>..." to update what will be committed)
732
+ (use "git checkout -- <file>..." to discard changes in working directory)
733
+
734
+ modified: benchmarks.rb
735
+
736
+
737
+ 명령어가 낮설게 느껴질 수도 있지만 잘 동작한다. benchmarks.rb 파일은 Unstage 상태가 됐다.
738
+
739
+ ### Modified 파일 되돌리기 ###
740
+
741
+ 어떻게 해야 benchmarks.rb 파일을 수정하고 나서 다시 되돌릴 수 있을까? 그러니까 최근 커밋된 버전으로(아니면 처음 Clone했을 때처럼 워킹 디렉토리에 처음 Checkout 한 그 내용으로) 되돌리는 방법이 무얼까? `git status` 명령이 친절하게 알려준다. 바로 위에 있는 예제에서 Unstaged 부분을 보자:
742
+
743
+ Changes not staged for commit:
744
+ (use "git add <file>..." to update what will be committed)
745
+ (use "git checkout -- <file>..." to discard changes in working directory)
746
+
747
+ modified: benchmarks.rb
748
+
749
+
750
+ 위의 메시지는 수정한 파일을 되돌리는 방법을 꽤 정확하게 알려준다(적어도 Git 1.6.1이후 버전부터는 그렇다. 만약 예전 것을 아직 사용하고 있으면 업그레드하는 것이 좋다. 편의성이 많이 개선됐다). 알려주는 대로 한 번 해보자:
751
+
752
+ $ git checkout -- benchmarks.rb
753
+ $ git status
754
+ On branch master
755
+ Changes to be committed:
756
+ (use "git reset HEAD <file>..." to unstage)
757
+
758
+ modified: README.txt
759
+
760
+
761
+ 정상적으로 복원된 것을 알 수 있다. 하지만 이 명령은 꽤 위험한 명령이라는 것을 알아야 한다. 수정 이전의 파일로 덮어썼기 때문에 수정했던 내용은 전부 사라진다. 수정한 내용이 진짜 마음에 들지 않을 때에만 사용하자. 정말 이렇게 삭제해야 한다면 Stash와 Branch를 사용하자. 다음 장에서 다루는 이 방법들이 훨씬 낫다.
762
+
763
+ Git으로 커밋한 모든 것은 언제나 복구할 수 있다. 삭제한 브랜치에 있었던 것도 `--amend` 옵션으로 다시 커밋한 것도 복구할 수 있다(자세한 것은 *9장*에서 다룬다). 하지만, 커밋하지 않고 잃어버린 것은 절대로 되돌릴 수 없다.
764
+
765
+ ## 리모트 저장소 ##
766
+
767
+ 리모트 저장소를 관리할 줄 알아야 다른 사람과 함께 일할 수 있다. 리모트 저장소는 인터넷이나 네트워크 어딘가에 있는 저장소를 말한다. 저장소는 여러 개가 있을 수 있는데 어떤 저장소는 읽고 쓰기 모두 할 수 있고 어떤 저장소는 읽기 권한만 있을 수도 있다. 간단히 말해서 다른 사람들과 함께 일한다는 것은 리모트 저장소를 관리하면서 데이터를 거기에 Push하고 Pull하는 것이다. 리모트 저장소를 관리한다는 것은 저장소를 추가, 삭제하는 것뿐만 아니라 브랜치를 관리하고 추적할지 말지 등을 관리하는 것을 말한다. 이번에는 리모트 저장소를 관리하는 방법에 대해 설명한다.
768
+
769
+ ### 리모트 저장소 확인하기 ###
770
+
771
+ `git remote` 명령으로 현재 프로젝트에 등록된 리모트 저장소를 확인할 수 있다. 이 명령은 리모트 저장소의 단축 이름을 보여준다. 저장소를 Clone하면 origin이라는 리모트 저장소가 자동으로 등록되기 때문에 origin이라는 이름을 볼 수 있다:
772
+
773
+ $ git clone git://github.com/schacon/ticgit.git
774
+ Cloning into 'ticgit'...
775
+ remote: Reusing existing pack: 1857, done.
776
+ remote: Total 1857 (delta 0), reused 0 (delta 0)
777
+ Receiving objects: 100% (1857/1857), 374.35 KiB | 193.00 KiB/s, done.
778
+ Resolving deltas: 100% (772/772), done.
779
+ Checking connectivity... done.
780
+ $ cd ticgit
781
+ $ git remote
782
+ origin
783
+
784
+ `-v`옵션을 주어 단축이름과 URL을 함께 볼 수 있다:
785
+
786
+ $ git remote -v
787
+ origin git://github.com/schacon/ticgit.git (fetch)
788
+ origin git://github.com/schacon/ticgit.git (push)
789
+
790
+ 리모트 저장소가 여러 개 있다면 이 명령은 전부 보여준다. 내 Grit 저장소에서 실행하면 아래와 같이 출력한다:
791
+
792
+ $ cd grit
793
+ $ git remote -v
794
+ bakkdoor git://github.com/bakkdoor/grit.git
795
+ cho45 git://github.com/cho45/grit.git
796
+ defunkt git://github.com/defunkt/grit.git
797
+ koke git://github.com/koke/grit.git
798
+ origin git@github.com:mojombo/grit.git
799
+
800
+ 이렇게 리모트 저장소가 여러 개가 등록되어 있으면 다른 사람이 기여한 내용(Contributions)을 쉽게 가져올 수 있다. 그리고 origin만 SSH URL이기 때문에 origin에만 Push할 수 있다(*4장*에서 좀 더 자세히 다룬다).
801
+
802
+ ### 리모트 저장소 추가하기 ###
803
+
804
+ 이전 절에서도 리모트 저장소를 추가하는 것에 대해 설명했었지만 수박 겉핥기식으로 살펴봤을 뿐이었다. 여기에서는 리모트 저장소를 추가하는 방법을 자세하게 설명한다. 쉽게 새 리모트 저장소를 추가할 수 있는데 `git remote add [단축이름] [url]` 명령을 실행한다:
805
+
806
+ $ git remote
807
+ origin
808
+ $ git remote add pb git://github.com/paulboone/ticgit.git
809
+ $ git remote -v
810
+ origin git://github.com/schacon/ticgit.git
811
+ pb git://github.com/paulboone/ticgit.git
812
+
813
+ 이제 URL 대신에 스트링 `pb`를 사용할 수 있다. 예를 들어 로컬 저장소에는 없지만 Paul의 저장소에 있는 것을 가져오려면 아래과 같이 실행한다:
814
+
815
+ $ git fetch pb
816
+ remote: Counting objects: 58, done.
817
+ remote: Compressing objects: 100% (41/41), done.
818
+ remote: Total 44 (delta 24), reused 1 (delta 0)
819
+ Unpacking objects: 100% (44/44), done.
820
+ From git://github.com/paulboone/ticgit
821
+ * [new branch] master -> pb/master
822
+ * [new branch] ticgit -> pb/ticgit
823
+
824
+ 로컬에서 `pb/master`가 Paul의 master 브랜치이다. 이것을 로컬 브랜치중 하나에 머지하거나 체크아웃하여 브랜치 내용을 자세히 확인할 수 있다.
825
+
826
+ ### 리모트 저장소를 Pull 하거나 Fetch 하기 ###
827
+
828
+ 앞서 설명했듯이 리모트 저장소에서 데이터를 가져오려면 간단히 아래와 같이 실행한다:
829
+
830
+ $ git fetch [remote-name]
831
+
832
+ 이 명령은 로컬에는 없지만, 리모트 저장소에는 있는 데이터를 모두 가져온다. 그리고 나면 리모트 저장소의 모든 브랜치를 로컬에서 접근할 수 있어서 언제든지 머지를 하거나 내용을 살펴볼 수 있다(우리는 *3장*에서 브랜치를 사용하는 방법에 대해 좀 더 자세히 설명할 것이다).
833
+
834
+ 저장소를 Clone하면 명령은 자동으로 리모트 저장소를 origin이라는 이름으로 추가한다. 그래서 나중에 `git fetch origin`을 실행하면 Clone한 이후에(혹은 마지막으로 가져온 이후에) 수정된 것을 모두 가져온다. `fetch` 명령은 리모트 저장소의 데이터를 모두 로컬로 가져오지만, 자동으로 머지하지 않는다. 그래서 당신이 로컬에서 하던 작업을 정리하고 나서 수동으로 머지해야 한다.
835
+
836
+ 그냥 쉽게 `git pull` 명령으로 리모트 저장소 브랜치에서 데이터를 가져올 뿐만 아니라 자동으로 로컬 브랜치와 머지시킬 수 있다. 먼저 `git clone` 명령은 자동으로 로컬의 master 브랜치가 리모트 저장소의 master 브랜치를 추적하도록 한다(물론 리모트 저장소에 master 브랜치가 있다고 가정에서). 그리고 `git pull` 명령은 Clone한 서버에서 데이터를 가져오고 그 데이터를 자동으로 현재 작업하는 코드와 머지시킨다.
837
+
838
+ ### 리모트 저장소에 Push하기 ###
839
+
840
+ 프로젝트를 공유하고 싶을 때 리모트 저장소에 Push할 수 있다. 이 명령은 `git push [리모트 저장소 이름] [브랜치 이름]`으로 단순하다. master 브랜치를 `origin` 서버에 Push하려면(다시 말하지만 Clone하면 보통 자동으로 origin 이름이 생성된다) 아래와 같이 서버에 Push한다:
841
+
842
+ $ git push origin master
843
+
844
+ 이 명령은 Clone한 리모트 저장소에 쓰기 권한이 있고, Clone하고 난 이후 아무도 리모트 저장소에 Push하지 않았을 때만 사용할 수 있다. 다시 말해서 Clone한 사람이 여러 명 있을 때, 다른 사람이 Push한 후에 Push하려고 하면 Push할 수 없다. 먼저 다른 사람이 작업한 것을 가져와서 머지한 후에 Push할 수 있다. *3장*에서 서버에 Push하는 방법에 대해 자세히 설명할 것이다.
845
+
846
+ ### 리모트 저장소 살펴보기 ###
847
+
848
+ (역주, 이 절은 최신 버전의 Git이 출력하는 메시지와 조금 다르다.)
849
+
850
+ `git remote show [리모트 저장소 이름]` 명령으로 리모트 저장소의 구체적인 정보를 확인할 수 있다. `origin` 같은 단축이름으로 이 명령을 실행하면 아래와 같은 정보를 볼 수 있다:
851
+
852
+ $ git remote show origin
853
+ * remote origin
854
+ URL: git://github.com/schacon/ticgit.git
855
+ Remote branch merged with 'git pull' while on branch master
856
+ master
857
+ Tracked remote branches
858
+ master
859
+ ticgit
860
+
861
+ 리모트 저장소의 URL과 추적하는 브랜치를 출력한다. 이 명령은 `git pull` 명령을 실행할 때 master 브랜치와 머지할 브랜치가 무엇인지 보여 준다. `git pull` 명령은 리모트 저장소 브랜치의 데이터를 모두 가져오고 나서 자동으로 머지할 것이다. 그리고 가져온 모든 리모트 저장소 정보도 출력한다.
862
+
863
+ 좀 더 Git을 열심히 사용하게 되면 `git remote show` 명령은 더 많은 정보를 보여줄 것이다. 여러분도 언젠가는 아래와 같은 메시지(역주, 다수의 브랜치를 사용하는 메시지)를 볼 날이 올 것이다.
864
+
865
+ $ git remote show origin
866
+ * remote origin
867
+ URL: git@github.com:defunkt/github.git
868
+ Remote branch merged with 'git pull' while on branch issues
869
+ issues
870
+ Remote branch merged with 'git pull' while on branch master
871
+ master
872
+ New remote branches (next fetch will store in remotes/origin)
873
+ caching
874
+ Stale tracking branches (use 'git remote prune')
875
+ libwalker
876
+ walker2
877
+ Tracked remote branches
878
+ acl
879
+ apiv2
880
+ dashboard2
881
+ issues
882
+ master
883
+ postgres
884
+ Local branch pushed with 'git push'
885
+ master:master
886
+
887
+ 브랜치명을 생략하고 `git push` 명령을 실행할 때 어떤 브랜치가 어떤 브랜치로 Push되는지 보여준다. 또 아직 로컬로 가져오지 않은 리모트 저장소의 브랜치는 어떤 것들이 있는지, 서버에서는 삭제됐지만 아직 가지고 있는 브랜치는 어떤 것인지, `git pull` 명령을 실행했을 때 자동으로 머지할 브랜치는 어떤 것이 있는지 보여준다.
888
+
889
+ ### 리모트 저장소 이름을 바꾸거나 리모트 저장소를 삭제하기 ###
890
+
891
+ `git remote rename` 명령으로 리모트 저장소의 이름을 변경할 수 있다. 예를 들어 `pb`를 `paul`로 변경하려면 `git remote rename` 명령을 사용한다:
892
+
893
+ $ git remote rename pb paul
894
+ $ git remote
895
+ origin
896
+ paul
897
+
898
+ 리모트 저장소의 브랜치 이름도 바뀐다. 여태까지 `pb/master`로 리모트 저장소 브랜치를 사용했으면 이제는 `paul/master`라고 사용해야 한다.
899
+
900
+ 리모트 저장소를 삭제해야 한다면 `git remote rm` 명령을 사용한다. 서버 정보가 바뀌었을 때, 더는 별도의 미러가 필요하지 않을 때, 더는 기여자가 활동하지 않을 때 필요하다:
901
+
902
+ $ git remote rm paul
903
+ $ git remote
904
+ origin
905
+
906
+ ## 태그 ##
907
+
908
+ 다른 VCS처럼 Git도 태그를 지원한다. 사람들은 보통 릴리즈할 때 사용한다(v1.0, 등등). 이번에는 태그를 조회하고 생성하는 법과 태그의 종류를 설명한다.
909
+
910
+ ### 태그 조회하기 ###
911
+
912
+ 우선 `git tag` 명령으로 이미 만들어진 태그가 있는지 확인할 수 있다:
913
+
914
+ $ git tag
915
+ v0.1
916
+ v1.3
917
+
918
+ 이 명령은 알파벳 순서로 태그를 보여준다. 사실 순서는 별로 중요한 게 아니다.
919
+
920
+ 검색 패턴을 사용하여 태그를 검색할 수 있다. Git 소스 저장소는 240여 개의 태그가 있다. 만약 1.4.2 버전의 태그들만 검색하고 싶으면 아래와 같이 실행한다:
921
+
922
+ $ git tag -l 'v1.4.2.*'
923
+ v1.4.2.1
924
+ v1.4.2.2
925
+ v1.4.2.3
926
+ v1.4.2.4
927
+
928
+ ### 태그 붙이기 ###
929
+
930
+ Git의 태그는 Lightweight 태그와 Annotated 태그로 두 종류가 있다. Lightweight 태그는 브랜치와 비슷한데 브랜치처럼 가리키는 지점을 최신 커밋으로 이동시키지 않는다. 단순히 특정 커밋에 대한 포인터일 뿐이다. 한편, Annotated 태그는 Git 데이터베이스에 태그를 만든 사람의 이름, 이메일과 태그를 만든 날짜, 그리고 태그 메시지도 저장한다. 또 GPG(GNU Privacy Guard)로 서명할 수도 있다. 이 모든 정보를 저장해둬야 할 때에만 Annotated 태그를 추천한다. 그냥 다른 정보를 저장하지 않는 단순한 태그가 필요하다면 Lightweight 태그를 사용하는 것이 좋다.
931
+
932
+ ### Annotated 태그 ###
933
+
934
+ Annotated 태그를 만드는 방법은 간단하다. `tag` 명령을 실행할 때 `-a` 옵션을 추가한다:
935
+
936
+ $ git tag -a v1.4 -m 'my version 1.4'
937
+ $ git tag
938
+ v0.1
939
+ v1.3
940
+ v1.4
941
+
942
+ `-m` 옵션으로 태그를 저장할 때 메시지를 함께 저장할 수 있다. 명령을 실행할 때 메시지를 입력하지 않으면 Git은 편집기를 실행시킨다.
943
+
944
+ `git show` 명령으로 태그 정보와 커밋 정보를 모두 확인할 수 있다:
945
+
946
+ $ git show v1.4
947
+ tag v1.4
948
+ Tagger: Scott Chacon <schacon@gee-mail.com>
949
+ Date: Mon Feb 9 14:45:11 2009 -0800
950
+
951
+ my version 1.4
952
+
953
+ commit 15027957951b64cf874c3557a0f3547bd83b3ff6
954
+ Merge: 4a447f7... a6b4c97...
955
+ Author: Scott Chacon <schacon@gee-mail.com>
956
+ Date: Sun Feb 8 19:02:46 2009 -0800
957
+
958
+ Merge branch 'experiment'
959
+
960
+ 커밋 정보를 보여주기 전에 먼저 태그를 만든 사람이 누구인지, 언제 태그를 만들었는지, 그리고 태그 메시지가 무엇인지 보여준다.
961
+
962
+ ### 태그에 서명하기 ###
963
+
964
+ GPG 개인키가 있으면 태그에 서명할 수 있다. 이때에는 `-a`옵션 대신 `-s`를 사용한다:
965
+
966
+ $ git tag -s v1.5 -m 'my signed 1.5 tag'
967
+ You need a passphrase to unlock the secret key for
968
+ user: "Scott Chacon <schacon@gee-mail.com>"
969
+ 1024-bit DSA key, ID F721C45A, created 2009-02-09
970
+
971
+ 이 태그에 `git show`를 실행하면 GPG 서명도 볼 수 있다:
972
+
973
+ $ git show v1.5
974
+ tag v1.5
975
+ Tagger: Scott Chacon <schacon@gee-mail.com>
976
+ Date: Mon Feb 9 15:22:20 2009 -0800
977
+
978
+ my signed 1.5 tag
979
+ -----BEGIN PGP SIGNATURE-----
980
+ Version: GnuPG v1.4.8 (Darwin)
981
+
982
+ iEYEABECAAYFAkmQurIACgkQON3DxfchxFr5cACeIMN+ZxLKggJQf0QYiQBwgySN
983
+ Ki0An2JeAVUCAiJ7Ox6ZEtK+NvZAj82/
984
+ =WryJ
985
+ -----END PGP SIGNATURE-----
986
+ commit 15027957951b64cf874c3557a0f3547bd83b3ff6
987
+ Merge: 4a447f7... a6b4c97...
988
+ Author: Scott Chacon <schacon@gee-mail.com>
989
+ Date: Sun Feb 8 19:02:46 2009 -0800
990
+
991
+ Merge branch 'experiment'
992
+
993
+ 잠시 후에 서명한 태그를 검증하는 방법도 설명한다.
994
+
995
+ ### Lightweight 태그 ###
996
+
997
+ Lightweight 태그는 기본적으로 파일에 커밋 체크섬을 저장하는 것뿐이다. 다른 정보는 저장하지 않는다. Lightweight 태그를 만들 때에는 `-a`, `-s`, `-m` 옵션을 사용하지 않는다:
998
+
999
+ $ git tag v1.4-lw
1000
+ $ git tag
1001
+ v0.1
1002
+ v1.3
1003
+ v1.4
1004
+ v1.4-lw
1005
+ v1.5
1006
+
1007
+ 이 태그에 `git show`를 실행하면 별도의 태그 정보를 확인할 수 없다. 이 명령은 단순히 커밋 정보만을 보여준다:
1008
+
1009
+ $ git show v1.4-lw
1010
+ commit 15027957951b64cf874c3557a0f3547bd83b3ff6
1011
+ Merge: 4a447f7... a6b4c97...
1012
+ Author: Scott Chacon <schacon@gee-mail.com>
1013
+ Date: Sun Feb 8 19:02:46 2009 -0800
1014
+
1015
+ Merge branch 'experiment'
1016
+
1017
+ ### 태그 검증하기 ###
1018
+
1019
+ `git tag -v [태그 이름]` 명령으로 서명한 태그를 검증한다. 이 명령은 GPG를 사용하여 서명을 검증한다. 그래서 서명자의 GPG 공개키가 필요하다. 이 공개키가 Keyring에 있어야만 이 명령이 성공적으로 실행된다:
1020
+
1021
+ $ git tag -v v1.4.2.1
1022
+ object 883653babd8ee7ea23e6a5c392bb739348b1eb61
1023
+ type commit
1024
+ tag v1.4.2.1
1025
+ tagger Junio C Hamano <junkio@cox.net> 1158138501 -0700
1026
+
1027
+ GIT 1.4.2.1
1028
+
1029
+ Minor fixes since 1.4.2, including git-mv and git-http with alternates.
1030
+ gpg: Signature made Wed Sep 13 02:08:25 2006 PDT using DSA key ID F3119B9A
1031
+ gpg: Good signature from "Junio C Hamano <junkio@cox.net>"
1032
+ gpg: aka "[jpeg image of size 1513]"
1033
+ Primary key fingerprint: 3565 2A26 2040 E066 C9A7 4A7D C0C6 D9A4 F311 9B9A
1034
+
1035
+ 만약 서명자의 공개키가 없으면 아래와 같은 메시지를 출력한다:
1036
+
1037
+ gpg: Signature made Wed Sep 13 02:08:25 2006 PDT using DSA key ID F3119B9A
1038
+ gpg: Can't check signature: public key not found
1039
+ error: could not verify the tag 'v1.4.2.1'
1040
+
1041
+ ### 나중에 태그하기 ###
1042
+
1043
+ 예전 커밋에 대해서도 태그할 수 있다. 커밋 히스토리는 아래와 같고:
1044
+
1045
+ $ git log --pretty=oneline
1046
+ 15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
1047
+ a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
1048
+ 0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
1049
+ 6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
1050
+ 0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
1051
+ 4682c3261057305bdd616e23b64b0857d832627b added a todo file
1052
+ 166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
1053
+ 9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
1054
+ 964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
1055
+ 8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme
1056
+
1057
+ "updated rakefile" 커밋을 v1.2로 태그하지 못했다고 해도 차후에 태그를 붙일 수 있다. 특정 커밋에 태그하기 위해서 명령의 끝에 커밋 체크섬을 명시한다(긴 체크섬을 전부 사용할 필요는 없다):
1058
+
1059
+ $ git tag -a v1.2 -m 'version 1.2' 9fceb02
1060
+
1061
+ 이제 아래와 같이 만든 태그를 확인한다:
1062
+
1063
+ $ git tag
1064
+ v0.1
1065
+ v1.2
1066
+ v1.3
1067
+ v1.4
1068
+ v1.4-lw
1069
+ v1.5
1070
+
1071
+ $ git show v1.2
1072
+ tag v1.2
1073
+ Tagger: Scott Chacon <schacon@gee-mail.com>
1074
+ Date: Mon Feb 9 15:32:16 2009 -0800
1075
+
1076
+ version 1.2
1077
+ commit 9fceb02d0ae598e95dc970b74767f19372d61af8
1078
+ Author: Magnus Chacon <mchacon@gee-mail.com>
1079
+ Date: Sun Apr 27 20:43:35 2008 -0700
1080
+
1081
+ updated rakefile
1082
+ ...
1083
+
1084
+ ### 태그 공유하기 ###
1085
+
1086
+ `git push` 명령은 자동으로 리모트 서버에 태그를 전송하지 않는다. 태그를 만들었으면 서버에 별도로 Push해야 한다. 브랜치를 공유하는 것과 같은 방법으로 할 수 있다. `git push origin [태그 이름]`을 실행한다:
1087
+
1088
+ $ git push origin v1.5
1089
+ Counting objects: 50, done.
1090
+ Compressing objects: 100% (38/38), done.
1091
+ Writing objects: 100% (44/44), 4.56 KiB, done.
1092
+ Total 44 (delta 18), reused 8 (delta 1)
1093
+ To git@github.com:schacon/simplegit.git
1094
+ * [new tag] v1.5 -> v1.5
1095
+
1096
+ 만약 한 번에 태그를 여러 개 Push하고 싶으면 `--tags` 옵션을 추가하여 `git push`명령을 실행한다. 이 명령으로 리모트 서버에 없는 태그를 모두 전송할 수 있다:
1097
+
1098
+ $ git push origin --tags
1099
+ Counting objects: 50, done.
1100
+ Compressing objects: 100% (38/38), done.
1101
+ Writing objects: 100% (44/44), 4.56 KiB, done.
1102
+ Total 44 (delta 18), reused 8 (delta 1)
1103
+ To git@github.com:schacon/simplegit.git
1104
+ * [new tag] v0.1 -> v0.1
1105
+ * [new tag] v1.2 -> v1.2
1106
+ * [new tag] v1.4 -> v1.4
1107
+ * [new tag] v1.4-lw -> v1.4-lw
1108
+ * [new tag] v1.5 -> v1.5
1109
+
1110
+ 누군가 저장소에서 Clone하거나 Pull을 하면 모든 태그 정보도 함께 전송된다.
1111
+
1112
+ ## 팁과 트릭 ##
1113
+
1114
+ Git의 기초를 마치기 전에 Git을 좀 더 쉽고 편안하게 쓸 수 있게 만들어 줄 몇 가지 팁과 트릭도 설명한다. 이런 팁 없이 Git을 사용하는 사람들도 많다. 우리는 이 책에서 이 팁을 다시 거론하지 않고 이런 팁을 알고 있다고 가정한다. 그래서 알고 있는 것이 좋다.
1115
+
1116
+ ### 자동완성 ###
1117
+
1118
+ Bash 쉘을 쓰고 있다면 멋진 자동완성(Auto-completion) 기능을 사용할 수 있다. https://github.com/git/git/blob/master/contrib/completion/git-completion.bash 에서 바로 다운받는다. 그 파일을 홈 디렉토리에 카피하고 `.bashrc` 파일에 아래와 같은 내용을 추가하자:
1119
+
1120
+ source ~/git-completion.bash
1121
+
1122
+ 또 모든 사용자가 사용할 수 있게 설정할 수 있다. Mac 시스템이라면 이 스크립트를 `/opt/local/etc/bash_completion.d` 디렉토리에 복사하고 리눅스라면 `/etc/bash_completion.d/`에 복사한다. 이 디렉토리는 Bash가 자동완성을 지원하기 위해 사용하는 디렉토리다.
1123
+
1124
+ 윈도에 msysGit을 설치해서 Git Bash를 사용하는 경우에는 자동완성이 미리 설정되어 있다.
1125
+
1126
+ Git 명령을 입력할 때 `<Tab>` 키를 누르면 Git이 제안하는 명령어가 출력된다:
1127
+
1128
+ $ git co<tab><tab>
1129
+ commit config
1130
+
1131
+ 이 경우 `git co`를 입력하고 Tab 키를 두번 누르면 commit과 config를 제안한다. 이 때 `m<tab>`을 입력하면 자동으로 `git commit`명령을 완성한다.
1132
+
1133
+ 옵션에도 이 기능이 되고 더 유용하다. 예를 들어 `git log`명령을 실행하는데 옵션이 전혀 기억나지 않는다면 아래와 같이 입력하고 Tap 키를 누르면 아래와 같은 옵션을 제안한다:
1134
+
1135
+ $ git log --s<tab>
1136
+ --shortstat --since= --src-prefix= --stat --summary
1137
+
1138
+ 이건 상당히 멋진 팁이다. 아마 문서를 찾아보는 등의 시간을 절약해 줄 것이다.
1139
+
1140
+ ### Git Alias ###
1141
+
1142
+ 명령을 완벽하게 입력하지 않으면 Git은 알아듣지 못한다. Git의 명령을 전부 입력하는 것이 귀찮다면 `git config`를 사용하여 각 명령의 Alias을 쉽게 만들 수 있다. 아래는 Alias을 만드는 예이다:
1143
+
1144
+ $ git config --global alias.co checkout
1145
+ $ git config --global alias.br branch
1146
+ $ git config --global alias.ci commit
1147
+ $ git config --global alias.st status
1148
+
1149
+ 이제 `git commit` 대신 `git ci`만으로도 커밋할 수 있다. Git을 계속 사용한다면 다른 명령어도 자주 사용하게 될 것이다. 자주 사용하는 명령은 Alias을 만들어 편하게 사용한다.
1150
+
1151
+ 이미 있는 명령을 편리하고 새로운 명령으로 만들어 사용할 수 있다. 예를 들어 파일을 Unstage 상태로 변경하는 명령을 만들어서 불편함을 덜 수 있다. 아래와 같이 `unstage` 라는 Alias을 만든다:
1152
+
1153
+ $ git config --global alias.unstage 'reset HEAD --'
1154
+
1155
+ 아래 두 명령은 동일한 명령이다:
1156
+
1157
+ $ git unstage fileA
1158
+ $ git reset HEAD fileA
1159
+
1160
+ 한결 간결해졌다. 추가로 `last` 명령을 만들어 보자:
1161
+
1162
+ $ git config --global alias.last 'log -1 HEAD'
1163
+
1164
+ 이제 최근 커밋을 좀 더 쉽게 확인할 수 있다:
1165
+
1166
+ $ git last
1167
+ commit 66938dae3329c7aebe598c2246a8e6af90d04646
1168
+ Author: Josh Goebel <dreamer3@example.com>
1169
+ Date: Tue Aug 26 19:48:51 2008 +0800
1170
+
1171
+ test for current head
1172
+
1173
+ Signed-off-by: Scott Chacon <schacon@example.com>
1174
+
1175
+ 이것으로 쉽게 새로운 명령을 만들 수 있다. 그리고 Git의 명령어뿐만 아니라 외부 명령어도 실행할 수 있다. `!`를 제일 앞에 추가하면 외부 명령을 실행한다. 아래 명령은 `git visual`이라고 입력하면 `gitk`가 실행된다:
1176
+
1177
+ $ git config --global alias.visual '!gitk'
1178
+
1179
+ ## 요약 ##
1180
+
1181
+ 이제 우리는 로컬에서 사용할 수 있는 Git 명령에 대한 기본 지식은 갖추었다. 저장소를 만들고 Clone하는 방법, 수정하고 나서 Stage하고 커밋하는 방법, 저장소의 히스토리를 조회하는 방법 등을 살펴보았다. 이어지는 장에서는 Git의 가장 강력한 기능인 브랜치 모델을 살펴볼 것이다.