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,1133 @@
1
+ # Git のさまざまなツール #
2
+
3
+ Git を使ったソースコード管理のためのリポジトリの管理や保守について、日々使用するコマンドやワークフローの大半を身につけました。ファイルの追跡やコミットといった基本的なタスクをこなせるようになっただけではなくステージングエリアの威力もいかせるようになりました。また気軽にトピックブランチを切ってマージする方法も知りました。
4
+
5
+ では、Git の非常に強力な機能の数々をさらに探っていきましょう。日々の作業でこれらを使うことはあまりありませんが、いつかは必要になるかもしれません。
6
+
7
+ ## リビジョンの選択 ##
8
+
9
+ Git で特定のコミットやコミットの範囲を指定するにはいくつかの方法があります。明白なものばかりではありませんが、知っておくと役立つでしょう。
10
+
11
+ ### 単一のリビジョン ###
12
+
13
+ SHA-1 ハッシュを指定すれば、コミットを明確に参照することができます。しかしそれ以外にも、より人間にやさしい方式でコミットを参照することもできます。このセクションでは単一のコミットを参照するためのさまざまな方法の概要を説明します。
14
+
15
+ ### SHA の短縮形 ###
16
+
17
+ Git は、最初の数文字をタイプしただけであなたがどのコミットを指定したいのかを汲み取ってくれます。条件は、SHA-1 の最初の 4 文字以上を入力していることと、それでひとつのコミットが特定できる (現在のリポジトリに、入力した文字ではじまる SHA-1 のコミットがひとつしかない) ことです。
18
+
19
+ あるコミットを指定するために `git log` コマンドを実行し、とある機能を追加したコミットを見つけました。
20
+
21
+ $ git log
22
+ commit 734713bc047d87bf7eac9674765ae793478c50d3
23
+ Author: Scott Chacon <schacon@gmail.com>
24
+ Date: Fri Jan 2 18:32:33 2009 -0800
25
+
26
+ fixed refs handling, added gc auto, updated tests
27
+
28
+ commit d921970aadf03b3cf0e71becdaab3147ba71cdef
29
+ Merge: 1c002dd... 35cfb2b...
30
+ Author: Scott Chacon <schacon@gmail.com>
31
+ Date: Thu Dec 11 15:08:43 2008 -0800
32
+
33
+ Merge commit 'phedders/rdocs'
34
+
35
+ commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
36
+ Author: Scott Chacon <schacon@gmail.com>
37
+ Date: Thu Dec 11 14:58:32 2008 -0800
38
+
39
+ added some blame and merge stuff
40
+
41
+ 探していたのは、`1c002dd....` で始まるコミットです。`git show` でこのコミットを見るときは、次のどのコマンドでも同じ結果になります (短いバージョンで、重複するコミットはないものとします)。
42
+
43
+ $ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
44
+ $ git show 1c002dd4b536e7479f
45
+ $ git show 1c002d
46
+
47
+ 一意に特定できる範囲での SHA-1 の短縮形を Git に見つけさせることもできます。`git log` コマンドで `--abbrev-commit` を指定すると、コミットを一意に特定できる範囲の省略形で出力します。デフォルトでは 7 文字ぶん表示しますが、それだけで SHA-1 を特定できない場合はさらに長くなります。
48
+
49
+ $ git log --abbrev-commit --pretty=oneline
50
+ ca82a6d changed the version number
51
+ 085bb3b removed unnecessary test code
52
+ a11bef0 first commit
53
+
54
+ ひとつのプロジェクト内での一意性を確保するには、普通は 8 文字から 10 文字もあれば十分すぎることでしょう。最も大規模な Git プロジェクトのひとつである Linux カーネルの場合は、40 文字のうち先頭の 12 文字を指定しないと一意性を確保できません。
55
+
56
+ ### SHA-1 に関するちょっとしたメモ ###
57
+ 「リポジトリ内のふたつのオブジェクトがたまたま同じ SHA-1 ハッシュ値を持ってしまったらどうするの?」と心配する人も多いでしょう。実際、どうなるのでしょう?
58
+
59
+ すでにリポジトリに存在するオブジェクトと同じ SHA-1 値を持つオブジェクトをコミットしてした場合、Git はすでにそのオブジェクトがデータベースに格納されているものと判断します。そのオブジェクトを後からどこかで取得しようとすると、常に最初のオブジェクトのデータが手元にやってきます (訳注: つまり、後からコミットした内容は存在しないことになってしまう)。
60
+
61
+ しかし、そんなことはまず起こりえないということを知っておくべきでしょう。SHA-1 ダイジェストの大きさは 20 バイト (160 ビット) です。ランダムなハッシュ値がつけられた中で、たった一つの衝突が 50% の確率で発生するために必要なオブジェクトの数は約 2^80 となります (衝突の可能性の計算式は `p = (n(n-1)/2) * (1/2^160)` です)。2^80 は、ほぼ 1.2 x 10^24 、つまり一兆二千億のそのまた一兆倍です。これは、地球上にあるすべての砂粒の数の千二百倍にあたります。
62
+
63
+ SHA-1 の衝突を見るにはどうしたらいいのか、ひとつの例をごらんに入れましょう。地球上の人類 65 億人が全員プログラムを書いていたとします。そしてその全員が、Linux カーネルのこれまでの開発履歴 (100 万の Git オブジェクト) と同等のコードを一秒で書き上げ、馬鹿でかい単一の Git リポジトリにプッシュしていくとします。これを五年間続けたとして、SHA-1 オブジェクトの衝突がひとつでも発生する可能性がやっと 50% になります。それよりも「あなたの所属する開発チームの全メンバーが、同じ夜にそれぞれまったく無関係の事件で全員オオカミに殺されてしまう」可能性のほうがよっぽど高いことでしょう。
64
+
65
+ ### ブランチの参照 ###
66
+
67
+ 特定のコミットを参照するのに一番直感的なのは、そのコミットを指すブランチがある場合です。コミットオブジェクトや SHA-1 値を指定する場面ではどこでも、その代わりにブランチ名を指定することができます。たとえば、あるブランチ上の最新のコミットを表示したい場合は次のふたつのコマンドが同じ意味となります (`topic1` ブランチが `ca82a6d` を指しているものとします)。
68
+
69
+ $ git show ca82a6dff817ec66f44342007202690a93763949
70
+ $ git show topic1
71
+
72
+ あるブランチがいったいどの SHA を指しているのか、あるいはその他の例の内容が結局のところどの SHA に行き着くのかといったことを知るには、Git の調査用ツールである `rev-parse` を使います。こういった調査用ツールのより詳しい情報は第 9 章で説明します。`rev-parse` は低レベルでの操作用のコマンドであり、日々の操作で使うためのものではありません。しかし、今実際に何が起こっているのかを知る必要があるときなどには便利です。ブランチ上で `rev-parse` を実行すると、このようになります。
73
+
74
+ $ git rev-parse topic1
75
+ ca82a6dff817ec66f44342007202690a93763949
76
+
77
+ ### 参照ログの短縮形 ###
78
+
79
+ あなたがせっせと働いている間に Git が裏でこっそり行っていることのひとつが、参照ログ (reflog) の管理です。これは、HEAD とブランチの参照が過去数ヶ月間どのように動いてきたかをあらわすものです。
80
+
81
+ 参照ログを見るには `git reflog` を使います。
82
+
83
+ $ git reflog
84
+ 734713b HEAD@{0}: commit: fixed refs handling, added gc auto, updated
85
+ d921970 HEAD@{1}: merge phedders/rdocs: Merge made by recursive.
86
+ 1c002dd HEAD@{2}: commit: added some blame and merge stuff
87
+ 1c36188 HEAD@{3}: rebase -i (squash): updating HEAD
88
+ 95df984 HEAD@{4}: commit: # This is a combination of two commits.
89
+ 1c36188 HEAD@{5}: rebase -i (squash): updating HEAD
90
+ 7e05da5 HEAD@{6}: rebase -i (pick): updating HEAD
91
+
92
+ 何らかの理由でブランチの先端が更新されるたびに、Git はその情報をこの一時履歴に格納します。そして、このデータを使って過去のコミットを指定することもできます。リポジトリの HEAD の五つ前の状態を知りたい場合は、先ほど見た reflog の出力のように `@{n}` 形式で参照することができます。
93
+
94
+ $ git show HEAD@{5}
95
+
96
+ この構文を使うと、指定した期間だけさかのぼったときに特定のブランチがどこを指していたかを知ることもできます。たとえば `master` ブランチの昨日の状態を知るには、このようにします。
97
+
98
+ $ git show master@{yesterday}
99
+
100
+ こうすると、そのブランチの先端が昨日どこを指していたかを表示します。この技が使えるのは参照ログにデータが残っている間だけなので、直近数ヶ月よりも前のコミットについては使うことができません。
101
+
102
+ 参照ログの情報を `git log` の出力風の表記で見るには `git log -g` を実行します。
103
+
104
+ $ git log -g master
105
+ commit 734713bc047d87bf7eac9674765ae793478c50d3
106
+ Reflog: master@{0} (Scott Chacon <schacon@gmail.com>)
107
+ Reflog message: commit: fixed refs handling, added gc auto, updated
108
+ Author: Scott Chacon <schacon@gmail.com>
109
+ Date: Fri Jan 2 18:32:33 2009 -0800
110
+
111
+ fixed refs handling, added gc auto, updated tests
112
+
113
+ commit d921970aadf03b3cf0e71becdaab3147ba71cdef
114
+ Reflog: master@{1} (Scott Chacon <schacon@gmail.com>)
115
+ Reflog message: merge phedders/rdocs: Merge made by recursive.
116
+ Author: Scott Chacon <schacon@gmail.com>
117
+ Date: Thu Dec 11 15:08:43 2008 -0800
118
+
119
+ Merge commit 'phedders/rdocs'
120
+
121
+ 参照ログの情報は、完全にローカルなものであることに気をつけましょう。これは、あなた自身が自分のリポジトリで何をしたのかを示す記録です。つまり、同じリポジトリをコピーした別の人の参照ログとは異なる内容になります。また、最初にリポジトリをクローンした直後の参照ログは空となります。まだリポジトリ上であなたが何もしていないからです。`git show HEAD@{2.months.ago}` が動作するのは、少なくとも二ヶ月以上前にそのリポジトリをクローンした場合のみで、もしつい 5 分前にクローンしたばかりなら何も結果を返しません。
122
+
123
+ ### 家系の参照 ###
124
+
125
+ コミットを特定する方法として他によく使われるのが、その家系をたどっていく方法です。参照の最後に `^` をつけると、Git はそれを「指定したコミットの親」と解釈します。あなたのプロジェクトの歴史がこのようになっていたとしましょう。
126
+
127
+ $ git log --pretty=format:'%h %s' --graph
128
+ * 734713b fixed refs handling, added gc auto, updated tests
129
+ * d921970 Merge commit 'phedders/rdocs'
130
+ |\
131
+ | * 35cfb2b Some rdoc changes
132
+ * | 1c002dd added some blame and merge stuff
133
+ |/
134
+ * 1c36188 ignore *.gem
135
+ * 9b29157 add open3_detach to gemspec file list
136
+
137
+ 直前のコミットを見るには `HEAD^` を指定します。これは "HEAD の親" という意味になります。
138
+
139
+ $ git show HEAD^
140
+ commit d921970aadf03b3cf0e71becdaab3147ba71cdef
141
+ Merge: 1c002dd... 35cfb2b...
142
+ Author: Scott Chacon <schacon@gmail.com>
143
+ Date: Thu Dec 11 15:08:43 2008 -0800
144
+
145
+ Merge commit 'phedders/rdocs'
146
+
147
+ `^` の後に数字を指定することもできます。たとえば `d921970^2` は "d921970 の二番目の親" という意味になります。これが役立つのはマージコミット (親が複数存在する) のときくらいでしょう。最初の親はマージを実行したときにいたブランチとなり、二番目の親は取り込んだブランチ上のコミットとなります。
148
+
149
+ $ git show d921970^
150
+ commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
151
+ Author: Scott Chacon <schacon@gmail.com>
152
+ Date: Thu Dec 11 14:58:32 2008 -0800
153
+
154
+ added some blame and merge stuff
155
+
156
+ $ git show d921970^2
157
+ commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548
158
+ Author: Paul Hedderly <paul+git@mjr.org>
159
+ Date: Wed Dec 10 22:22:03 2008 +0000
160
+
161
+ Some rdoc changes
162
+
163
+ 家系の指定方法としてもうひとつよく使うのが `~` です。これも最初の親を指します。つまり `HEAD~` と `HEAD^` は同じ意味になります。違いが出るのは、数字を指定したときです。`HEAD~2` は "最初の親の最初の親" つまり "祖父母" という意味になります。指定した数だけ、順に最初の親をさかのぼっていくことになります。たとえば、先ほど示したような歴史上では `HEAD~3` は次のようになります。
164
+
165
+ $ git show HEAD~3
166
+ commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
167
+ Author: Tom Preston-Werner <tom@mojombo.com>
168
+ Date: Fri Nov 7 13:47:59 2008 -0500
169
+
170
+ ignore *.gem
171
+
172
+ これは `HEAD^^^` のようにあらわすこともできます。これは「最初の親の最初の親の最初の親」という意味になります。
173
+
174
+ $ git show HEAD^^^
175
+ commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
176
+ Author: Tom Preston-Werner <tom@mojombo.com>
177
+ Date: Fri Nov 7 13:47:59 2008 -0500
178
+
179
+ ignore *.gem
180
+
181
+ これらふたつの構文を組み合わせることもできます。直近の参照 (マージコミットだったとします) の二番目の親を取得するには `HEAD~3^2` などとすればいいのです。
182
+
183
+ ### コミットの範囲指定 ###
184
+
185
+ 個々のコミットを指定できるようになったので、次はコミットの範囲を指定する方法を覚えていきましょう。これは、ブランチをマージするときに便利です。たくさんのブランチを持っている場合など「で、このブランチの作業のなかでまだメインブランチにマージしていないのはどれだったっけ?」といった疑問に答えるために範囲指定を使えます。
186
+
187
+ #### ダブルドット ####
188
+
189
+ 範囲指定の方法としてもっとも一般的なのが、ダブルドット構文です。これは、ひとつのコミットからはたどれるけれどもうひとつのコミットからはたどれないというコミットの範囲を Git に調べさせるものです。図 6-1 のようなコミット履歴を例に考えましょう。
190
+
191
+ Insert 18333fig0601.png
192
+ 図 6-1. 範囲指定選択用の歴史の例
193
+
194
+ experiment ブランチの内容のうち、まだ master ブランチにマージされていないものを調べることになりました。対象となるコミットのログを見るには、Git に `master..experiment` と指示します。これは "experiment からはたどれるけれど、master からはたどれないすべてのコミット" という意味です。説明を短く簡潔にするため、実際のログの出力のかわりに上の図の中でコミットオブジェクトをあらわす文字を使うことにします。
195
+
196
+ $ git log master..experiment
197
+ D
198
+ C
199
+
200
+ もし逆に、`master` には存在するけれども `experiment` には存在しないすべてのコミットが知りたいのなら、ブランチ名を逆にすればいいのです。`experiment..master` とすれば、`master` のすべてのコミットのうち `experiment` からたどれないものを取得できます。
201
+
202
+ $ git log experiment..master
203
+ F
204
+ E
205
+
206
+ これは、`experiment` ブランチを最新の状態に保つために何をマージしなければならないのかを知るのに便利です。もうひとつ、この構文をよく使う例としてあげられるのが、これからリモートにプッシュしようとしている内容を知りたいときです。
207
+
208
+ $ git log origin/master..HEAD
209
+
210
+ このコマンドは、現在のブランチ上でのコミットのうち、リモート `origin` の `master` ブランチに存在しないものをすべて表示します。現在のブランチが `origin/master` を追跡しているときに `git push` を実行すると、`git log origin/master..HEAD` で表示されたコミットがサーバーに転送されます。この構文で、どちらか片方を省略することもできます。その場合、Git は省略したほうを HEAD とみなします。たとえば、`git log origin/master..` と入力すると先ほどの例と同じ結果が得られます。Git は、省略した側を HEAD に置き換えて処理を進めるのです。
211
+
212
+ #### 複数のポイント ####
213
+
214
+ ダブルドット構文は、とりあえず使うぶんには便利です。しかし、二つよりもっと多くのブランチを指定してリビジョンを特定したいこともあるでしょう。複数のブランチの中から現在いるブランチには存在しないコミットを見つける場合などです。Git でこれを行うには `^` 文字を使うか、あるいはそこからたどりつけるコミットが不要な参照の前に `--not` をつけます。これら三つのコマンドは、同じ意味となります。
215
+
216
+ $ git log refA..refB
217
+ $ git log ^refA refB
218
+ $ git log refB --not refA
219
+
220
+ これらの構文が便利なのは、二つよりも多くの参照を使って指定できるというところです。ダブルドット構文では二つの参照しか指定できませんでした。たとえば、`refA` と `refB` のどちらかからはたどれるけれども `refC` からはたどれないコミットを取得したい場合は、次のいずれかを実行します。
221
+
222
+ $ git log refA refB ^refC
223
+ $ git log refA refB --not refC
224
+
225
+ この非常に強力なリビジョン問い合わせシステムを使えば、今あなたのブランチに何があるのかを知るのに非常に役立つことでしょう。
226
+
227
+ #### トリプルドット ####
228
+
229
+ 範囲指定選択の主な構文であとひとつ残っているのがトリプルドット構文です。これは、ふたつの参照のうちどちらか一方からのみたどれるコミット (つまり、両方からたどれるコミットは含まない) を指定します。図 6-1 で示したコミット履歴の例を振り返ってみましょう。`master` あるいは `experiment` に存在するコミットのうち、両方に存在するものを除いたコミットを知りたい場合は次のようにします。
230
+
231
+ $ git log master...experiment
232
+ F
233
+ E
234
+ D
235
+ C
236
+
237
+ これは通常の `log` の出力と同じですが、これら四つのコミットについての情報しか表示しません。表示順は、従来どおりコミット日時順となります。
238
+
239
+ この場合に `log` コマンドでよく使用するスイッチが `--left-right` です。このスイッチは、それぞれのコミットがどちら側に存在するのかを表示します。これを使うとデータをより活用しやすくなるでしょう。
240
+
241
+ $ git log --left-right master...experiment
242
+ < F
243
+ < E
244
+ > D
245
+ > C
246
+
247
+ これらのツールを使えば、より簡単に「どれを調べたいのか」を Git に伝えられるようになります。
248
+
249
+ ## 対話的なステージング ##
250
+
251
+ Git には、コマンドラインでの作業をしやすくするためのスクリプトがいくつか付属しています。ここでは、対話コマンドをいくつか紹介しましょう。これらを使うと、コミットの内容に細工をして特定のコミットだけとかファイルの中の一部だけとかを含めるようにすることが簡単にできるようになります。大量のファイルを変更した後に、それをひとつの馬鹿でかいコミットにしてしまうのではなくテーマごとの複数のコミットに分けて処理したい場合などに非常に便利です。このようにして各コミットを論理的に独立した状態にしておけば、同僚によるレビューも容易になります。`git add` に `-i` あるいは `--interactive` というオプションをつけて実行すると、Git は対話シェルモードに移行し、このように表示されます。
252
+
253
+ $ git add -i
254
+ staged unstaged path
255
+ 1: unchanged +0/-1 TODO
256
+ 2: unchanged +1/-1 index.html
257
+ 3: unchanged +5/-1 lib/simplegit.rb
258
+
259
+ *** Commands ***
260
+ 1: status 2: update 3: revert 4: add untracked
261
+ 5: patch 6: diff 7: quit 8: help
262
+ What now>
263
+
264
+ このコマンドは、ステージングエリアに関する情報を違った観点で表示します。`git status` で得られる情報と基本的には同じですが、より簡潔で有益なものとなっています。ステージした変更が左側、そしてステージしていない変更が右側に表示されます。
265
+
266
+ Commands セクションでは、さまざまなことができるようになっています。ファイルをステージしたりステージングエリアから戻したり、ファイルの一部だけをステージしたりまだ追跡されていないファイルを追加したり、あるいは何がステージされたのかを diff で見たりといったことが可能です。
267
+
268
+ ### ファイルのステージとその取り消し ###
269
+
270
+ `What now>` プロンプトで `2` または `u` と入力すると、どのファイルをステージするかを聞いてきます。
271
+
272
+ What now> 2
273
+ staged unstaged path
274
+ 1: unchanged +0/-1 TODO
275
+ 2: unchanged +1/-1 index.html
276
+ 3: unchanged +5/-1 lib/simplegit.rb
277
+ Update>>
278
+
279
+ TODO と index.html をステージするには、その番号を入力します。
280
+
281
+ Update>> 1,2
282
+ staged unstaged path
283
+ * 1: unchanged +0/-1 TODO
284
+ * 2: unchanged +1/-1 index.html
285
+ 3: unchanged +5/-1 lib/simplegit.rb
286
+ Update>>
287
+
288
+ ファイル名の横に `*` がついていれば、そのファイルがステージ対象として選択されたことを意味します。`Update>>` プロンプトで何も入力せずに Enter を押すと、選択されたすべてのファイルを Git がステージします。
289
+
290
+ Update>>
291
+ updated 2 paths
292
+
293
+ *** Commands ***
294
+ 1: status 2: update 3: revert 4: add untracked
295
+ 5: patch 6: diff 7: quit 8: help
296
+ What now> 1
297
+ staged unstaged path
298
+ 1: +0/-1 nothing TODO
299
+ 2: +1/-1 nothing index.html
300
+ 3: unchanged +5/-1 lib/simplegit.rb
301
+
302
+ TODO と index.html がステージされ、simplegit.rb はまだステージされていないままです。ここで仮に TODO ファイルのステージを取り消したくなったとしたら、`3` あるいは `r` (revert の r) を選択します。
303
+
304
+ *** Commands ***
305
+ 1: status 2: update 3: revert 4: add untracked
306
+ 5: patch 6: diff 7: quit 8: help
307
+ What now> 3
308
+ staged unstaged path
309
+ 1: +0/-1 nothing TODO
310
+ 2: +1/-1 nothing index.html
311
+ 3: unchanged +5/-1 lib/simplegit.rb
312
+ Revert>> 1
313
+ staged unstaged path
314
+ * 1: +0/-1 nothing TODO
315
+ 2: +1/-1 nothing index.html
316
+ 3: unchanged +5/-1 lib/simplegit.rb
317
+ Revert>> [enter]
318
+ reverted one path
319
+
320
+ もう一度 Git のステータスを見ると、TODO ファイルのステージが取り消されていることがわかります。
321
+
322
+ *** Commands ***
323
+ 1: status 2: update 3: revert 4: add untracked
324
+ 5: patch 6: diff 7: quit 8: help
325
+ What now> 1
326
+ staged unstaged path
327
+ 1: unchanged +0/-1 TODO
328
+ 2: +1/-1 nothing index.html
329
+ 3: unchanged +5/-1 lib/simplegit.rb
330
+
331
+ ステージした変更の diff を見るには、`6` あるいは `d` (diff の d) を使用します。このコマンドは、ステージしたファイルの一覧を表示します。その中から、ステージされた diff を見たいファイルを選択します。これは、コマンドラインで `git diff --cached` を使用するのと同じようなことです。
332
+
333
+ *** Commands ***
334
+ 1: status 2: update 3: revert 4: add untracked
335
+ 5: patch 6: diff 7: quit 8: help
336
+ What now> 6
337
+ staged unstaged path
338
+ 1: +1/-1 nothing index.html
339
+ Review diff>> 1
340
+ diff --git a/index.html b/index.html
341
+ index 4d07108..4335f49 100644
342
+ --- a/index.html
343
+ +++ b/index.html
344
+ @@ -16,7 +16,7 @@ Date Finder
345
+
346
+ <p id="out">...</p>
347
+
348
+ -<div id="footer">contact : support@github.com</div>
349
+ +<div id="footer">contact : email.support@github.com</div>
350
+
351
+ <script type="text/javascript">
352
+
353
+ これらの基本的なコマンドを使えば、ステージングエリアでの対話的な追加モードを多少簡単に扱えるようになるでしょう。
354
+
355
+ ### パッチのステージ ###
356
+
357
+ Git では、ファイルの特定の箇所だけをステージして他の部分はそのままにしておくということもできます。たとえば、simplegit.rb のふたつの部分を変更したけれど、そのうちの一方だけをステージしたいという場合があります。Git なら、そんなことも簡単です。対話モードのプロンプトで `5` あるいは `p` (patch の p) と入力しましょう。Git は、どのファイルを部分的にステージしたいのかを聞いてきます。その後、選択したファイルのそれぞれについて diff のハンクを順に表示し、ステージするかどうかをひとつひとつたずねます。
358
+
359
+ diff --git a/lib/simplegit.rb b/lib/simplegit.rb
360
+ index dd5ecc4..57399e0 100644
361
+ --- a/lib/simplegit.rb
362
+ +++ b/lib/simplegit.rb
363
+ @@ -22,7 +22,7 @@ class SimpleGit
364
+ end
365
+
366
+ def log(treeish = 'master')
367
+ - command("git log -n 25 #{treeish}")
368
+ + command("git log -n 30 #{treeish}")
369
+ end
370
+
371
+ def blame(path)
372
+ Stage this hunk [y,n,a,d,/,j,J,g,e,?]?
373
+
374
+ ここでは多くの選択肢があります。何ができるのかを見るには `?` を入力しましょう。
375
+
376
+ Stage this hunk [y,n,a,d,/,j,J,g,e,?]? ?
377
+ y - stage this hunk
378
+ n - do not stage this hunk
379
+ a - stage this and all the remaining hunks in the file
380
+ d - do not stage this hunk nor any of the remaining hunks in the file
381
+ g - select a hunk to go to
382
+ / - search for a hunk matching the given regex
383
+ j - leave this hunk undecided, see next undecided hunk
384
+ J - leave this hunk undecided, see next hunk
385
+ k - leave this hunk undecided, see previous undecided hunk
386
+ K - leave this hunk undecided, see previous hunk
387
+ s - split the current hunk into smaller hunks
388
+ e - manually edit the current hunk
389
+ ? - print help
390
+
391
+ たいていは、`y` か `n` で各ハンクをステージするかどうかを指定していくでしょう。しかし、それ以外にも「このファイルの残りのハンクをすべてステージする」とか「このハンクをステージするかどうかの判断を先送りする」などというオプションも便利です。あるファイルのひとつの箇所だけをステージして残りはそのままにした場合、ステータスの出力はこのようになります。
392
+
393
+ What now> 1
394
+ staged unstaged path
395
+ 1: unchanged +0/-1 TODO
396
+ 2: +1/-1 nothing index.html
397
+ 3: +1/-1 +4/-0 lib/simplegit.rb
398
+
399
+ simplegit.rb のステータスがおもしろいことになっています。ステージされた行もあれば、ステージされていない行もあるという状態です。つまり、このファイルを部分的にステージしたというわけです。この時点で対話的追加モードを抜けて `git commit` を実行すると、ステージした部分だけをコミットすることができます。
400
+
401
+ 最後に、この対話的追加モードを使わずに部分的なステージを行いたい場合は、コマンドラインから `git add -p` あるいは `git add --patch` を実行すれば同じことができます。
402
+
403
+ ## 作業を隠す ##
404
+
405
+ 何らかのプロジェクトの一員として作業している場合にありがちなのですが、ある作業が中途半端な状態になっているときに、ブランチを切り替えてちょっとだけ別の作業をしたくなることがあります。中途半端な状態をコミットしてしまうのはいやなので、できればコミットせずにしておいて後でその状態から作業を再開したいものです。そんなときに使うのが `git stash` コマンドです。
406
+
407
+ これは、作業ディレクトリのダーティな状態 (追跡しているファイルのうち変更されたもの、そしてステージされた変更) を受け取って未完了の作業をスタックに格納し、あとで好きなときに再度それを適用できるようにするものです。
408
+
409
+ ### 自分の作業を隠す ###
410
+
411
+ 例を見てみましょう。自分のプロジェクトでいくつかのファイルを編集し、その中のひとつをステージしたとします。ここで `git status` を実行すると、ダーティな状態を確認することができます。
412
+
413
+ $ git status
414
+ # On branch master
415
+ # Changes to be committed:
416
+ # (use "git reset HEAD <file>..." to unstage)
417
+ #
418
+ # modified: index.html
419
+ #
420
+ # Changes not staged for commit:
421
+ # (use "git add <file>..." to update what will be committed)
422
+ #
423
+ # modified: lib/simplegit.rb
424
+ #
425
+
426
+ ここで別のブランチに切り替えることになりましたが、現在の作業内容はまだコミットしたくありません。そこで、変更をいったん隠すことにします。新たにスタックに隠すには `git stash` を実行します。
427
+
428
+ $ git stash
429
+ Saved working directory and index state \
430
+ "WIP on master: 049d078 added the index file"
431
+ HEAD is now at 049d078 added the index file
432
+ (To restore them type "git stash apply")
433
+
434
+ これで、作業ディレクトリはきれいな状態になりました。
435
+
436
+ $ git status
437
+ # On branch master
438
+ nothing to commit, working directory clean
439
+
440
+ これで、簡単にブランチを切り替えて別の作業をできるようになりました。これまでの変更内容はスタックに格納されています。今までに格納した内容を見るには `git stash list` を使います。
441
+
442
+ $ git stash list
443
+ stash@{0}: WIP on master: 049d078 added the index file
444
+ stash@{1}: WIP on master: c264051 Revert "added file_size"
445
+ stash@{2}: WIP on master: 21d80a5 added number to log
446
+
447
+ この例では、以前にも二回ほど作業を隠していたようです。そこで、三種類の異なる作業にアクセスできるようになっています。先ほど隠した変更を再度適用するには、stash コマンドの出力に書かれていたように `git stash apply` コマンドを実行します。それよりもっと前に隠したものを適用したい場合は `git stash apply stash@{2}` のようにして名前を指定することもできます。名前を指定しなければ、Git は直近に隠された変更を再適用します。
448
+
449
+ $ git stash apply
450
+ # On branch master
451
+ # Changes not staged for commit:
452
+ # (use "git add <file>..." to update what will be committed)
453
+ #
454
+ # modified: index.html
455
+ # modified: lib/simplegit.rb
456
+ #
457
+
458
+ Git がファイルを変更して、未コミットのファイルが先ほどスタックに隠したときと同じ状態に戻ったことがわかるでしょう。今回は、作業ディレクトリがきれいな状態で変更を書き戻しました。また、変更を隠したときと同じブランチに書き戻しています。しかし、隠した内容を再適用するためにこれらが必須条件であるというわけではありません。あるブランチの変更を隠し、別のブランチに移動して移動先のブランチにそれを書き戻すこともできます。また、隠した変更を書き戻す際に、現在のブランチに未コミットの変更があってもかまいません。もしうまく書き戻せなかった場合は、マージ時のコンフリクトと同じようになります。
459
+
460
+ さて、ファイルへの変更はもとどおりになりましたが、以前にステージしていたファイルはステージされていません。これを行うには、`git stash apply` コマンドに `--index` オプションをつけて実行し、変更のステージ処理も再適用するよう指示しなければなりません。先ほどのコマンドのかわりにこれを実行すると、元の状態に戻ります。
461
+
462
+ $ git stash apply --index
463
+ # On branch master
464
+ # Changes to be committed:
465
+ # (use "git reset HEAD <file>..." to unstage)
466
+ #
467
+ # modified: index.html
468
+ #
469
+ # Changes not staged for commit:
470
+ # (use "git add <file>..." to update what will be committed)
471
+ #
472
+ # modified: lib/simplegit.rb
473
+ #
474
+
475
+ apply オプションは、スタックに隠した作業を再度適用するだけで、スタックにはまだその作業が残ったままになります。スタックから削除するには、`git stash drop` に削除したい作業の名前を指定して実行します。
476
+
477
+ $ git stash list
478
+ stash@{0}: WIP on master: 049d078 added the index file
479
+ stash@{1}: WIP on master: c264051 Revert "added file_size"
480
+ stash@{2}: WIP on master: 21d80a5 added number to log
481
+ $ git stash drop stash@{0}
482
+ Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)
483
+
484
+ あるいは `git stash pop` を実行すれば、隠した内容を再適用してその後スタックからも削除してくれます。
485
+
486
+ ### 隠した内容の適用の取り消し ###
487
+
488
+ 隠した変更を適用して何らかの作業をした後に、先ほどの適用を取り消してしまいたくなることもあるでしょう。そんなときに使えそうな `stash unapply` コマンドは git にはありませんが、同じような操作をすることはできます。適用した変更を表すパッチを取得して、それを逆に適用すればいいのです。
489
+
490
+ $ git stash show -p stash@{0} | git apply -R
491
+
492
+ 名前を指定しなければ、Git は直近に隠した変更を使うものとみなします。
493
+
494
+ $ git stash show -p | git apply -R
495
+
496
+ 次の例のようにエイリアスを作れば、Git に `stash-unapply` コマンドを追加したのと事実上同じことになります。
497
+
498
+ $ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
499
+ $ git stash apply
500
+ $ #... 何か作業をして ...
501
+ $ git stash-unapply
502
+
503
+ ### 隠した変更からのブランチの作成 ###
504
+
505
+ 作業をいったん隠し、しばらくそのブランチで作業を続けていると、隠した内容を再適用するときに問題が発生する可能性があります。隠した後に何らかの変更をしたファイルに変更を再適用しようとすると、マージ時にコンフリクトが発生してそれを解決しなければならなくなるでしょう。もう少しお手軽な方法で以前の作業を確認したい場合は `git stash branch` を実行します。このコマンドは、まず新しいブランチを作成し、作業をスタックに隠したときのコミットをチェックアウトし、スタックにある作業を再適用し、それに成功すればスタックからその作業を削除します。
506
+
507
+ $ git stash branch testchanges
508
+ Switched to a new branch "testchanges"
509
+ # On branch testchanges
510
+ # Changes to be committed:
511
+ # (use "git reset HEAD <file>..." to unstage)
512
+ #
513
+ # modified: index.html
514
+ #
515
+ # Changes not staged for commit:
516
+ # (use "git add <file>..." to update what will be committed)
517
+ #
518
+ # modified: lib/simplegit.rb
519
+ #
520
+ Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)
521
+
522
+ これを使うと、保存していた作業をお手軽に復元して新しいブランチで作業をすることができます。
523
+
524
+ ## 歴史の書き換え ##
525
+
526
+ Git を使って作業をしていると、何らかの理由でコミットの歴史を書き換えたくなることが多々あります。Git のすばらしい点のひとつは、何をどうするかの決断をぎりぎりまで先送りできることです。どのファイルをどのコミットに含めるのかは、ステージングエリアの内容をコミットする直前まで変更することができますし、既に作業した内容でも stash コマンドを使えばまだ作業していないことにできます。また、すでにコミットしてしまった変更についても、それを書き換えてまるで別の方法で行ったかのようにすることもできます。コミットの順序を変更したり、コミットメッセージやコミットされるファイルを変更したり、複数のコミットをひとつにまとめたりひとつのコミットを複数に分割したり、コミットそのものをなかったことにしたり……といった作業を、変更内容を他のメンバーに公開する前ならいつでもすることができます。
527
+
528
+ このセクションでは、これらの便利な作業の方法について扱います。これで、あなたのコミットの歴史を思い通りに書き換えてから他の人と共有できるようになります。
529
+
530
+ ### 直近のコミットの変更 ###
531
+
532
+ 直近のコミットを変更するというのは、歴史を書き換える作業のうちもっともよくあるものでしょう。直近のコミットに対して手を加えるパターンとしては、コミットメッセージを変更したりそのコミットで記録されるスナップショットを変更 (ファイルを追加・変更あるいは削除) したりといったものがあります。
533
+
534
+ 単に直近のコミットメッセージを変更したいだけの場合は非常にシンプルです。
535
+
536
+ $ git commit --amend
537
+
538
+ これを実行するとテキストエディタが開きます。すでに直近のコミットメッセージが書き込まれた状態になっており、それを変更することができます。変更を保存してエディタを終了すると、変更後のメッセージを含む新しいコミットを作成して直近のコミットをそれで置き換えます。
539
+
540
+ いったんコミットしたあとで、そこにさらにファイルを追加したり変更したりしたくなったとしましょう。「新しく作ったファイルを追加し忘れた」とかがありそうですね。この場合の手順も基本的には同じです。ファイルを編集して `git add` したり追跡中のファイルを `git rm` したりしてステージングエリアをお好みの状態にしたら、続いて `git commit --amend` を実行します。すると、現在のステージングエリアの状態を次回のコミット用のスナップショットにします。
541
+
542
+ この技を使う際には注意が必要です。この処理を行うとコミットの SHA-1 が変わるからです。いわば、非常に小規模なリベースのようなものです。すでにプッシュしているコミットは書き換えないようにしましょう。
543
+
544
+ ### 複数のコミットメッセージの変更 ###
545
+
546
+ さらに歴史をさかのぼったコミットを変更したい場合は、もう少し複雑なツールを使わなければなりません。Git には歴史を修正するツールはありませんが、リベースツールを使って一連のコミットを (別の場所ではなく) もともとあった場所と同じ HEAD につなげるという方法を使うことができます。対話的なリベースツールを使えば、各コミットについてメッセージを変更したりファイルを追加したりお望みの変更をすることができます。対話的なリベースを行うには、`git rebase` に `-i` オプションを追加します。どこまでさかのぼってコミットを書き換えるかを指示するために、どのコミットにリベースするかを指定しなければなりません。
547
+
548
+ 直近の三つのコミットメッセージあるいはそのいずれかを変更したくなった場合、変更したい最古のコミットの親を `git rebase -i` の引数に指定します。ここでは `HEAD~2^` あるいは `HEAD~3` となります。直近の三つのコミットを編集しようと考えているのだから、`~3` のほうが覚えやすいでしょう。しかし、実際のところは四つ前 (変更したい最古のコミットの親) のコミットを指定していることに注意しましょう。
549
+
550
+ $ git rebase -i HEAD~3
551
+
552
+ これはリベースコマンドであることを認識しておきましょう。 `HEAD~3..HEAD` に含まれるすべてのコミットは、実際にメッセージを変更したか否かにかかわらずすべて書き換えられます。すでに中央サーバーにプッシュしたコミットをここに含めてはいけません。含めてしまうと、同じ変更が別のバージョンで見えてしまうことになって他の開発者が混乱します。
553
+
554
+ このコマンドを実行すると、テキストエディタが開いてコミットの一覧が表示され、このようになります。
555
+
556
+ pick f7f3f6d changed my name a bit
557
+ pick 310154e updated README formatting and added blame
558
+ pick a5f4a0d added cat-file
559
+
560
+ # Rebase 710f0f8..a5f4a0d onto 710f0f8
561
+ #
562
+ # Commands:
563
+ # p, pick = use commit
564
+ # r, reword = use commit, but edit the commit message
565
+ # e, edit = use commit, but stop for amending
566
+ # s, squash = use commit, but meld into previous commit
567
+ # f, fixup = like "squash", but discard this commit's log message
568
+ # x, exec = run command (the rest of the line) using shell
569
+ #
570
+ # These lines can be re-ordered; they are executed from top to bottom.
571
+ #
572
+ # If you remove a line here THAT COMMIT WILL BE LOST.
573
+ #
574
+ # However, if you remove everything, the rebase will be aborted.
575
+ #
576
+ # Note that empty commits are commented out
577
+
578
+ このコミット一覧の表示順は、`log` コマンドを使ったときの通常の表示順とは逆になることに注意しましょう。`log` を実行すると、このようになります。
579
+
580
+ $ git log --pretty=format:"%h %s" HEAD~3..HEAD
581
+ a5f4a0d added cat-file
582
+ 310154e updated README formatting and added blame
583
+ f7f3f6d changed my name a bit
584
+
585
+ 逆順になっていますね。対話的なリベースを実行するとスクリプトが出力されるので、それをあとで実行することになります。このスクリプトはコマンドラインで指定したコミット (`HEAD~3`) から始まり、それ以降のコミットを古い順に再現していきます。最新のものからではなく古いものから表示されているのは、最初に再現するのがいちばん古いコミットだからです。
586
+
587
+ このスクリプトを編集し、手を加えたいコミットのところでスクリプトを停止させるようにします。そのためには、各コミットのうちスクリプトを停止させたいものについて「pick」を「edit」に変更します。たとえば、三番目のコミットメッセージだけを変更したい場合はこのようにファイルを変更します。
588
+
589
+ edit f7f3f6d changed my name a bit
590
+ pick 310154e updated README formatting and added blame
591
+ pick a5f4a0d added cat-file
592
+
593
+ これを保存してエディタを終了すると、Git はそのリストの最初のコミットまで処理を巻き戻し、次のようなメッセージとともにコマンドラインを返します。
594
+
595
+ $ git rebase -i HEAD~3
596
+ Stopped at 7482e0d... updated the gemspec to hopefully work better
597
+ You can amend the commit now, with
598
+
599
+ git commit --amend
600
+
601
+ Once you’re satisfied with your changes, run
602
+
603
+ git rebase --continue
604
+
605
+ この指示が、まさにこれからすべきことを教えてくれています。
606
+
607
+ $ git commit --amend
608
+
609
+ と打ち込んでコミットメッセージを変更してからエディタを終了し、次に
610
+
611
+ $ git rebase --continue
612
+
613
+ を実行します。このコマンドはその他のふたつのコミットも自動的に適用するので、これで作業は終了です。複数行で「pick」を「edit」に変更した場合は、これらの作業を各コミットについてくりかえすことになります。それぞれの場面で Git が停止するので、amend でコミットを書き換えて continue で処理を続けます。
614
+
615
+ ### コミットの並べ替え ###
616
+
617
+ 対話的なリベースで、コミットの順番を変更したり完全に消し去ってしまったりすることもできます。"added cat-file" のコミットを削除して残りの二つのコミットの適用順を反対にしたい場合は、リベーススクリプトを
618
+
619
+ pick f7f3f6d changed my name a bit
620
+ pick 310154e updated README formatting and added blame
621
+ pick a5f4a0d added cat-file
622
+
623
+ から
624
+
625
+ pick 310154e updated README formatting and added blame
626
+ pick f7f3f6d changed my name a bit
627
+
628
+ のように変更します。これを保存してエディタを終了すると、Git はまずこれらのコミットの親までブランチを巻き戻してから `310154e` を適用し、その次に `f7f3f6d` を適用して停止します。これで、効率的にコミット順を変更して "added cat-file" のコミットは完全に取り除くことができました。
629
+
630
+ ### コミットのまとめ ###
631
+
632
+ 一連のコミット群をひとつのコミットにまとめて押し込んでしまうことも、対話的なリベースツールで行うことができます。リベースメッセージの中に、その手順が出力されています。
633
+
634
+ #
635
+ # Commands:
636
+ # p, pick = use commit
637
+ # r, reword = use commit, but edit the commit message
638
+ # e, edit = use commit, but stop for amending
639
+ # s, squash = use commit, but meld into previous commit
640
+ # f, fixup = like "squash", but discard this commit's log message
641
+ # x, exec = run command (the rest of the line) using shell
642
+ #
643
+ # These lines can be re-ordered; they are executed from top to bottom.
644
+ #
645
+ # If you remove a line here THAT COMMIT WILL BE LOST.
646
+ #
647
+ # However, if you remove everything, the rebase will be aborted.
648
+ #
649
+ # Note that empty commits are commented out
650
+
651
+ 「pick」や「edit」のかわりに「squash」を指定すると、Git はその変更と直前の変更をひとつにまとめて新たなコミットメッセージを書き込めるようにします。つまり、これらの三つのコミットをひとつのコミットにまとめたい場合は、スクリプトをこのように変更します。
652
+
653
+ pick f7f3f6d changed my name a bit
654
+ squash 310154e updated README formatting and added blame
655
+ squash a5f4a0d added cat-file
656
+
657
+ これを保存してエディタを終了すると、Git は三つの変更をすべて適用してからエディタに戻るので、そこでコミットメッセージを変更します。
658
+
659
+ # This is a combination of 3 commits.
660
+ # The first commit's message is:
661
+ changed my name a bit
662
+
663
+ # This is the 2nd commit message:
664
+
665
+ updated README formatting and added blame
666
+
667
+ # This is the 3rd commit message:
668
+
669
+ added cat-file
670
+
671
+ これを保存すると、さきほどの三つのコミットの内容をすべて含んだひとつのコミットができあがります。
672
+
673
+ ### コミットの分割 ###
674
+
675
+ コミットの分割は、いったんコミットを取り消してから部分的なステージとコミットを繰り返して行います。たとえば、先ほどの三つのコミットのうち真ん中のものを分割することになったとしましょう。"updated README formatting and added blame" のコミットを、"updated README formatting" と "added blame" のふたつに分割します。そのためには、`rebase -i` スクリプトを実行してそのコミットの指示を「edit」に変更します。
676
+
677
+ pick f7f3f6d changed my name a bit
678
+ edit 310154e updated README formatting and added blame
679
+ pick a5f4a0d added cat-file
680
+
681
+ 変更を保存してエディタを終了すると、Git はリストの最初のコミットの親まで処理を巻き戻します。そして最初のコミット (`f7f3f6d`) と二番目のコミット (`310154e`) を適用してからコンソールに戻ります。コミットをリセットするには `git reset HEAD^` を実行します。これはコミット自体を取り消し、変更されたファイルはステージしていない状態にします。ここまでくれば、取り消された変更点から必要なものだけを選択してコミットすることができます。一連のコミットが終わったら、以下のように`git rebase --continue` を実行しましょう。
682
+
683
+ $ git reset HEAD^
684
+ $ git add README
685
+ $ git commit -m 'updated README formatting'
686
+ $ git add lib/simplegit.rb
687
+ $ git commit -m 'added blame'
688
+ $ git rebase --continue
689
+
690
+ Git はスクリプトの最後のコミット (`a5f4a0d`) を適用し、歴史はこのようになります。
691
+
692
+ $ git log -4 --pretty=format:"%h %s"
693
+ 1c002dd added cat-file
694
+ 9b29157 added blame
695
+ 35cfb2b updated README formatting
696
+ f3cc40e changed my name a bit
697
+
698
+ 念のためにもう一度言いますが、この変更はリスト内のすべてのコミットの SHA を変更します。すでに共有リポジトリにプッシュしたコミットは、このリストに表示させないようにしましょう。
699
+
700
+ ### 最強のオプション: filter-branch ###
701
+
702
+ 歴史を書き換える方法がもうひとつあります。これは、大量のコミットの書き換えを機械的に行いたい場合 (メールアドレスを一括変更したりすべてのコミットからあるファイルを削除したりなど) に使うものです。そのためのコマンドが `filter-branch` です。これは歴史を大規模にばさっと書き換えることができるものなので、プロジェクトを一般に公開した後や書き換え対象のコミットを元にしてだれかが作業を始めている場合はまず使うことはありません。しかし、これは非常に便利なものでもあります。一般的な使用例をいくつか説明するので、それをもとにこの機能を使いこなせる場面を考えてみましょう。
703
+
704
+ #### 全コミットからのファイルの削除 ####
705
+
706
+ これは、相当よくあることでしょう。誰かが不注意で `git add .` をした結果、巨大なバイナリファイルが間違えてコミットされてしまったとしましょう。これを何とか削除してしまいたいものです。あるいは、間違ってパスワードを含むファイルをコミットしてしまったとしましょう。このプロジェクトをオープンソースにしたいと思ったときに困ります。`filter-branch` は、こんな場合に歴史全体を洗うために使うツールです。passwords.txt というファイルを歴史から完全に抹殺してしまうには、`filter-branch` の `--tree-filter` オプションを使います。
707
+
708
+ $ git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
709
+ Rewrite 6b9b3cf04e7c5686a9cb838c3f36a8cb6a0fc2bd (21/21)
710
+ Ref 'refs/heads/master' was rewritten
711
+
712
+ `--tree-filter` オプションは、プロジェクトの各チェックアウトに対して指定したコマンドを実行し、結果を再コミットします。この場合は、すべてのスナップショットから passwords.txt というファイルを削除します。間違えてコミットしてしまったエディタのバックアップファイルを削除するには、`git filter-branch --tree-filter "rm -f *~" HEAD` のように実行します。
713
+
714
+ Git がツリーを書き換えてコミットし、ブランチのポインタを末尾に移動させる様子がごらんいただけるでしょう。この作業は、まずはテスト用ブランチで実行してから結果をよく吟味し、それから master ブランチに適用することをおすすめします。`filter-branch` をすべてのブランチで実行するには、このコマンドに `--all` を渡します。
715
+
716
+ #### サブディレクトリを新たなルートへ ####
717
+
718
+ 別のソース管理システムからのインポートを終えた後、無意味なサブディレクトリ (trunk、tags など) が残っている状態を想定しましょう。すべてのコミットの `trunk` ディレクトリを新たなプロジェクトルートとしたい場合にも、`filter-branch` が助けになります。
719
+
720
+ $ git filter-branch --subdirectory-filter trunk HEAD
721
+ Rewrite 856f0bf61e41a27326cdae8f09fe708d679f596f (12/12)
722
+ Ref 'refs/heads/master' was rewritten
723
+
724
+ これで、新たなプロジェクトルートはそれまで `trunk` ディレクトリだった場所になります。Git は、このサブディレクトリに影響を及ぼさないコミットを自動的に削除します。
725
+
726
+ #### メールアドレスの一括変更 ####
727
+
728
+ もうひとつよくある例としては、「作業を始める前に `git config` で名前とメールアドレスを設定することを忘れていた」とか「業務で開発したプロジェクトをオープンソースにするにあたって、職場のメールアドレスをすべて個人アドレスに変更したい」などがあります。どちらの場合についても、複数のコミットのメールアドレスを一括で変更することになりますが、これも `filter-branch` ですることができます。注意して、あなたのメールアドレスのみを変更しなければなりません。そこで、`--commit-filter` を使います。
729
+
730
+ $ git filter-branch --commit-filter '
731
+ if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
732
+ then
733
+ GIT_AUTHOR_NAME="Scott Chacon";
734
+ GIT_AUTHOR_EMAIL="schacon@example.com";
735
+ git commit-tree "$@";
736
+ else
737
+ git commit-tree "$@";
738
+ fi' HEAD
739
+
740
+ これで、すべてのコミットであなたのアドレスを新しいものに書き換えます。コミットにはその親の SHA-1 値が含まれるので、このコマンドは (マッチするメールアドレスが存在するものだけではなく) すべてのコミットを書き換えます。
741
+
742
+ ## Git によるデバッグ ##
743
+
744
+ Git には、プロジェクトで発生した問題をデバッグするためのツールも用意されています。Git はほとんどあらゆる種類のプロジェクトで使えるように設計されているので、このツールも非常に汎用的なものです。しかし、バグを見つけたり不具合の原因を探したりするための助けとなるでしょう。
745
+
746
+ ### ファイルの注記 ###
747
+
748
+ コードのバグを追跡しているときに「それが、いつどんな理由で追加されたのか」が知りたくなることがあるでしょう。そんな場合にもっとも便利なのが、ファイルの注記です。これは、ファイルの各行について、その行を最後に更新したのがどのコミットかを表示します。もしコードの中の特定のメソッドにバグがあることを見つけたら、そのファイルを `git blame` しましょう。そうすれば、そのメソッドの各行がいつ誰によって更新されたのかがわかります。この例では、`-L` オプションを使って 12 行目から 22 行目までに出力を限定しています。
749
+
750
+ $ git blame -L 12,22 simplegit.rb
751
+ ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 12) def show(tree = 'master')
752
+ ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 13) command("git show #{tree}")
753
+ ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 14) end
754
+ ^4832fe2 (Scott Chacon 2008-03-15 10:31:28 -0700 15)
755
+ 9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 16) def log(tree = 'master')
756
+ 79eaf55d (Scott Chacon 2008-04-06 10:15:08 -0700 17) command("git log #{tree}")
757
+ 9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 18) end
758
+ 9f6560e4 (Scott Chacon 2008-03-17 21:52:20 -0700 19)
759
+ 42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 20) def blame(path)
760
+ 42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 21) command("git blame #{path}")
761
+ 42cf2861 (Magnus Chacon 2008-04-13 10:45:01 -0700 22) end
762
+
763
+ 最初の項目は、その行を最後に更新したコミットの SHA-1 の一部です。次のふたつの項目は、そのコミットから抽出した作者情報とコミット日時です。これで、いつ誰がその行を更新したのかが簡単にわかります。それに続いて、行番号とファイルの中身が表示されます。`^4832fe2` のコミットに関する行に注目しましょう。これらの行は、ファイルが最初にコミットされたときのままであることを表します。このコミットはファイルがプロジェクトに最初に追加されたときのものであり、これらの行はそれ以降変更されていません。これはちょっと戸惑うかも知れません。Git では、これまで紹介してきただけで少なくとも三種類以上の意味で `^` を使っていますからね。しかし、ここではそういう意味になるのです。
764
+
765
+ Git のすばらしいところのひとつに、ファイルのリネームを明示的には追跡しないということがあります。スナップショットだけを記録し、もしリネームされていたのなら暗黙のうちにそれを検出します。この機能の興味深いところは、ファイルのリネームだけでなくコードの移動についても検出できるということです。`git blame` に `-C` を渡すと Git はそのファイルを解析し、別のところからコピーされたコード片がないかどうかを探します。最近私は `GITServerHandler.m` というファイルをリファクタリングで複数のファイルに分割しました。そのうちのひとつが `GITPackUpload.m` です。ここで `-C` オプションをつけて `GITPackUpload.m` を調べると、コードのどの部分をどのファイルからコピーしたのかを知ることができます。
766
+
767
+ $ git blame -C -L 141,153 GITPackUpload.m
768
+ f344f58d GITServerHandler.m (Scott 2009-01-04 141)
769
+ f344f58d GITServerHandler.m (Scott 2009-01-04 142) - (void) gatherObjectShasFromC
770
+ f344f58d GITServerHandler.m (Scott 2009-01-04 143) {
771
+ 70befddd GITServerHandler.m (Scott 2009-03-22 144) //NSLog(@"GATHER COMMI
772
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 145)
773
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 146) NSString *parentSha;
774
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 147) GITCommit *commit = [g
775
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 148)
776
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 149) //NSLog(@"GATHER COMMI
777
+ ad11ac80 GITPackUpload.m (Scott 2009-03-24 150)
778
+ 56ef2caf GITServerHandler.m (Scott 2009-01-05 151) if(commit) {
779
+ 56ef2caf GITServerHandler.m (Scott 2009-01-05 152) [refDict setOb
780
+ 56ef2caf GITServerHandler.m (Scott 2009-01-05 153)
781
+
782
+ これはほんとうに便利です。通常は、そのファイルがコピーされたときのコミットを知ることになります。コピー先のファイルにおいて最初にその行をさわったのが、その内容をコピーしてきたときだからです。Git は、その行が本当に書かれたコミットがどこであったのかを (たとえ別のファイルであったとしても) 教えてくれるのです。
783
+
784
+ ### 二分探索 ###
785
+
786
+ ファイルの注記を使えば、その問題がどの時点で始まったのかを知ることができます。何がおかしくなったのかがわからず、最後にうまく動作していたときから何十何百ものコミットが行われている場合などは、`git bisect` に頼ることになるでしょう。`bisect` コマンドはコミットの歴史に対して二分探索を行い、どのコミットで問題が混入したのかを可能な限り手早く見つけ出せるようにします。
787
+
788
+ 自分のコードをリリースして運用環境にプッシュしたあとに、バグ報告を受け取ったと仮定しましょう。そのバグは開発環境では再現せず、なぜそんなことになるのか想像もつきません。コードをよく調べて問題を再現させることはできましたが、何が悪かったのかがわかりません。こんな場合に、二分探索で原因を特定することができます。まず、`git bisect start` を実行します。そして次に `git bisect bad` を使って、現在のコミットが壊れた状態であることをシステムに伝えます。次に、まだ壊れていなかったとわかっている直近のコミットを `git bisect good [good_commit]` で伝えます。
789
+
790
+ $ git bisect start
791
+ $ git bisect bad
792
+ $ git bisect good v1.0
793
+ Bisecting: 6 revisions left to test after this
794
+ [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo
795
+
796
+ Git は、まだうまく動いていたと指定されたコミット (v1.0) と現在の壊れたバージョンの間には 12 のコミットがあるということを検出しました。そして、そのちょうど真ん中にあるコミットをチェックアウトしました。ここでテストを実行すれば、このコミットで同じ問題が発生するかどうかがわかります。もし問題が発生したなら、実際に問題が混入したのはそれより前のコミットだということになります。そうでなければ、それ以降のコミットで問題が混入したのでしょう。ここでは、問題が発生しなかったものとします。`git bisect good` で Git にその旨を伝え、旅を続けましょう。
797
+
798
+ $ git bisect good
799
+ Bisecting: 3 revisions left to test after this
800
+ [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing
801
+
802
+ また別のコミットがやってきました。先ほど調べたコミットと「壊れている」と伝えたコミットの真ん中にあるものです。ふたたびテストを実行し、今度はこのコミットで問題が再現したものとします。それを Git に伝えるには `git bisect bad` を使います。
803
+
804
+ $ git bisect bad
805
+ Bisecting: 1 revisions left to test after this
806
+ [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table
807
+
808
+ このコミットはうまく動きました。というわけで、問題が混入したコミットを特定するための情報がこれですべて整いました。Git は問題が混入したコミットの SHA-1 を示し、そのコミット情報とどのファイルが変更されたのかを表示します。これを使って、いったい何が原因でバグが発生したのかを突き止めます。
809
+
810
+ $ git bisect good
811
+ b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit
812
+ commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04
813
+ Author: PJ Hyett <pjhyett@example.com>
814
+ Date: Tue Jan 27 14:48:32 2009 -0800
815
+
816
+ secure this thing
817
+
818
+ :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730
819
+ f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config
820
+
821
+ 原因がわかったら、作業を始める前に `git bisect reset` を実行して HEAD を作業前の状態に戻さなければなりません。そうしないと面倒なことになってしまいます。
822
+
823
+ $ git bisect reset
824
+
825
+ この強力なツールを使えば、何百ものコミットの中からバグの原因となるコミットを数分で見つけだせるようになります。実際、プロジェクトが正常なときに 0 を返してどこかおかしいときに 0 以外を返すスクリプトを用意しておけば、`git bisect` を完全に自動化することもできます。まず、先ほどと同じく、壊れているコミットと正しく動作しているコミットを指定します。これは `bisect start` コマンドで行うこともできます。まず最初に壊れているコミット、そしてその後に正しく動作しているコミットを指定します。
826
+
827
+ $ git bisect start HEAD v1.0
828
+ $ git bisect run test-error.sh
829
+
830
+ こうすると、チェックアウトされたコミットに対して自動的に `test-error.sh` を実行し、壊れる原因となるコミットを見つけ出すまで自動的に処理を続けます。`make` や `make tests`、その他自動テストを実行するためのプログラムなどをここで実行させることもできます。
831
+
832
+ ## サブモジュール ##
833
+
834
+ あるプロジェクトで作業をしているときに、プロジェクト内で別のプロジェクトを使わなければならなくなることがよくあります。サードパーティが開発しているライブラリや、自身が別途開発していて複数の親プロジェクトから利用しているライブラリなどがそれにあたります。こういったときに出てくるのが「ふたつのプロジェクトはそれぞれ別のものとして管理したい。だけど、一方を他方の一部としても使いたい」という問題です。
835
+
836
+ 例を考えてみましょう。ウェブサイトを制作しているあなたは、Atom フィードを作成することになりました。Atom 生成コードを自前で書くのではなく、ライブラリを使うことに決めました。この場合、CPAN や gem などの共有ライブラリからコードをインクルードするか、ソースコードそのものをプロジェクトのツリーに取り込むかのいずれかが必要となります。ライブラリをインクルードする方式の問題は、ライブラリのカスタマイズが困難であることと配布が面倒になるということです。すべてのクライアントにそのライブラリを導入させなければなりません。コードをツリーに取り込む方式の問題は、手元でコードに手を加えてしまうと本家の更新に追従しにくくなるということです。
837
+
838
+ Git では、サブモジュールを使ってこの問題に対応します。サブモジュールを使うと、ある Git リポジトリを別の Git リポジトリのサブディレクトリとして扱うことができるようになります。これで、別のリポジトリをプロジェクト内にクローンしても自分のコミットは別管理とすることができるようになります。
839
+
840
+ ### サブモジュールの作り方 ###
841
+
842
+ Rack ライブラリ (Ruby のウェブサーバーゲートウェイインターフェイス) を自分のプロジェクトに取り込むことになったとしましょう。手元で変更を加えるかもしれませんが、本家で更新があった場合にはそれを取り込み続けるつもりです。まず最初にしなければならないことは、外部のリポジトリをサブディレクトリにクローンすることです。外部のプロジェクトをサブモジュールとして追加するには `git submodule add` コマンドを使用します。
843
+
844
+ $ git submodule add git://github.com/chneukirchen/rack.git rack
845
+ Initialized empty Git repository in /opt/subtest/rack/.git/
846
+ remote: Counting objects: 3181, done.
847
+ remote: Compressing objects: 100% (1534/1534), done.
848
+ remote: Total 3181 (delta 1951), reused 2623 (delta 1603)
849
+ Receiving objects: 100% (3181/3181), 675.42 KiB | 422 KiB/s, done.
850
+ Resolving deltas: 100% (1951/1951), done.
851
+
852
+ これで、プロジェクト内の `rack` サブディレクトリに Rack プロジェクトが取り込まれました。このサブディレクトリに入って変更を加えたり、書き込み権限のあるリモートリポジトリを追加してそこに変更をプッシュしたり、本家のリポジトリの内容を取得してマージしたり、さまざまなことができるようになります。サブモジュールを追加した直後に `git status` を実行すると、二つのものが見られます。
853
+
854
+ $ git status
855
+ # On branch master
856
+ # Changes to be committed:
857
+ # (use "git reset HEAD <file>..." to unstage)
858
+ #
859
+ # new file: .gitmodules
860
+ # new file: rack
861
+ #
862
+
863
+ まず気づくのが `.gitmodules` ファイルです。この設定ファイルには、プロジェクトの URL とそれを取り込んだローカルサブディレクトリの対応が格納されています。
864
+
865
+ $ cat .gitmodules
866
+ [submodule "rack"]
867
+ path = rack
868
+ url = git://github.com/chneukirchen/rack.git
869
+
870
+ 複数のサブモジュールを追加した場合は、このファイルに複数のエントリが書き込まれます。このファイルもまた他のファイルと同様にバージョン管理下に置かれることに注意しましょう。`.gitignore` ファイルと同じことです。プロジェクトの他のファイルと同様、このファイルもプッシュやプルの対象となります。プロジェクトをクローンした人は、このファイルを使ってサブモジュールの取得元を知ることになります。
871
+
872
+ `git status` の出力に、もうひとつ rack というエントリが含まれています。これに対して `git diff` を実行すると、ちょっと興味深い結果が得られます。
873
+
874
+ $ git diff --cached rack
875
+ diff --git a/rack b/rack
876
+ new file mode 160000
877
+ index 0000000..08d709f
878
+ --- /dev/null
879
+ +++ b/rack
880
+ @@ -0,0 +1 @@
881
+ +Subproject commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
882
+
883
+ `rack` は作業ディレクトリ内にあるサブディレクトリですが、Git はそれがサブモジュールであるとみなし、あなたがそのディレクトリにいない限りその中身を追跡することはありません。そのかわりに、Git はこのサブディレクトリを元のプロジェクトの特定のコミットとして記録します。このサブディレクトリ内に変更を加えてコミットすると、親プロジェクト側で HEAD が変わったことを検知し、実際の作業内容をコミットとして記録します。そうすることで、他の人がこのプロジェクトをクローンしたときに正しく環境を作れるようになります。
884
+
885
+ ここがサブモジュールのポイントです。サブモジュールは、それがある場所の実際のコミットとして記録され、`master` やその他の参照として記録することはできません。
886
+
887
+ コミットすると、このようになります。
888
+
889
+ $ git commit -m 'first commit with submodule rack'
890
+ [master 0550271] first commit with submodule rack
891
+ 2 files changed, 4 insertions(+), 0 deletions(-)
892
+ create mode 100644 .gitmodules
893
+ create mode 160000 rack
894
+
895
+ rack エントリのモードが 160000 となったことに注目しましょう。これは Git における特別なモードで、サブディレクトリやファイルではなくディレクトリエントリとしてこのコミットを記録したことを意味します。
896
+
897
+ `rack` ディレクトリを独立したプロジェクトとして扱い、ときどき親プロジェクトをアップデートして親プロジェクトの最新コミットにポインタを移動させることができます。すべての Git コマンドが、これらふたつのディレクトリで独立して使用可能です。
898
+
899
+ $ git log -1
900
+ commit 0550271328a0038865aad6331e620cd7238601bb
901
+ Author: Scott Chacon <schacon@gmail.com>
902
+ Date: Thu Apr 9 09:03:56 2009 -0700
903
+
904
+ first commit with submodule rack
905
+ $ cd rack/
906
+ $ git log -1
907
+ commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
908
+ Author: Christian Neukirchen <chneukirchen@gmail.com>
909
+ Date: Wed Mar 25 14:49:04 2009 +0100
910
+
911
+ Document version change
912
+
913
+ ### サブモジュールを含むプロジェクトのクローン ###
914
+
915
+ ここでは、内部にサブモジュールを含むプロジェクトをクローンしてみます。すると、サブモジュールを含むディレクトリは取得できますがその中にはまだ何もファイルが入っていません。
916
+
917
+ $ git clone git://github.com/schacon/myproject.git
918
+ Initialized empty Git repository in /opt/myproject/.git/
919
+ remote: Counting objects: 6, done.
920
+ remote: Compressing objects: 100% (4/4), done.
921
+ remote: Total 6 (delta 0), reused 0 (delta 0)
922
+ Receiving objects: 100% (6/6), done.
923
+ $ cd myproject
924
+ $ ls -l
925
+ total 8
926
+ -rw-r--r-- 1 schacon admin 3 Apr 9 09:11 README
927
+ drwxr-xr-x 2 schacon admin 68 Apr 9 09:11 rack
928
+ $ ls rack/
929
+ $
930
+
931
+ `rack` ディレクトリは存在しますが、中身がからっぽです。ここで、ふたつのコマンドを実行しなければなりません。まず `git submodule init` でローカルの設定ファイルを初期化し、次に `git submodule update` でプロジェクトからのデータを取得し、親プロジェクトで指定されている適切なコミットをチェックアウトします。
932
+
933
+ $ git submodule init
934
+ Submodule 'rack' (git://github.com/chneukirchen/rack.git) registered for path 'rack'
935
+ $ git submodule update
936
+ Initialized empty Git repository in /opt/myproject/rack/.git/
937
+ remote: Counting objects: 3181, done.
938
+ remote: Compressing objects: 100% (1534/1534), done.
939
+ remote: Total 3181 (delta 1951), reused 2623 (delta 1603)
940
+ Receiving objects: 100% (3181/3181), 675.42 KiB | 173 KiB/s, done.
941
+ Resolving deltas: 100% (1951/1951), done.
942
+ Submodule path 'rack': checked out '08d709f78b8c5b0fbeb7821e37fa53e69afcf433'
943
+
944
+ これで、サブディレクトリ `rack` の中身が先ほどコミットしたときとまったく同じ状態になりました。別の開発者が rack のコードを変更してコミットしたときにそれを取り込んでマージするには、もう少し付け加えます。
945
+
946
+ $ git merge origin/master
947
+ Updating 0550271..85a3eee
948
+ Fast forward
949
+ rack | 2 +-
950
+ 1 files changed, 1 insertions(+), 1 deletions(-)
951
+ [master*]$ git status
952
+ # On branch master
953
+ # Changes not staged for commit:
954
+ # (use "git add <file>..." to update what will be committed)
955
+ # (use "git checkout -- <file>..." to discard changes in working directory)
956
+ #
957
+ # modified: rack
958
+ #
959
+
960
+ このマージで、サブモジュールが指すポインタの位置が変わりました。しかしサブモジュールディレクトリ内のコードは更新されていません。つまり、作業ディレクトリ内でダーティな状態になっています。
961
+
962
+ $ git diff
963
+ diff --git a/rack b/rack
964
+ index 6c5e70b..08d709f 160000
965
+ --- a/rack
966
+ +++ b/rack
967
+ @@ -1 +1 @@
968
+ -Subproject commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
969
+ +Subproject commit 08d709f78b8c5b0fbeb7821e37fa53e69afcf433
970
+
971
+ これは、サブモジュールのポインタが指す位置と実際のサブモジュールディレクトリの中身が異なるからです。これを修正するには、ふたたび `git submodule update` を実行します。
972
+
973
+ $ git submodule update
974
+ remote: Counting objects: 5, done.
975
+ remote: Compressing objects: 100% (3/3), done.
976
+ remote: Total 3 (delta 1), reused 2 (delta 0)
977
+ Unpacking objects: 100% (3/3), done.
978
+ From git@github.com:schacon/rack
979
+ 08d709f..6c5e70b master -> origin/master
980
+ Submodule path 'rack': checked out '6c5e70b984a60b3cecd395edd5b48a7575bf58e0'
981
+
982
+ サブモジュールの変更をプロジェクトに取り込んだときには、毎回これをしなければなりません。ちょっと奇妙ですが、これでうまく動作します。
983
+
984
+ よくある問題が、開発者がサブモジュール内でローカルに変更を加えたけれどそれを公開サーバーにプッシュしていないときに起こります。ポインタの指す先を非公開の状態にしたまま、それを親プロジェクトにプッシュしてしまうと、他の開発者が `git submodule update` をしたときにサブモジュールが参照するコミットを見つけられなくなります。そのコミットは最初の開発者の環境にしか存在しないからです。この状態になると、次のようなエラーとなります。
985
+
986
+ $ git submodule update
987
+ fatal: reference isn’t a tree: 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
988
+ Unable to checkout '6c5e70b984a60b3cecd395edd5ba7575bf58e0' in submodule path 'rack'
989
+
990
+ サブモジュールを最後に更新したのがいったい誰なのかを突き止めなければなりません。
991
+
992
+ $ git log -1 rack
993
+ commit 85a3eee996800fcfa91e2119372dd4172bf76678
994
+ Author: Scott Chacon <schacon@gmail.com>
995
+ Date: Thu Apr 9 09:19:14 2009 -0700
996
+
997
+ added a submodule reference I will never make public. hahahahaha!
998
+
999
+ 犯人がわかったら、メールで彼に怒鳴りつけてやりましょう。
1000
+
1001
+ ### 親プロジェクト ###
1002
+
1003
+ 時には、大規模なプロジェクトのサブディレクトリから今自分がいるチームに応じた組み合わせを取得したくなることもあるでしょう。これは、CVS や Subversion から移行した場合によくあることでしょう。モジュールを定義したりサブディレクトリのコレクションを定義していたりといったかつてのワークフローをそのまま維持したいというような状況です。
1004
+
1005
+ Git でこれと同じことをするためのよい方法は、それぞれのサブディレクトリを別々の Git リポジトリにして、それらのサブモジュールとして含む親プロジェクトとなる Git リポジトリを作ることです。この方式の利点は、親プロジェクトのタグやブランチを活用してプロジェクト間の関係をより細やかに定義できることです。
1006
+
1007
+ ### サブモジュールでの問題 ###
1008
+
1009
+ しかし、サブモジュールを使っているとなにかしらちょっとした問題が出てくるものです。まず、サブモジュールのディレクトリで作業をするときはいつも以上に注意深くならなければなりません。`git submodule update` を実行すると、プロジェクトの特定のバージョンをチェックアウトしますが、それはブランチの中にあるものではありません。これを、切り離された HEAD (detached HEAD) と呼びます。つまり、HEAD が何らかの参照ではなく直接特定のコミットを指している状態です。通常は、HEAD が切り離された状態で作業をしようとは思わないでしょう。手元の変更が簡単に失われてしまうからです。最初に `submodule update` し、作業用のブランチを作らずにサブモジュールディレクトリ内にコミットし、`git submodule update` を再び実行すると、親プロジェクトでコミットが何もなくても Git は手元の変更を断りなく上書きしてしまいます。技術的な意味では手元の作業は失われたわけではないのですが、それを指すブランチが存在しない以上、先ほどの作業を取り戻すのは困難です。
1010
+
1011
+ この問題を回避するには、サブモジュールのディレクトリで作業をするときに `git checkout -b work` などとしてブランチを作っておきます。次にサブモジュールを更新するときにあなたの作業は消えてしまいますが、少なくとも元に戻すためのポインタは残っています。
1012
+
1013
+ サブモジュールを含むブランチを切り替えるのは、これまた用心が必要です。新しいブランチを作成してそこにサブモジュールを追加し、サブモジュールを含まないブランチに戻ったとしましょう。そこには、サブモジュールのディレクトリが「追跡されていないディレクトリ」として残ったままになります。
1014
+
1015
+ $ git checkout -b rack
1016
+ Switched to a new branch "rack"
1017
+ $ git submodule add git@github.com:schacon/rack.git rack
1018
+ Initialized empty Git repository in /opt/myproj/rack/.git/
1019
+ ...
1020
+ Receiving objects: 100% (3184/3184), 677.42 KiB | 34 KiB/s, done.
1021
+ Resolving deltas: 100% (1952/1952), done.
1022
+ $ git commit -am 'added rack submodule'
1023
+ [rack cc49a69] added rack submodule
1024
+ 2 files changed, 4 insertions(+), 0 deletions(-)
1025
+ create mode 100644 .gitmodules
1026
+ create mode 160000 rack
1027
+ $ git checkout master
1028
+ Switched to branch "master"
1029
+ $ git status
1030
+ # On branch master
1031
+ # Untracked files:
1032
+ # (use "git add <file>..." to include in what will be committed)
1033
+ #
1034
+ # rack/
1035
+
1036
+ これをどこか別の場所に移すか、削除しなければなりません。いずれにせよ、先ほどのブランチに戻ったときには改めてクローンしなおさなければならず、ローカルでの変更やプッシュしていないブランチは失われてしまうことになります。
1037
+
1038
+ 最後にもうひとつ、多くの人がハマるであろう点を指摘しておきましょう。これは、サブディレクトリからサブモジュールへ切り替えるときに起こることです。プロジェクト内で追跡しているファイルをサブモジュール内に移動したくなったとしましょう。よっぽど注意しないと、Git に怒られてしまいます。rack のファイルをプロジェクト内のサブディレクトリで管理しており、それをサブモジュールに切り替えたくなったとしましょう。サブディレクトリをいったん削除してから `submodule add` と実行すると、Git に怒鳴りつけられてしまいます。
1039
+
1040
+ $ rm -Rf rack/
1041
+ $ git submodule add git@github.com:schacon/rack.git rack
1042
+ 'rack' already exists in the index
1043
+
1044
+ まず最初に `rack` ディレクトリをアンステージしなければなりません。それからだと、サブモジュールを追加することができます。
1045
+
1046
+ $ git rm -r rack
1047
+ $ git submodule add git@github.com:schacon/rack.git rack
1048
+ Initialized empty Git repository in /opt/testsub/rack/.git/
1049
+ remote: Counting objects: 3184, done.
1050
+ remote: Compressing objects: 100% (1465/1465), done.
1051
+ remote: Total 3184 (delta 1952), reused 2770 (delta 1675)
1052
+ Receiving objects: 100% (3184/3184), 677.42 KiB | 88 KiB/s, done.
1053
+ Resolving deltas: 100% (1952/1952), done.
1054
+
1055
+ これをどこかのブランチで行ったとしましょう。そこから、(まだサブモジュールへの切り替えがすんでおらず実際のツリーがある状態の) 別のブランチに切り替えようとすると、このようなエラーになります。
1056
+
1057
+ $ git checkout master
1058
+ error: Untracked working tree file 'rack/AUTHORS' would be overwritten by merge.
1059
+
1060
+ いったん `rack` サブモジュールのディレクトリを別の場所に追い出してからでないと、サブモジュールを持たないブランチに切り替えることはできません。
1061
+
1062
+ $ mv rack /tmp/
1063
+ $ git checkout master
1064
+ Switched to branch "master"
1065
+ $ ls
1066
+ README rack
1067
+
1068
+ さて、戻ってきたら、空っぽの `rack` ディレクトリが得られました。ここで `git submodule update` を実行して再クローンするか、あるいは `/tmp/rack` ディレクトリを書き戻します。
1069
+
1070
+ ## サブツリーマージ ##
1071
+
1072
+ サブモジュールの仕組みに関する問題を見てきました。今度は同じ問題を解決するための別の方法を見ていきましょう。Git でマージを行うときには、何をマージしなければならないのかを Git がまず調べてそれに応じた適切なマージ手法を選択します。ふたつのブランチをマージするときに Git が使うのは、_再帰 (recursive)_ 戦略です。三つ以上のブランチをマージするときには、Git は _たこ足 (octopus)_ 戦略を選択します。どちらの戦略を使うかは、Git が自動的に選択します。再帰戦略は複雑な三方向のマージ (共通の先祖が複数あるなど) もこなせますが、ふたつのブランチしか処理できないからです。たこ足マージは三つ以上のブランチを扱うことができますが、難しいコンフリクトを避けるためにより慎重になります。そこで、三つ以上のブランチをマージするときのデフォルトの戦略として選ばれています。しかし、それ以外にも選べる戦略があります。そのひとつが _サブツリー (subtree)_ マージで、これを使えば先ほどのサブプロジェクト問題に対応することができます。先ほどのセクションと同じような rack の取り込みを、サブツリーマージを用いて行う方法を紹介しましょう。
1073
+
1074
+ サブツリーマージの考え方は、ふたつのプロジェクトがあるときに一方のプロジェクトをもうひとつのプロジェクトのサブディレクトリに位置づけたりその逆を行ったりするというものです。サブツリーマージを指定すると、Git は一方が他方のサブツリーであることを理解して適切にマージを行います。驚くべきことです。
1075
+
1076
+ まずは Rack アプリケーションをプロジェクトに追加します。つまり、Rack プロジェクトをリモート参照として自分のプロジェクトに追加し、そのブランチにチェックアウトします。
1077
+
1078
+ $ git remote add rack_remote git@github.com:schacon/rack.git
1079
+ $ git fetch rack_remote
1080
+ warning: no common commits
1081
+ remote: Counting objects: 3184, done.
1082
+ remote: Compressing objects: 100% (1465/1465), done.
1083
+ remote: Total 3184 (delta 1952), reused 2770 (delta 1675)
1084
+ Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, done.
1085
+ Resolving deltas: 100% (1952/1952), done.
1086
+ From git@github.com:schacon/rack
1087
+ * [new branch] build -> rack_remote/build
1088
+ * [new branch] master -> rack_remote/master
1089
+ * [new branch] rack-0.4 -> rack_remote/rack-0.4
1090
+ * [new branch] rack-0.9 -> rack_remote/rack-0.9
1091
+ $ git checkout -b rack_branch rack_remote/master
1092
+ Branch rack_branch set up to track remote branch refs/remotes/rack_remote/master.
1093
+ Switched to a new branch "rack_branch"
1094
+
1095
+ これで Rack プロジェクトのルートが `rack_branch` ブランチに取得でき、あなたのプロジェクトが `master` ブランチにある状態になりました。まずどちらかをチェックアウトしてそれからもう一方に移ると、それぞれ別のプロジェクトルートとなっていることがわかります。
1096
+
1097
+ $ ls
1098
+ AUTHORS KNOWN-ISSUES Rakefile contrib lib
1099
+ COPYING README bin example test
1100
+ $ git checkout master
1101
+ Switched to branch "master"
1102
+ $ ls
1103
+ README
1104
+
1105
+ Rack プロジェクトを `master` プロジェクトのサブディレクトリとして取り込みたくなったときには、`git read-tree` を使います。`read-tree` とその仲間たちについては第 9 章で詳しく説明します。現時点では、とりあえず「あるブランチのルートツリーを読み込んで、それを現在のステージングエリアと作業ディレクトリに書き込むもの」だと認識しておけばよいでしょう。まず `master` ブランチに戻り、`rack_branch` ブランチの内容を `master` ブランチの `rack` サブディレクトリに取り込みます。
1106
+
1107
+ $ git read-tree --prefix=rack/ -u rack_branch
1108
+
1109
+ これをコミットすると、Rack のファイルをすべてサブディレクトリに取り込んだようになります。そう、まるで tarball からコピーしたかのような状態です。おもしろいのは、あるブランチでの変更を簡単に別のブランチにマージできるということです。もし Rack プロジェクトが更新されたら、そのブランチに切り替えてプルするだけで本家の変更を取得できます。
1110
+
1111
+ $ git checkout rack_branch
1112
+ $ git pull
1113
+
1114
+ これで、変更を master ブランチにマージできるようになりました。`git merge -s subtree` を使えばうまく動作します。が、Git は歴史もともにマージしようとします。おそらくこれはお望みの動作ではないでしょう。変更をプルしてコミットメッセージを埋めるには、戦略を指定するオプション `-s subtree` のほかに `--squash` オプションと `--no-commit` オプションを使います。
1115
+
1116
+ $ git checkout master
1117
+ $ git merge --squash -s subtree --no-commit rack_branch
1118
+ Squash commit -- not updating HEAD
1119
+ Automatic merge went well; stopped before committing as requested
1120
+
1121
+ Rack プロジェクトでのすべての変更がマージされ、ローカルにコミットできる準備が整いました。この逆を行うこともできます。master ブランチの `rack` サブディレクトリで変更した内容を後で `rack_branch` ブランチにマージし、それをメンテナに投稿したり本家にプッシュしたりといったことも可能です。
1122
+
1123
+ `rack` サブディレクトリの内容と `rack_branch` ブランチのコードの差分を取得する (そして、マージしなければならない内容を知る) には、通常の `diff` コマンドを使うことはできません。そのかわりに、`git diff-tree` で比較対象のブランチを指定します。
1124
+
1125
+ $ git diff-tree -p rack_branch
1126
+
1127
+ あるいは、`rack` サブディレクトリの内容と前回取得したときのサーバーの `master` ブランチとを比較するには、次のようにします。
1128
+
1129
+ $ git diff-tree -p rack_remote/master
1130
+
1131
+ ## まとめ ##
1132
+
1133
+ さまざまな高度な道具を使い、コミットやステージングエリアをより細やかに操作できる方法をまとめました。何か問題が起こったときには、いつ誰がどのコミットでそれを仕込んだのかを容易に見つけられるようになったことでしょう。また、プロジェクトの中で別のプロジェクトを使いたくなったときのための方法もいくつか紹介しました。Git を使った日々のコマンドラインでの作業の大半を、自信を持ってできるようになったことでしょう。