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,978 @@
1
+ # Git Internamente #
2
+
3
+ Você pode ter pulado para este capítulo a partir de um capítulo anterior, ou você pode ter chegado aqui depois de ler o resto do livro — em ambos os casos, este é o lugar onde você vai conhecer o funcionamento interno e implementação do Git. Descobri que aprender esta informação era de fundamental importância para a compreensão de quanto o Git é útil e poderoso, mas outros argumentaram que pode ser confuso e desnecessariamente complexo para iniciantes. Assim, eu fiz essa discussão o último capítulo do livro para que você possa lê-lo mais cedo ou mais tarde, em seu processo de aprendizagem. Deixo isso para você decidir.
4
+
5
+ Agora que você está aqui, vamos começar. Primeiro, se ainda não for claro, o Git é fundamentalmente um sistema de arquivos de conteúdo endereçavel com uma interface de usuário VCS escrito em cima dele. Você vai aprender mais sobre o que isto significa daqui a pouco.
6
+
7
+ Nos primeiros dias do Git (principalmente antes da versão 1.5), a interface de usuário era muito mais complexa, pois enfatizou este sistema de arquivos, em vez de um VCS. Nos últimos anos, a interface do usuário tem sido aperfeiçoada até que ela se torne tão limpa e fácil de usar como qualquer outro sistema; mas, muitas vezes, o estereótipo persiste sobre a UI antiga do Git que era complexa e difícil de aprender.
8
+
9
+ A camada de sistema de arquivos de conteúdo endereçável é incrivelmente interessante, então eu vou falar dela primeiro neste capítulo; então, você vai aprender sobre os mecanismos de transporte e as tarefas de manutenção do repositório.
10
+
11
+ ## Encanamento (Plumbing) e Porcelana (Porcelain) ##
12
+
13
+ Este livro aborda como usar o Git com 30 ou mais verbos como `checkout`, `branch`, `remote`, e assim por diante. Mas como o Git foi pensado inicialmente um conjunto de ferramentas para um VCS, em vez de apenas um VCS amigável, ele tem um grupo de verbos que fazem o trabalho de baixo nível e foram projetados para serem encadeados (usando pipe) no estilo UNIX ou chamados a partir de scripts. Estes comandos são geralmente referidos como comandos de "encanamento" (plumbing), e os comandos mais amigáveis ​​são chamados de comandos "porcelana" (porcelain).
14
+
15
+ Os oito primeiros capítulos do livro tratam quase que exclusivamente com comandos porcelana. Mas, neste capítulo, você estará lidando principalmente com os comandos de nível inferior de encanamento, porque eles te dão acesso aos trabalhos internos do Git e ajudam a demonstrar como e por que o Git faz o que faz. Estes comandos não são destinados a ser usados manualmente na linha de comando, mas sim para serem usados como blocos de construção para novas ferramentas e scripts personalizados.
16
+
17
+ Quando você executa `git init` em um diretório novo ou existente, Git cria o diretório `.git`, que é onde quase tudo que o Git armazena e manipula está localizado. Se você deseja fazer o backup ou clonar seu repositório, copiar este diretório para outro lugar lhe dará quase tudo o que você precisa. Este capítulo inteiro trata basicamente do conteúdo deste diretório. Eis o que ele contém:
18
+
19
+ $ ls
20
+ HEAD
21
+ branches/
22
+ config
23
+ description
24
+ hooks/
25
+ index
26
+ info/
27
+ objects/
28
+ refs/
29
+
30
+ Você pode ver alguns outros arquivos lá, mas este é um novo repositório `git init` — é o que você vê por padrão. O diretório `branches` não é usado por versões mais recentes do Git, e o arquivo `description` só é usado pelo programa gitweb, então não se preocupe com eles. O arquivo `config` contém as opções de configuração específicas do projeto, e o diretório `info` contém um arquivo de exclusão global com padrões ignorados que você não deseja rastrear em um arquivo .gitignore. O diretório `hooks` contém os "hook scripts" de cliente ou servidor, que são discutidos em detalhes no *Capítulo 7*.
31
+
32
+ Isso deixa quatro entradas importantes: os arquivos `HEAD` e `index` e diretórios `objects` e `refs`. Estas são as peças centrais do Git. O diretório `objects` armazena todo o conteúdo do seu banco de dados, o diretório `refs` armazena os ponteiros para objetos de commit (branches), o arquivo `HEAD` aponta para o branch atual, e o arquivo `index` é onde Git armazena suas informações da área de preparação (staging area). Você vai agora ver cada uma dessas seções em detalhes para saber como o Git opera.
33
+
34
+ ## Objetos do Git ##
35
+
36
+ Git é um sistema de arquivos de conteúdo endereçável. O que significa isso?
37
+ Isso significa que o núcleo do Git armazena dados usando um simples mecanismo chave-valor. Você pode inserir qualquer tipo de conteúdo nele, e ele vai retornar uma chave que você pode usar para recuperar o conteúdo a qualquer momento. Para demonstrar, você pode usar o comando de encanamento `hash-object`, pega alguns dados, armazena eles em seu diretório `.git`, e retorna a chave dos dados armazenados. Primeiro, você inicializa um novo repositório Git e verifica se não há nada no diretório `objects`:
38
+
39
+ $ mkdir test
40
+ $ cd test
41
+ $ git init
42
+ Initialized empty Git repository in /tmp/test/.git/
43
+ $ find .git/objects
44
+ .git/objects
45
+ .git/objects/info
46
+ .git/objects/pack
47
+ $ find .git/objects -type f
48
+ $
49
+
50
+ Git inicializou o diretório `objects` e criou os subdiretórios `pack` e `info`, mas não existem arquivos comuns neles. Agora, armazene um texto em seu banco de dados Git:
51
+
52
+ $ echo 'test content' | git hash-object -w --stdin
53
+ d670460b4b4aece5915caf5c68d12f560a9fe3e4
54
+
55
+ O `-w` diz ao `hash-object` para armazenar o objeto; caso contrário, o comando simplesmente diz qual seria a chave. `--stdin` indica ao comando para ler o conteúdo da entrada padrão (stdin); se você não especificar isso, `hash-object` espera um caminho (path) para um arquivo. A saída do comando é uma soma hash de 40 caracteres. Este é o hash SHA-1 — uma soma de verificação do conteúdo que você está armazenando mais um cabeçalho, que você vai entender mais daqui a pouco. Agora você pode ver como o Git armazenou seus dados:
56
+
57
+ $ find .git/objects -type f
58
+ .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
59
+
60
+ Você pode ver um arquivo no diretório `objects`. Isto é como o Git armazena o conteúdo inicialmente — como um único arquivo por parte de conteúdo, nomeado com o checksum SHA-1 do conteúdo e seu cabeçalho. O subdiretório é nomeado com os 2 primeiros caracteres do SHA, e o arquivo é nomeado com os 38 caracteres restantes.
61
+
62
+ Você pode fazer um pull do conteúdo com o comando `cat-file`. Este comando é uma espécie de canivete suíço para inspecionar objetos Git. Passando `-p` para ele instrui o comando `cat-file` a descobrir o tipo de conteúdo e exibi-lo para você:
63
+
64
+ $ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
65
+ test content
66
+
67
+ Agora, você pode adicionar conteúdo no Git e fazer pull dele. Você também pode fazer isso com o conteúdo de arquivos. Por exemplo, você pode fazer algum controle de versão simples em um arquivo. Primeiro, crie um novo arquivo e salve seu conteúdo em seu banco de dados:
68
+
69
+ $ echo 'version 1' > test.txt
70
+ $ git hash-object -w test.txt
71
+ 83baae61804e65cc73a7201a7252750c76066a30
72
+
73
+ Então, escreva algum conteúdo novo no arquivo e salve-o novamente:
74
+
75
+ $ echo 'version 2' > test.txt
76
+ $ git hash-object -w test.txt
77
+ 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
78
+
79
+ Seu banco de dados contém as duas novas versões do arquivo, assim como o primeiro conteúdo que você armazenou lá:
80
+
81
+ $ find .git/objects -type f
82
+ .git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
83
+ .git/objects/83/baae61804e65cc73a7201a7252750c76066a30
84
+ .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
85
+
86
+ Agora você pode reverter o arquivo de volta para a primeira versão
87
+
88
+ $ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt
89
+ $ cat test.txt
90
+ version 1
91
+
92
+ ou a segunda versão:
93
+
94
+ $ git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt
95
+ $ cat test.txt
96
+ version 2
97
+
98
+ Mas, lembrar a chave SHA-1 para cada versão de seu arquivo não é prático; mais ainda, você não está armazenando o nome do arquivo em seu sistema — apenas o conteúdo. Esse tipo de objeto é chamado de blob. Você pode fazer o Git informar o tipo de objeto de qualquer objeto no Git, dada a sua chave SHA-1, com `cat-file -t`:
99
+
100
+ $ git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
101
+ blob
102
+
103
+ ### Objetos Árvore ###
104
+
105
+ O próximo tipo que você verá é o objeto árvore, que resolve o problema de armazenar o nome do arquivo e também permite que você armazene um grupo de arquivos juntos. Git armazena o conteúdo de uma maneira semelhante a um sistema de arquivos UNIX, mas de forma um pouco simplificada. Todo o conteúdo é armazenado como árvore e objetos blob, com árvores correspondendo às entradas de diretório do UNIX e os blobs correspondendo mais ou menos a inodes ou conteúdo de arquivos. Um único objeto árvore contém uma ou mais entradas de árvores, cada uma das quais contém um ponteiro SHA-1 para um blob ou subárvore com seu modo associado, tipo e o nome do arquivo. Por exemplo, a árvore mais recente no projeto simplegit pode parecer algo como isto:
106
+
107
+ $ git cat-file -p master^{tree}
108
+ 100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README
109
+ 100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile
110
+ 040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib
111
+
112
+ A sintaxe `master^{tree}` especifica o objeto árvore que é apontado pelo último commit em seu branch `master`. Observe que o subdiretório `lib` não é um blob, mas sim, um ponteiro para outra árvore:
113
+
114
+ $ git cat-file -p 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0
115
+ 100644 blob 47c6340d6459e05787f644c2447d2595f5d3a54b simplegit.rb
116
+
117
+ Conceitualmente, os dados que o Git está armazenando são algo como mostra a Figura 9-1.
118
+
119
+ Insert 18333fig0901.png
120
+ Figura 9-1. Versão simples do modelo de dados Git.
121
+
122
+ Você pode criar sua própria árvore. Git normalmente cria uma árvore, a partir do estado de sua área de seleção ou índice e escreve um objeto árvore a partir dele. Assim, para criar um objeto árvore, primeiro você tem que criar um índice colocando alguns arquivos na área de seleção (staging area). Para criar um índice com uma única entrada — a primeira versão do seu arquivo text.txt — você pode usar o comando plumbing `update-index`. Você pode usar este comando para adicionar artificialmente a versão anterior do arquivo test.txt em uma nova área de seleção. Você deve passar a opção `--add` porque o arquivo ainda não existe na sua área de seleção (você não tem sequer uma área de seleção criada ainda) e `--cacheinfo` porque o arquivo que você está adicionando não está em seu diretório, mas está em seu banco de dados. Então, você especifica o modo, o SHA-1, e o nome do arquivo:
123
+
124
+ $ git update-index --add --cacheinfo 100644 \
125
+ 83baae61804e65cc73a7201a7252750c76066a30 test.txt
126
+
127
+ Neste caso, você está especificando um modo `100644`, que significa que é um arquivo normal. Outras opções são `100755`, que significa que é um arquivo executável, e `120000`, que especifica um link simbólico. O modo é obtido a partir de modos normais do Unix, mas é muito menos flexível — estes três modos são os únicos que são válidas para arquivos (blobs) no Git (embora outros modos sejam usados ​​para diretórios e submódulos).
128
+
129
+ Agora, você pode usar o comando `write-tree` para escrever a área de seleção em um objeto árvore. Nenhuma opção `-w` é necessária — chamando `write-tree` cria automaticamente um objeto árvore a partir do estado do índice se a árvore ainda não existe:
130
+
131
+ $ git write-tree
132
+ d8329fc1cc938780ffdd9f94e0d364e0ea74f579
133
+ $ git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579
134
+ 100644 blob 83baae61804e65cc73a7201a7252750c76066a30 test.txt
135
+
136
+ Você também pode verificar que este é um objeto árvore:
137
+
138
+ $ git cat-file -t d8329fc1cc938780ffdd9f94e0d364e0ea74f579
139
+ tree
140
+
141
+ Você vai agora criar uma nova árvore com a segunda versão do test.txt e um novo arquivo também:
142
+
143
+ $ echo 'new file' > new.txt
144
+ $ git update-index test.txt
145
+ $ git update-index --add new.txt
146
+
147
+ Sua área de seleção agora tem a nova versão do test.txt bem como o novo arquivo new.txt. Escreva aquela árvore (grave o estado da área de seleção ou índice em um objeto árvore) e veja o que aparece:
148
+
149
+ $ git write-tree
150
+ 0155eb4229851634a0f03eb265b69f5a2d56f341
151
+ $ git cat-file -p 0155eb4229851634a0f03eb265b69f5a2d56f341
152
+ 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
153
+ 100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
154
+
155
+ Note que esta árvore tem entradas de arquivos e também que o SHA de test.txt é a "versão 2" do SHA de antes (`1f7a7a`). Apenas por diversão, você vai adicionar a primeira árvore como um subdiretório nesta árvore. Você pode ler as árvores em sua área de seleção chamando `read-tree`. Neste caso, você pode ler uma árvore existente em sua área de seleção como uma subárvore usando a opção `--prefix` em `read-tree`:
156
+
157
+ $ git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579
158
+ $ git write-tree
159
+ 3c4e9cd789d88d8d89c1073707c3585e41b0e614
160
+ $ git cat-file -p 3c4e9cd789d88d8d89c1073707c3585e41b0e614
161
+ 040000 tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 bak
162
+ 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
163
+ 100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
164
+
165
+ Se você criou um diretório de trabalho da nova árvore que acabou de escrever, você teria os dois arquivos no nível mais alto do diretório de trabalho e um subdiretório chamado `bak`, que continha a primeira versão do arquivo teste.txt. Você pode pensar nos dados que o Git contém para estas estruturas como sendo parecidas com a Figura 9-2.
166
+
167
+ Insert 18333fig0902.png
168
+ Figura 9-2. A estrutura de conteúdo de seus dados Git atuais.
169
+
170
+ ### Objetos de Commit ###
171
+
172
+ Você tem três árvores que especificam os diferentes snapshots de seu projeto que você deseja acompanhar, mas o problema anterior mantém-se: você deve se lembrar de todos os três valores SHA-1, a fim de recuperar os snapshots. Você também não tem qualquer informação sobre quem salvou os snapshots, quando eles foram salvos, ou por que eles foram salvos. Esta é a informação básica que os objetos commit armazenam para você.
173
+
174
+ Para criar um objeto commit, você chama `commit-tree` e especifica uma única árvore SHA-1 e quais objetos commit, se houverem, diretamente precederam ele. Comece com a primeira árvore que você escreveu:
175
+
176
+ $ echo 'first commit' | git commit-tree d8329f
177
+ fdf4fc3344e67ab068f836878b6c4951e3b15f3d
178
+
179
+ Agora você pode ver o seu novo objeto commit com `cat-file`:
180
+
181
+ $ git cat-file -p fdf4fc3
182
+ tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
183
+ author Scott Chacon <schacon@gmail.com> 1243040974 -0700
184
+ committer Scott Chacon <schacon@gmail.com> 1243040974 -0700
185
+
186
+ first commit
187
+
188
+ O formato de um objeto commit é simples: ele especifica a árvore de nível superior para o snapshot do projeto nesse momento; a informação do author/committer (autor do commit) obtido de suas opções de configuração `user.name` e `user.email`, com a timestamp atual; uma linha em branco, e em seguida, a mensagem de commit.
189
+
190
+ Em seguida, você vai escrever os outros dois objetos commit, cada um referenciando o commit que veio diretamente antes dele:
191
+
192
+ $ echo 'second commit' | git commit-tree 0155eb -p fdf4fc3
193
+ cac0cab538b970a37ea1e769cbbde608743bc96d
194
+ $ echo 'third commit' | git commit-tree 3c4e9c -p cac0cab
195
+ 1a410efbd13591db07496601ebc7a059dd55cfe9
196
+
197
+ Cada um dos três objetos commit apontam para uma das três árvores de snapshot criadas. Curiosamente, agora você tem um histórico Git real que você pode ver com o comando `git log`, se você executá-lo no último commit SHA-1:
198
+
199
+ $ git log --stat 1a410e
200
+ commit 1a410efbd13591db07496601ebc7a059dd55cfe9
201
+ Author: Scott Chacon <schacon@gmail.com>
202
+ Date: Fri May 22 18:15:24 2009 -0700
203
+
204
+ third commit
205
+
206
+ bak/test.txt | 1 +
207
+ 1 files changed, 1 insertions(+), 0 deletions(-)
208
+
209
+ commit cac0cab538b970a37ea1e769cbbde608743bc96d
210
+ Author: Scott Chacon <schacon@gmail.com>
211
+ Date: Fri May 22 18:14:29 2009 -0700
212
+
213
+ second commit
214
+
215
+ new.txt | 1 +
216
+ test.txt | 2 +-
217
+ 2 files changed, 2 insertions(+), 1 deletions(-)
218
+
219
+ commit fdf4fc3344e67ab068f836878b6c4951e3b15f3d
220
+ Author: Scott Chacon <schacon@gmail.com>
221
+ Date: Fri May 22 18:09:34 2009 -0700
222
+
223
+ first commit
224
+
225
+ test.txt | 1 +
226
+ 1 files changed, 1 insertions(+), 0 deletions(-)
227
+
228
+ Incrível. Você acabou de fazer as operações de baixo nível para construir um histórico Git sem usar qualquer um dos front ends. Isso é essencialmente o que o Git faz quando você executa os comandos `git add` e `git commit` — ele armazena blobs dos arquivos que foram alterados, atualiza o índice, escreve árvores, e escreve objetos commit que fazem referência às árvores de nível superior e os commits que vieram imediatamente antes deles. Esses três objetos Git principais — o blob, a árvore, e o commit — são inicialmente armazenados como arquivos separados no seu diretório `.git/objects`. Aqui estão todos os objetos no diretório de exemplo agora, comentado com o que eles armazenam:
229
+
230
+ $ find .git/objects -type f
231
+ .git/objects/01/55eb4229851634a0f03eb265b69f5a2d56f341 # tree 2
232
+ .git/objects/1a/410efbd13591db07496601ebc7a059dd55cfe9 # commit 3
233
+ .git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a # test.txt v2
234
+ .git/objects/3c/4e9cd789d88d8d89c1073707c3585e41b0e614 # tree 3
235
+ .git/objects/83/baae61804e65cc73a7201a7252750c76066a30 # test.txt v1
236
+ .git/objects/ca/c0cab538b970a37ea1e769cbbde608743bc96d # commit 2
237
+ .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4 # 'test content'
238
+ .git/objects/d8/329fc1cc938780ffdd9f94e0d364e0ea74f579 # tree 1
239
+ .git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 # new.txt
240
+ .git/objects/fd/f4fc3344e67ab068f836878b6c4951e3b15f3d # commit 1
241
+
242
+ Se você seguir todos os ponteiros internos, você tem um gráfico como o da Figura 9-3.
243
+
244
+ Insert 18333fig0903.png
245
+ Figura 9-3. Todos os objetos em seu diretório Git.
246
+
247
+ ### Armazenamento de Objetos ###
248
+
249
+ Eu mencionei anteriormente que um cabeçalho é armazenado com o conteúdo. Vamos ver como Git armazena seus objetos. Você vai ver como armazenar um objeto blob — neste caso, a string "what is up, doc?" — interativamente na linguagem de script Ruby. Você pode iniciar o modo interativo Ruby com o comando `irb`:
250
+
251
+ $ irb
252
+ >> content = "what is up, doc?"
253
+ => "what is up, doc?"
254
+
255
+ Git constrói um cabeçalho que começa com o tipo do objeto, neste caso um blob. Em seguida, é adicionado um espaço seguindo-se a dimensão do conteúdo e, finalmente, um byte nulo:
256
+
257
+ >> header = "blob #{content.length}\0"
258
+ => "blob 16\000"
259
+
260
+ Git concatena o cabeçalho e o conteúdo original e, em seguida, calcula o checksum SHA-1 do novo conteúdo. Você pode calcular o valor SHA-1 em Ruby, incluindo a biblioteca SHA1 digest com o comando `require` e então chamar `Digest::SHA1.hexdigest()` passando a string:
261
+
262
+ >> store = header + content
263
+ => "blob 16\000what is up, doc?"
264
+ >> require 'digest/sha1'
265
+ => true
266
+ >> sha1 = Digest::SHA1.hexdigest(store)
267
+ => "bd9dbf5aae1a3862dd1526723246b20206e5fc37"
268
+
269
+ Git comprime o conteúdo novo com zlib, o que você pode fazer em Ruby com a biblioteca zlib. Primeiro, você precisa incluir a biblioteca e, em seguida, executar `Zlib::Deflate.deflate()` no conteúdo:
270
+
271
+ >> require 'zlib'
272
+ => true
273
+ >> zlib_content = Zlib::Deflate.deflate(store)
274
+ => "x\234K\312\311OR04c(\317H,Q\310,V(-\320QH\311O\266\a\000_\034\a\235"
275
+
276
+ Finalmente, você vai escrever o seu conteúdo "zlib-deflated" em um objeto no disco. Você vai determinar o caminho do objeto que você deseja escrever (os dois primeiros caracteres do valor SHA-1 serão o nome do subdiretório, e os últimos 38 caracteres serão o nome do arquivo dentro desse diretório). Em Ruby, você pode usar a função `FileUtils.mkdir_p()` para criar o subdiretório se ele não existir. Em seguida, abra o arquivo com `File.open()` e escreva o conteúdo anteriormente comprimido com zlib no arquivo com uma chamada a `write()` no identificador de arquivo resultante:
277
+
278
+ >> path = '.git/objects/' + sha1[0,2] + '/' + sha1[2,38]
279
+ => ".git/objects/bd/9dbf5aae1a3862dd1526723246b20206e5fc37"
280
+ >> require 'fileutils'
281
+ => true
282
+ >> FileUtils.mkdir_p(File.dirname(path))
283
+ => ".git/objects/bd"
284
+ >> File.open(path, 'w') { |f| f.write zlib_content }
285
+ => 32
286
+
287
+ Isso é tudo — você criou um objeto Git blob válido. Todos os objetos do Git são armazenados da mesma maneira, só que com diferentes tipos — em vez da string blob, o cabeçalho vai começar com commit ou tree. Além disso, embora o conteúdo do blob possa ser pequeno, o commit e conteúdo da árvore são formatados muito especificamente.
288
+
289
+ ## Referencias Git ##
290
+
291
+ Você pode executar algo como `git log 1a410e` para ver seu histórico inteiro, mas você ainda tem que lembrar que `1a410e` é o último commit, a fim de que o você possa navegar no histórico para encontrar todos os objetos. Você precisa de um arquivo no qual você possa armazenar o valor SHA-1 em um nome simples para que você possa usar esse ponteiro em vez do valor SHA-1.
292
+
293
+ No Git, eles são chamados de "referências" (references) ou "refs"; você pode encontrar os arquivos que contêm os valores SHA-1 no diretório `.git/refs`. No projeto atual, esse diretório não contém arquivos, mas contém uma estrutura simples:
294
+
295
+ $ find .git/refs
296
+ .git/refs
297
+ .git/refs/heads
298
+ .git/refs/tags
299
+ $ find .git/refs -type f
300
+ $
301
+
302
+ Para criar uma nova referência que irá ajudá-lo a se lembrar onde seu último commit está, você pode tecnicamente fazer algo tão simples como isto:
303
+
304
+ $ echo "1a410efbd13591db07496601ebc7a059dd55cfe9" > .git/refs/heads/master
305
+
306
+ Agora, você pode usar a referência head que você acabou de criar em vez do valor SHA-1 em seus comandos do Git:
307
+
308
+ $ git log --pretty=oneline master
309
+ 1a410efbd13591db07496601ebc7a059dd55cfe9 third commit
310
+ cac0cab538b970a37ea1e769cbbde608743bc96d second commit
311
+ fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit
312
+
313
+ Você não deve editar diretamente os arquivos de referência. Git oferece um comando mais seguro para fazer isso, se você deseja atualizar uma referência chamada `update-ref`:
314
+
315
+ $ git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9
316
+
317
+ Isso é basicamente o que um branch em Git: um simples ponteiro ou referência para o head de uma linha de trabalho. Para criar um branch de volta ao segundo commit, você pode fazer isso:
318
+
319
+ $ git update-ref refs/heads/test cac0ca
320
+
321
+ Seu branch irá conter apenas o trabalho do commit abaixo:
322
+
323
+ $ git log --pretty=oneline test
324
+ cac0cab538b970a37ea1e769cbbde608743bc96d second commit
325
+ fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit
326
+
327
+ Agora, seu banco de dados Git conceitualmente é algo como a Figura 9-4.
328
+
329
+ Insert 18333fig0904.png
330
+ Figura 9-4. Objetos de diretório Git com referências ao branch head incluídas.
331
+
332
+ Quando você executar comandos como `git branch (branchname)`, Git basicamente executa o comando `update-ref` para adicionar o SHA-1 do último commit do branch em que você está em qualquer nova referência que deseja criar.
333
+
334
+ ### O HEAD ###
335
+
336
+ A questão agora é, quando você executar `git branch (branchname)`, como é que o Git sabe o SHA-1 do último commit? A resposta é o arquivo HEAD. O arquivo HEAD é uma referência simbólica para o branch em que você está no momento. Por referência simbólica, quer dizer que, ao contrário de uma referência normal, ele geralmente não contêm um valor SHA-1 mas sim um apontador para uma outra referência. Se você olhar no arquivo, você normalmente verá algo como isto:
337
+
338
+ $ cat .git/HEAD
339
+ ref: refs/heads/master
340
+
341
+ Se você executar `git checkout test`, Git atualiza o arquivo para ficar assim:
342
+
343
+ $ cat .git/HEAD
344
+ ref: refs/heads/test
345
+
346
+ Quando você executar `git commit`, ele crirá o objeto commit, especificando o pai desse objeto commit para ser o valor SHA-1 de referência apontada por HEAD.
347
+
348
+ Você também pode editar manualmente esse arquivo, mas um comando mais seguro existe para fazer isso: `symbolic-ref`. Você pode ler o valor de seu HEAD através deste comando:
349
+
350
+ $ git symbolic-ref HEAD
351
+ refs/heads/master
352
+
353
+ Você também pode definir o valor de HEAD:
354
+
355
+ $ git symbolic-ref HEAD refs/heads/test
356
+ $ cat .git/HEAD
357
+ ref: refs/heads/test
358
+
359
+ Você não pode definir uma referência simbólica fora do estilo refs:
360
+
361
+ $ git symbolic-ref HEAD test
362
+ fatal: Refusing to point HEAD outside of refs/
363
+
364
+ ### Tags ###
365
+
366
+ Você acabou de ver os três tipos de objetos principais do Git, mas há um quarto. O objeto tag é muito parecido com um objeto commit — contém um tagger (pessoa que cria a tag), uma data, uma mensagem e um ponteiro. A principal diferença é que um objeto tag aponta para um commit em vez de uma árvore. É como uma referência de branch, mas nunca se move — ele sempre aponta para o mesmo commit, mas te dá um nome mais amigável para ele.
367
+
368
+ Como discutido no Capítulo 2, existem dois tipos de tags: anotadas (annotated) e leves (lightweight). Você pode fazer uma tag leve executando algo como isto:
369
+
370
+ $ git update-ref refs/tags/v1.0 cac0cab538b970a37ea1e769cbbde608743bc96d
371
+
372
+ Isso é tudo que uma tag leve é — um branch que nunca se move. Uma tag anotada é mais complexa. Se você criar uma tag anotada, Git cria um objeto tag e depois escreve uma referência para apontar para ela em vez de diretamente para um commit. Você pode ver isso através da criação de uma tag anotada (`-a` especifica que é uma tag anotada):
373
+
374
+ $ git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 -m 'test tag'
375
+
376
+ Aqui está o valor SHA-1 do objeto que ele criou:
377
+
378
+ $ cat .git/refs/tags/v1.1
379
+ 9585191f37f7b0fb9444f35a9bf50de191beadc2
380
+
381
+ Agora, execute o comando `cat-file` com este valor SHA-1:
382
+
383
+ $ git cat-file -p 9585191f37f7b0fb9444f35a9bf50de191beadc2
384
+ object 1a410efbd13591db07496601ebc7a059dd55cfe9
385
+ type commit
386
+ tag v1.1
387
+ tagger Scott Chacon <schacon@gmail.com> Sat May 23 16:48:58 2009 -0700
388
+
389
+ test tag
390
+
391
+ Observe que a entrada do objeto aponta para o valor SHA-1 do commit que você taggeou. Também observe que ele não precisa apontar para um commit; você pode taggear qualquer objeto Git. No código-fonte Git, por exemplo, o mantenedor adicionou sua chave pública GPG como um objeto blob e depois taggeou ele. Você pode ver a chave pública, executando
392
+
393
+ $ git cat-file blob junio-gpg-pub
394
+
395
+ no repositório de código-fonte Git. O repositório do kernel Linux também tem um objeto tag que não aponta para um commit — a primeira tag criada aponta para a árvore inicial da importação do código fonte.
396
+
397
+ ### Remotos ###
398
+
399
+ O terceiro tipo de referência que você vai ver é uma referência remota. Se você adicionar um remoto e fazer um push para ele, Git armazena o valor de seu último push para esse remoto para cada branch no diretório refs `refs/remotes`. Por exemplo, você pode adicionar um remoto chamado `origin` e fazer um push do seu branch `master` nele:
400
+
401
+ $ git remote add origin git@github.com:schacon/simplegit-progit.git
402
+ $ git push origin master
403
+ Counting objects: 11, done.
404
+ Compressing objects: 100% (5/5), done.
405
+ Writing objects: 100% (7/7), 716 bytes, done.
406
+ Total 7 (delta 2), reused 4 (delta 1)
407
+ To git@github.com:schacon/simplegit-progit.git
408
+ a11bef0..ca82a6d master -> master
409
+
410
+ Então, você pode ver como era o branch `master` no remoto `origin` da última vez que você se comunicou com o servidor, verificando o arquivo `refs/remotes/origin/master`:
411
+
412
+ $ cat .git/refs/remotes/origin/master
413
+ ca82a6dff817ec66f44342007202690a93763949
414
+
415
+ Referências remotas diferem dos branches (referências `refs/heads`), principalmente no sentido de que não pode ser feito o checkout delas. Git move elas como indicadores para o último estado conhecido de onde os branches estavam nesses servidores.
416
+
417
+ ## Packfiles ##
418
+
419
+ Vamos voltar para o banco de dados de objetos do seu repositório de testes Git. Neste momento, você tem 11 objetos — 4 blobs, 3 árvores, 3 commits, e 1 tag:
420
+
421
+ $ find .git/objects -type f
422
+ .git/objects/01/55eb4229851634a0f03eb265b69f5a2d56f341 # tree 2
423
+ .git/objects/1a/410efbd13591db07496601ebc7a059dd55cfe9 # commit 3
424
+ .git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a # test.txt v2
425
+ .git/objects/3c/4e9cd789d88d8d89c1073707c3585e41b0e614 # tree 3
426
+ .git/objects/83/baae61804e65cc73a7201a7252750c76066a30 # test.txt v1
427
+ .git/objects/95/85191f37f7b0fb9444f35a9bf50de191beadc2 # tag
428
+ .git/objects/ca/c0cab538b970a37ea1e769cbbde608743bc96d # commit 2
429
+ .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4 # 'test content'
430
+ .git/objects/d8/329fc1cc938780ffdd9f94e0d364e0ea74f579 # tree 1
431
+ .git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 # new.txt
432
+ .git/objects/fd/f4fc3344e67ab068f836878b6c4951e3b15f3d # commit 1
433
+
434
+ Git comprime o conteúdo desses arquivos com zlib, então todos estes arquivos ocupam coletivamente apenas 925 bytes. Você vai adicionar um conteúdo um pouco maior no repositório para demonstrar uma característica interessante do Git. Adicione o arquivo repo.rb da biblioteca Grit em que você trabalhou anteriormente — trata-se de um arquivo de código fonte de 12K:
435
+
436
+ $ curl http://github.com/mojombo/grit/raw/master/lib/grit/repo.rb > repo.rb
437
+ $ git add repo.rb
438
+ $ git commit -m 'added repo.rb'
439
+ [master 484a592] added repo.rb
440
+ 3 files changed, 459 insertions(+), 2 deletions(-)
441
+ delete mode 100644 bak/test.txt
442
+ create mode 100644 repo.rb
443
+ rewrite test.txt (100%)
444
+
445
+ Se você olhar para a árvore resultante, você pode ver o valor SHA-1 que o arquivo repo.rb tem no objeto blob:
446
+
447
+ $ git cat-file -p master^{tree}
448
+ 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
449
+ 100644 blob 9bc1dc421dcd51b4ac296e3e5b6e2a99cf44391e repo.rb
450
+ 100644 blob e3f094f522629ae358806b17daf78246c27c007b test.txt
451
+
452
+ Você pode então usar `git cat-file` para ver o quão grande esse objeto é:
453
+
454
+ $ git cat-file -s 9bc1dc421dcd51b4ac296e3e5b6e2a99cf44391e
455
+ 12898
456
+
457
+ Agora, modifique o arquivo um pouco, e veja o que acontece:
458
+
459
+ $ echo '# testing' >> repo.rb
460
+ $ git commit -am 'modified repo a bit'
461
+ [master ab1afef] modified repo a bit
462
+ 1 files changed, 1 insertions(+), 0 deletions(-)
463
+
464
+ Verifique a árvore criada por este commit, e você verá algo interessante:
465
+
466
+ $ git cat-file -p master^{tree}
467
+ 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
468
+ 100644 blob 05408d195263d853f09dca71d55116663690c27c repo.rb
469
+ 100644 blob e3f094f522629ae358806b17daf78246c27c007b test.txt
470
+
471
+ O blob agora é um blob diferente, o que significa que, embora você tenha adicionado apenas uma única linha ao final de um arquivo de 400 linhas, Git armazenou esse novo conteúdo como um objeto completamente novo:
472
+
473
+ $ git cat-file -s 05408d195263d853f09dca71d55116663690c27c
474
+ 12908
475
+
476
+ Você tem dois objetos de 12K quase idênticos em seu disco. Não seria bom se o Git pudesse armazenar um deles na íntegra, mas, o segundo objeto apenas como o delta entre ele e o primeiro?
477
+
478
+ Acontece que ele pode. O formato inicial em que Git salva objetos em disco é chamado de formato de objeto solto (loose object format). No entanto, ocasionalmente Git empacota vários desses objetos em um único arquivo binário chamado de packfile, a fim de economizar espaço e ser mais eficiente. Git faz isso, se você tem muitos objetos soltos, se você executar o comando `git gc` manualmente, ou se você fizer push para um servidor remoto. Para ver o que acontece, você pode manualmente pedir ao Git para arrumar os objetos chamando o comando `git gc`:
479
+
480
+ $ git gc
481
+ Counting objects: 17, done.
482
+ Delta compression using 2 threads.
483
+ Compressing objects: 100% (13/13), done.
484
+ Writing objects: 100% (17/17), done.
485
+ Total 17 (delta 1), reused 10 (delta 0)
486
+
487
+ Se você olhar em seu diretório de objetos, você vai descobrir que a maioria de seus objetos sumiram, e um novo par de arquivos apareceu:
488
+
489
+ $ find .git/objects -type f
490
+ .git/objects/71/08f7ecb345ee9d0084193f147cdad4d2998293
491
+ .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
492
+ .git/objects/info/packs
493
+ .git/objects/pack/pack-7a16e4488ae40c7d2bc56ea2bd43e25212a66c45.idx
494
+ .git/objects/pack/pack-7a16e4488ae40c7d2bc56ea2bd43e25212a66c45.pack
495
+
496
+ Os objetos que permanecem são os blobs que não são apontados por qualquer commit — neste caso, os blobs de exemplo "what is up, doc?" e o exemplo "test content" que você criou anteriormente. Como você nunca adicionou eles a qualquer commit, eles são considerados pendentes e não são embalados em sua nova packfile.
497
+
498
+ Os outros arquivos são o seu novo packfile e um índice. O packfile é um arquivo único contendo o conteúdo de todos os objetos que foram removidos do seu sistema de arquivos. O índice é um arquivo que contém offsets deste packfile assim você pode rapidamente buscar um objeto específico. O que é legal é que, embora os objetos em disco antes de executar o `gc` tinham coletivamente cerca de 12K de tamanho, o packfile novo tem apenas 6K. Você reduziu a utilização do disco pela metade empacotando seus objetos.
499
+
500
+ Como o Git faz isso? Quando Git empacota objetos, ele procura por arquivos que são nomeados e dimensionados de forma semelhante, e armazena apenas os deltas de uma versão do arquivo para a próxima. Você pode olhar dentro do packfile e ver o que o Git fez para economizar espaço. O comando plumbing `git verify-pack` permite que você veja o que foi empacotado:
501
+
502
+ $ git verify-pack -v \
503
+ .git/objects/pack/pack-7a16e4488ae40c7d2bc56ea2bd43e25212a66c45.idx
504
+ 0155eb4229851634a0f03eb265b69f5a2d56f341 tree 71 76 5400
505
+ 05408d195263d853f09dca71d55116663690c27c blob 12908 3478 874
506
+ 09f01cea547666f58d6a8d809583841a7c6f0130 tree 106 107 5086
507
+ 1a410efbd13591db07496601ebc7a059dd55cfe9 commit 225 151 322
508
+ 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a blob 10 19 5381
509
+ 3c4e9cd789d88d8d89c1073707c3585e41b0e614 tree 101 105 5211
510
+ 484a59275031909e19aadb7c92262719cfcdf19a commit 226 153 169
511
+ 83baae61804e65cc73a7201a7252750c76066a30 blob 10 19 5362
512
+ 9585191f37f7b0fb9444f35a9bf50de191beadc2 tag 136 127 5476
513
+ 9bc1dc421dcd51b4ac296e3e5b6e2a99cf44391e blob 7 18 5193 1 \
514
+ 05408d195263d853f09dca71d55116663690c27c
515
+ ab1afef80fac8e34258ff41fc1b867c702daa24b commit 232 157 12
516
+ cac0cab538b970a37ea1e769cbbde608743bc96d commit 226 154 473
517
+ d8329fc1cc938780ffdd9f94e0d364e0ea74f579 tree 36 46 5316
518
+ e3f094f522629ae358806b17daf78246c27c007b blob 1486 734 4352
519
+ f8f51d7d8a1760462eca26eebafde32087499533 tree 106 107 749
520
+ fa49b077972391ad58037050f2a75f74e3671e92 blob 9 18 856
521
+ fdf4fc3344e67ab068f836878b6c4951e3b15f3d commit 177 122 627
522
+ chain length = 1: 1 object
523
+ pack-7a16e4488ae40c7d2bc56ea2bd43e25212a66c45.pack: ok
524
+
525
+ Aqui, o blob `9bc1d`, que se você se lembrar foi a primeira versão do seu arquivo repo.rb, faz referência ao blob `05408`, que foi a segunda versão do arquivo. A terceira coluna da saída é o tamanho do objeto no pacote, assim você pode ver que `05408` ocupa 12K do arquivo, mas que `9bc1d` ocupa apenas 7 bytes. O que também é interessante é que a segunda versão do arquivo é a que é armazenada intacta, enquanto que a versão original é armazenada como um delta — isso porque é mais provável a necessidade de acesso mais rápido para a versão mais recente do arquivo.
526
+
527
+ A coisa realmente interessante sobre isso é que ele pode ser reembalado a qualquer momento. Git irá ocasionalmente reembalar seu banco de dados automaticamente, sempre tentando economizar mais espaço. Você pode também manualmente reembalar a qualquer momento executando `git gc`.
528
+
529
+ ## O Refspec ##
530
+
531
+ Ao longo deste livro, você usou um simples mapeamento de branches remotos para referências locais; mas eles podem ser mais complexos.
532
+ Suponha que você adicione um remoto como este:
533
+
534
+ $ git remote add origin git@github.com:schacon/simplegit-progit.git
535
+
536
+ Ele adiciona uma seção em seu arquivo `.git/config`, especificando o nome do remoto (`origin`), a URL do repositório remoto, e o refspec a ser buscado:
537
+
538
+ [remote "origin"]
539
+ url = git@github.com:schacon/simplegit-progit.git
540
+ fetch = +refs/heads/*:refs/remotes/origin/*
541
+
542
+ O formato do refspec é um `+` opcional, seguido por `<src>:<dst>`, onde `<src>` é o padrão para referências no lado remoto e `<dst>` é onde essas referências serão escritas localmente. O `+` diz ao Git para atualizar a referência, mesmo que não seja um fast-forward.
543
+
544
+ No caso padrão que é automaticamente escrito por um comando `git remote add`, Git busca todas as referências em `refs/heads/` no servidor e grava-os em `refs/remotes/origin/` localmente. Então, se há um branch `master` no servidor, você pode acessar o log desse branch localmente através de
545
+
546
+ $ git log origin/master
547
+ $ git log remotes/origin/master
548
+ $ git log refs/remotes/origin/master
549
+
550
+ Eles são todos equivalentes, porque Git expande cada um deles em `refs/remotes/origin/master`.
551
+
552
+ Se você quiser que o Git só faça o pull do branch `master` toda vez, e não qualquer outro branch do servidor remoto, você pode alterar a linha fetch para
553
+
554
+ fetch = +refs/heads/master:refs/remotes/origin/master
555
+
556
+ Este é apenas o refspec padrão do `git fetch` para esse remoto. Se você quiser fazer algo apenas uma vez, você pode especificar o refspec na linha de comando também. Para fazer o pull do branch `master` do remoto até `origin/mymaster` localmente, você pode executar
557
+
558
+ $ git fetch origin master:refs/remotes/origin/mymaster
559
+
560
+ Você também pode especificar múltiplos refspecs. Na linha de comando, você pode fazer pull de vários branches assim:
561
+
562
+ $ git fetch origin master:refs/remotes/origin/mymaster \
563
+ topic:refs/remotes/origin/topic
564
+ From git@github.com:schacon/simplegit
565
+ ! [rejected] master -> origin/mymaster (non fast forward)
566
+ * [new branch] topic -> origin/topic
567
+
568
+ Neste caso, o pull do branch master foi rejeitado, porque não era uma referência fast-forward. Você pode evitar isso especificando o `+` na frente do refspec.
569
+
570
+ Você também pode especificar múltiplos refspecs em seu arquivo de configuração. Se você quer sempre buscar os branches master e experiment, adicione duas linhas:
571
+
572
+ [remote "origin"]
573
+ url = git@github.com:schacon/simplegit-progit.git
574
+ fetch = +refs/heads/master:refs/remotes/origin/master
575
+ fetch = +refs/heads/experiment:refs/remotes/origin/experiment
576
+
577
+ Você não pode usar globs parciais no padrão, então isto seria inválido:
578
+
579
+ fetch = +refs/heads/qa*:refs/remotes/origin/qa*
580
+
581
+ No entanto, você pode usar namespacing para realizar algo assim. Se você tem uma equipe de QA que faz push de uma série de branches, e você deseja obter o branch master e qualquer um dos branches da equipe de QA, mas nada mais, você pode usar uma seção de configuração como esta:
582
+
583
+ [remote "origin"]
584
+ url = git@github.com:schacon/simplegit-progit.git
585
+ fetch = +refs/heads/master:refs/remotes/origin/master
586
+ fetch = +refs/heads/qa/*:refs/remotes/origin/qa/*
587
+
588
+ Se você tem um fluxo de trabalho complexo que tem uma equipe de QA fazendo push de branches, desenvolvedores fazendo push de branches, e equipes de integração fazendo push e colaborando em branches remotos, você pode nomeá-los (namespace) facilmente desta forma.
589
+
590
+ ### Fazendo Push de Refspecs ###
591
+
592
+ É legal que você possa buscar referências nomeadas dessa maneira, mas como é que a equipe de QA obtêm os seus branches em um namespace `qa/`? Você consegue fazer isso utilizando refspecs para fazer o push.
593
+
594
+ Se a equipe de QA quer fazer push de seu branch `master` em `qa/master` no servidor remoto, eles podem executar
595
+
596
+ $ git push origin master:refs/heads/qa/master
597
+
598
+ Se eles querem que o Git faça isso automaticamente toda vez que executar `git push origin`, eles podem adicionar o valor `push` ao seu arquivo de configuração:
599
+
600
+ [remote "origin"]
601
+ url = git@github.com:schacon/simplegit-progit.git
602
+ fetch = +refs/heads/*:refs/remotes/origin/*
603
+ push = refs/heads/master:refs/heads/qa/master
604
+
605
+ Novamente, isso vai fazer com que `git push origin` faça um push do branch `master` local para o branch remoto `qa/master` por padrão.
606
+
607
+ ### Deletando Referencias ###
608
+
609
+ Você também pode usar o refspec para apagar referências do servidor remoto executando algo como isto:
610
+
611
+ $ git push origin :topic
612
+
613
+ Já que o refspec é `<src>:<dst>`, ao remover `<src>`, basicamente diz para enviar nada para o branch tópico no remoto, o que o exclui.
614
+
615
+ ## Protocolos de Transferência ##
616
+
617
+ Git pode transferir dados entre dois repositórios de duas maneiras principais: através de HTTP e através dos protocolos chamados inteligentes: `file://`, `ssh://` e `git://`. Esta seção irá mostrar rapidamente como esses dois principais protocolos operam.
618
+
619
+ ### O Protocolo Burro ###
620
+
621
+ HTTP é muitas vezes referido como o protocolo burro, porque não requer código Git específico do lado servidor durante o processo de transporte. O processo de fetch é uma série de solicitações GET, onde o cliente pode assumir o layout do repositório Git no servidor. Vamos ver o processo `http-fetch` para obter a biblioteca simplegit:
622
+
623
+ $ git clone http://github.com/schacon/simplegit-progit.git
624
+
625
+ A primeira coisa que este comando faz é obter o arquivo `info/refs`. Este arquivo é escrito pelo comando `update-server-info`, é por isso que você precisa ativar ele como um hook `post-receive` para que o transporte HTTP funcione corretamente:
626
+
627
+ => GET info/refs
628
+ ca82a6dff817ec66f44342007202690a93763949 refs/heads/master
629
+
630
+ Agora você tem uma lista de referências remotas e os SHAs. Em seguida, você verifica qual é a referência HEAD para que você saiba o que deve ser obtido (check out) quando você terminar:
631
+
632
+ => GET HEAD
633
+ ref: refs/heads/master
634
+
635
+ Você precisa fazer o check out do branch `master` quando você tiver concluído o processo.
636
+ Neste momento, você está pronto para iniciar o processo de "caminhada". Como o seu ponto de partida é o objeto commit `ca82a6` que você viu no arquivo `info/refs`, você começa obtendo ele:
637
+
638
+ => GET objects/ca/82a6dff817ec66f44342007202690a93763949
639
+ (179 bytes of binary data)
640
+
641
+ Você obtêm um objeto — este objeto é um "loose format" no servidor, e você o obteu a partir de uma conexão HTTP GET estática. Você pode descompactá-lo, retirar o cabeçalho, e ver o conteúdo do commit:
642
+
643
+ $ git cat-file -p ca82a6dff817ec66f44342007202690a93763949
644
+ tree cfda3bf379e4f8dba8717dee55aab78aef7f4daf
645
+ parent 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
646
+ author Scott Chacon <schacon@gmail.com> 1205815931 -0700
647
+ committer Scott Chacon <schacon@gmail.com> 1240030591 -0700
648
+
649
+ changed the version number
650
+
651
+ A seguir, você tem mais dois objetos para obter — `cfda3b`, que a árvore de conteúdo do commit que acabamos de obter referencia, e `085bb3`, que é o commit pai:
652
+
653
+ => GET objects/08/5bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
654
+ (179 bytes of data)
655
+
656
+ Isso lhe dá o seu próximo objeto commit. Obtenha o objeto árvore:
657
+
658
+ => GET objects/cf/da3bf379e4f8dba8717dee55aab78aef7f4daf
659
+ (404 - Not Found)
660
+
661
+ Oops — parece que esse objeto árvore não está em "loose format" no servidor, então você recebe um erro 404. Há algumas razões para isso — o objeto pode estar em um repositório alternativo, ou poderia estar em um packfile neste repositório. Git verifica a existência de quaisquer alternativas listadas primeiro:
662
+
663
+ => GET objects/info/http-alternates
664
+ (empty file)
665
+
666
+ Se isso retornar uma lista de URLs alternativas, Git verifica a existência de "loose files" e packfiles lá — este é um mecanismo legal para projetos que são forks de um outro para compartilhar objetos no disco. No entanto, como não há substitutos listados neste caso, o objeto deve estar em um packfile. Para saber quais packfiles estão disponíveis neste servidor, você precisa obter o arquivo `objects/info/packs`, que contém uma lista deles (também gerado pelo `update-server-info`):
667
+
668
+ => GET objects/info/packs
669
+ P pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack
670
+
671
+ Há apenas um packfile no servidor, então o seu objeto deve estar lá, mas você vai verificar o arquivo de índice para ter certeza. Isso também é útil se você tem vários packfiles no servidor, assim você pode ver qual packfile contém o objeto que você precisa:
672
+
673
+ => GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.idx
674
+ (4k of binary data)
675
+
676
+ Agora que você tem o índice do packfile, você pode ver se o seu objeto esta nele — porque o índice lista os SHAs dos objetos contidos no packfile e os deslocamentos (offsets) desses objetos. Seu objeto está lá, então vá em frente e obtenha todo o packfile:
677
+
678
+ => GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack
679
+ (13k of binary data)
680
+
681
+ Você tem o seu objeto árvore, então você continua navegando em seus commits. Eles todos estão dentro do packfile que você acabou de baixar, então você não precisa fazer mais solicitações para o servidor. Git faz o check out de uma cópia de trabalho do branch `master`, que foi apontada pela referência HEAD que você baixou no início.
682
+
683
+ Toda a saída deste processo é parecida com isto:
684
+
685
+ $ git clone http://github.com/schacon/simplegit-progit.git
686
+ Initialized empty Git repository in /private/tmp/simplegit-progit/.git/
687
+ got ca82a6dff817ec66f44342007202690a93763949
688
+ walk ca82a6dff817ec66f44342007202690a93763949
689
+ got 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
690
+ Getting alternates list for http://github.com/schacon/simplegit-progit.git
691
+ Getting pack list for http://github.com/schacon/simplegit-progit.git
692
+ Getting index for pack 816a9b2334da9953e530f27bcac22082a9f5b835
693
+ Getting pack 816a9b2334da9953e530f27bcac22082a9f5b835
694
+ which contains cfda3bf379e4f8dba8717dee55aab78aef7f4daf
695
+ walk 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
696
+ walk a11bef06a3f659402fe7563abf99ad00de2209e6
697
+
698
+ ### O Protocolo Inteligente ###
699
+
700
+ O método HTTP é simples, mas um pouco ineficiente. Usar protocolos inteligentes é um método mais comum de transferência de dados. Estes protocolos têm um processo no sistema remoto que é inteligente em relação ao Git — ele pode ler dados locais e descobrir o que o cliente tem ou precisa e gera dados personalizados para ele. Existem dois conjuntos de processos de transferência de dados: um par para enviar dados (upload) e um par para download de dados.
701
+
702
+ #### Fazendo Upload de Dados ####
703
+
704
+ Para fazer upload de dados para um processo remoto, Git usa os processos `send-pack` e `receive-pack`. O processo `send-pack` é executado no cliente e se conecta a um processo `receive-pack` no lado remoto.
705
+
706
+ Por exemplo, digamos que você execute `git push origin master` em seu projeto, e `origin` é definido como uma URL que usa o protocolo SSH. Git executa o processo `send-pack`, que inicia uma conexão SSH ao seu servidor. Ele tenta executar um comando no servidor remoto através de uma chamada SSH que é parecida com isto:
707
+
708
+ $ ssh -x git@github.com "git-receive-pack 'schacon/simplegit-progit.git'"
709
+ 005bca82a6dff817ec66f4437202690a93763949 refs/heads/master report-status delete-refs
710
+ 003e085bb3bcb608e1e84b2432f8ecbe6306e7e7 refs/heads/topic
711
+ 0000
712
+
713
+ O comando `git-receive-pack` imediatamente responde com uma linha para cada referência que tem atualmente — neste caso, apenas o branch `master` e seu SHA. A primeira linha também tem uma lista de recursos do servidor (aqui, `report-status` e `delete-refs`).
714
+
715
+ Cada linha se inicia com um valor hexadecimal de 4 bytes especificando quão longo o resto da linha é. Sua primeira linha começa com 005B, que é 91 em hexadecimal, o que significa que 91 bytes permanecem nessa linha. A próxima linha começa com 003e, que é 62, então você leu os 62 bytes restantes. A próxima linha é 0000, ou seja, o servidor terminou com a sua lista de referências.
716
+
717
+ Agora que ele sabe o estado do servidor, o seu processo `send-pack` determina que commits ele tem mas que o servidor não tem. Para cada referência que este push irá atualizar, o processo `send-pack` diz essa informação ao processo `receive-pack`. Por exemplo, se você está atualizando o branch `master` e está adicionando um branch `experiment`, a resposta do `send-pack` pode ser parecida com esta:
718
+
719
+ 0085ca82a6dff817ec66f44342007202690a93763949 15027957951b64cf874c3557a0f3547bd83b3ff6 refs/heads/master report-status
720
+ 00670000000000000000000000000000000000000000 cdfdb42577e2506715f8cfeacdbabc092bf63e8d refs/heads/experiment
721
+ 0000
722
+
723
+ O valor SHA-1 de todos os '0's significa que nada estava lá antes — porque você está adicionando a referência de experiment. Se você estivesse apagando uma referência, você veria o oposto: tudo '0' no lado direito.
724
+
725
+ Git envia uma linha para cada referência que você está atualizando com o SHA antigo, o SHA novo, e a referência que está sendo atualizada. A primeira linha também tem as capacidades do cliente. Em seguida, o cliente faz upload de um packfile com todos os objetos que o servidor não tem ainda. Finalmente, o servidor responde com uma indicação de sucesso (ou falha):
726
+
727
+ 000Aunpack ok
728
+
729
+ #### Fazendo Download de Dados ####
730
+
731
+ Quando você baixa os dados, os processos `fetch-pack` e `upload-pack` são usados. O cliente inicia um processo `fetch-pack` que se conecta a um processo `upload-pack` no lado remoto para negociar os dados que serão transferidos para a máquina local.
732
+
733
+ Existem diferentes maneiras de iniciar o processo `upload-pack` no repositório remoto. Você pode fazê-lo via SSH da mesma forma que o processo `receive-pack`. Você também pode iniciar o processo, através do daemon Git, que escuta em um servidor na porta 9418 por padrão. O processo `fetch-pack` envia dados que se parecem com isso para o servidor após se conectar:
734
+
735
+ 003fgit-upload-pack schacon/simplegit-progit.git\0host=myserver.com\0
736
+
737
+ Ele começa com os 4 bytes que especificam a quantidade de dados enviados, seguido pelo comando a ser executado, seguido por um byte nulo e, em seguida, o hostname do servidor seguido por um ultimo byte nulo. O daemon Git verifica que o comando pode ser executado e que o repositório existe e tem permissões públicas. Se tudo estiver certo, ele aciona o processo `upload-pack` e envia o pedido para ele.
738
+
739
+ Se você estiver fazendo o fetch através de SSH, `fetch-pack` executa algo como isto:
740
+
741
+ $ ssh -x git@github.com "git-upload-pack 'schacon/simplegit-progit.git'"
742
+
743
+ Em todo caso, depois que `fetch-pack` conectar, `upload-pack` devolve algo como isto:
744
+
745
+ 0088ca82a6dff817ec66f44342007202690a93763949 HEAD\0multi_ack thin-pack \
746
+ side-band side-band-64k ofs-delta shallow no-progress include-tag
747
+ 003fca82a6dff817ec66f44342007202690a93763949 refs/heads/master
748
+ 003e085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 refs/heads/topic
749
+ 0000
750
+
751
+ Isto é muito semelhante a resposta de `receive-pack`, mas as funcionalidades são diferentes. Além disso, ele envia de volta a referência de HEAD para que o cliente saiba o que deve ser verificado (check out) se este for um clone.
752
+
753
+ Neste momento, o processo `fetch-pack` verifica quais objetos ele possui e responde com os objetos de que necessita através do envio de "want" e do SHA que quer. Ele envia todos os objetos que ele já tem com "have" e também o SHA. No final da lista, ele escreve "done" para iniciar o processo `upload-pack` para começar a enviar o packfile dos dados que ele precisa:
754
+
755
+ 0054want ca82a6dff817ec66f44342007202690a93763949 ofs-delta
756
+ 0032have 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
757
+ 0000
758
+ 0009done
759
+
760
+ Isto é um caso muito simples dos protocolos de transferência. Em casos mais complexos, o cliente suporta funcionalidades `multi_ack` ou `side-band`; mas este exemplo mostra o funcionamento de upload e download básico utilizado pelos processos de protocolo inteligentes.
761
+
762
+ ## Manutenção e Recuperação de Dados ##
763
+
764
+ Ocasionalmente, você pode ter que fazer alguma limpeza — compactar um repositório, limpar um repositório importado, ou recuperar trabalhos perdidos. Esta seção irá mostrar alguns desses cenários.
765
+
766
+ ### Manutenção ###
767
+
768
+ Ocasionalmente, Git automaticamente executa um comando chamado "auto gc". Na maioria das vezes, este comando não faz nada. No entanto, se houverem muitos objetos soltos (loose objects) (objetos que não estejam em um packfile) ou muitos packfiles, Git executa um verdadeiro comando `git gc`. O `gc` significa garbage collect (coleta de lixo), e o comando faz uma série de coisas: ele reúne todos os objetos soltos e os coloca em packfiles, consolida packfiles em um packfile maior, e remove objetos que não estejam ao alcance de qualquer commit e tem poucos meses de idade.
769
+
770
+ Você pode executar auto gc manualmente da seguinte forma:
771
+
772
+ $ git gc --auto
773
+
774
+ Mais uma vez, isso geralmente não faz nada. Você deve ter cerca de 7.000 objetos soltos ou mais de 50 packfiles para que o Git execute um comando gc real. Você pode modificar esses limites com as opções de configuração `gc.auto` e `gc.autopacklimit`, respectivamente.
775
+
776
+ A outra coisa que `gc` irá fazer é arrumar suas referências em um único arquivo. Suponha que seu repositório contém os seguintes branches e tags:
777
+
778
+ $ find .git/refs -type f
779
+ .git/refs/heads/experiment
780
+ .git/refs/heads/master
781
+ .git/refs/tags/v1.0
782
+ .git/refs/tags/v1.1
783
+
784
+ Se você executar `git gc`, você não terá mais esses arquivos no diretório `refs`. Git irá movê-los para um arquivo chamado `.git/packed-refs` que se parece com isto:
785
+
786
+ $ cat .git/packed-refs
787
+ # pack-refs with: peeled
788
+ cac0cab538b970a37ea1e769cbbde608743bc96d refs/heads/experiment
789
+ ab1afef80fac8e34258ff41fc1b867c702daa24b refs/heads/master
790
+ cac0cab538b970a37ea1e769cbbde608743bc96d refs/tags/v1.0
791
+ 9585191f37f7b0fb9444f35a9bf50de191beadc2 refs/tags/v1.1
792
+ ^1a410efbd13591db07496601ebc7a059dd55cfe9
793
+
794
+ Se você atualizar uma referência, Git não edita esse arquivo, mas em vez disso, escreve um novo arquivo em `refs/heads`. Para obter o SHA apropriado para uma dada referência, Git checa a referência no diretório `refs` e então verifica o arquivo `packed-refs` como um último recurso. No entanto, se você não conseguir encontrar uma referência no diretório `refs`, ela está provavelmente em seu arquivo `packed-refs`.
795
+
796
+ Observe a última linha do arquivo, que começa com um `^`. Isto significa que a tag diretamente acima é uma tag anotada (annotated tag) e que a linha é o commit que a tag anotada aponta.
797
+
798
+ ### Recuperação de Dados ###
799
+
800
+ Em algum ponto de sua jornada Git, você pode acidentalmente perder um commit. Geralmente, isso acontece porque você forçou a remoção (force-delete) de um branch que tinha informações nele, e depois se deu conta de que precisava do branch; ou você resetou (hard-reset) um branch, abandonando commits com informações importantes. Assumindo que isso aconteceu, como você pode obter o seu commit de volta?
801
+
802
+ Aqui está um exemplo que reseta (hard-resets) o branch master no seu repositório de teste para um commit antigo e depois recupera os commits perdidos. Primeiro, vamos rever onde seu repositório está neste momento:
803
+
804
+ $ git log --pretty=oneline
805
+ ab1afef80fac8e34258ff41fc1b867c702daa24b modified repo a bit
806
+ 484a59275031909e19aadb7c92262719cfcdf19a added repo.rb
807
+ 1a410efbd13591db07496601ebc7a059dd55cfe9 third commit
808
+ cac0cab538b970a37ea1e769cbbde608743bc96d second commit
809
+ fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit
810
+
811
+ Agora, mova o branch `master` de volta para o commit do meio:
812
+
813
+ $ git reset --hard 1a410efbd13591db07496601ebc7a059dd55cfe9
814
+ HEAD is now at 1a410ef third commit
815
+ $ git log --pretty=oneline
816
+ 1a410efbd13591db07496601ebc7a059dd55cfe9 third commit
817
+ cac0cab538b970a37ea1e769cbbde608743bc96d second commit
818
+ fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit
819
+
820
+ Você efetivamente perdeu os dois primeiros commits — você não tem um branch de onde os commits são alcançáveis. Você precisa encontrar o SHA do último commit e em seguida, adicionar um branch que aponta para ele. O truque é encontrar o SHA do commit mais recente — você não o memorizou, certo?
821
+
822
+ Muitas vezes, a maneira mais rápida é usar uma ferramenta chamada `git reflog`. Quando você está trabalhando, Git silenciosamente registra onde está o HEAD cada vez que você mudá-lo. Cada vez que você fizer um commit ou alterar branches, o reflog é atualizado. O reflog também é atualizado pelo comando `git update-ref`, o que é mais um motivo para usá-lo em vez de apenas escrever o valor SHA em seus arquivos ref, como abordado anteriormente na seção "Referências Git" deste capítulo. Você pode ver onde você está, a qualquer momento, executando `git reflog`:
823
+
824
+ $ git reflog
825
+ 1a410ef HEAD@{0}: 1a410efbd13591db07496601ebc7a059dd55cfe9: updating HEAD
826
+ ab1afef HEAD@{1}: ab1afef80fac8e34258ff41fc1b867c702daa24b: updating HEAD
827
+
828
+ Aqui podemos ver os dois commits que obtemos com check out, no entanto, não há muita informação aqui. Para ver a mesma informação de uma forma muito mais útil, podemos executar `git log -g`, que vai lhe dar uma saída de log normal do seu reflog.
829
+
830
+ $ git log -g
831
+ commit 1a410efbd13591db07496601ebc7a059dd55cfe9
832
+ Reflog: HEAD@{0} (Scott Chacon <schacon@gmail.com>)
833
+ Reflog message: updating HEAD
834
+ Author: Scott Chacon <schacon@gmail.com>
835
+ Date: Fri May 22 18:22:37 2009 -0700
836
+
837
+ third commit
838
+
839
+ commit ab1afef80fac8e34258ff41fc1b867c702daa24b
840
+ Reflog: HEAD@{1} (Scott Chacon <schacon@gmail.com>)
841
+ Reflog message: updating HEAD
842
+ Author: Scott Chacon <schacon@gmail.com>
843
+ Date: Fri May 22 18:15:24 2009 -0700
844
+
845
+ modified repo a bit
846
+
847
+ Parece que o commit de baixo é o que você perdeu, então você pode recuperá-lo através da criação de um novo branch neste commit. Por exemplo, você pode criar um branch chamado `recover-branch` naquele commit (ab1afef):
848
+
849
+ $ git branch recover-branch ab1afef
850
+ $ git log --pretty=oneline recover-branch
851
+ ab1afef80fac8e34258ff41fc1b867c702daa24b modified repo a bit
852
+ 484a59275031909e19aadb7c92262719cfcdf19a added repo.rb
853
+ 1a410efbd13591db07496601ebc7a059dd55cfe9 third commit
854
+ cac0cab538b970a37ea1e769cbbde608743bc96d second commit
855
+ fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit
856
+
857
+ Agora você tem um branch chamado `recover-branch` que é onde o seu branch `master` costumava estar, fazendo os dois primeiros commits acessíveis novamente.
858
+ Em seguida, suponha que a sua perda por algum motivo não está no reflog — você pode simular isso ao remover `recover-branch` e apagar o reflog. Agora os dois primeiros commits não são acessíveis por qualquer coisa:
859
+
860
+ $ git branch -D recover-branch
861
+ $ rm -Rf .git/logs/
862
+
863
+ Como os dados do reflog são mantidos no diretório `.git/logs/`, você efetivamente não têm reflog. Como você pode recuperar aquele commit agora? Uma maneira é usar o utilitário `git fsck`, que verifica a integridade de seu banco de dados. Se você executá-lo com a opção `--full`, ele mostra todos os objetos que não são apontadas por outro objeto:
864
+
865
+ $ git fsck --full
866
+ dangling blob d670460b4b4aece5915caf5c68d12f560a9fe3e4
867
+ dangling commit ab1afef80fac8e34258ff41fc1b867c702daa24b
868
+ dangling tree aea790b9a58f6cf6f2804eeac9f0abbe9631e4c9
869
+ dangling blob 7108f7ecb345ee9d0084193f147cdad4d2998293
870
+
871
+ Neste caso, você pode ver o seu commit desaparecido após o commit pendente (dangling). Você pode recuperá-lo da mesma forma, adicionando um branch que aponta para seu SHA.
872
+
873
+ ### Removendo Objetos ###
874
+
875
+ Há um monte de coisas boas em relação ao Git, mas um recurso que pode causar problemas é o fato de que o `git clone` baixa todo o histórico do projeto, incluindo todas as versões de cada arquivo. Isso é bom se a coisa toda for código fonte, porque Git é altamente otimizado para comprimir os dados de forma eficiente. No entanto, se alguém, em algum momento adicionou um arquivo enorme, todo clone será forçado a baixar o arquivo grande, mesmo que ele tenha sido retirado do projeto no commit seguinte. Como ele é acessível a partir do histórico, ele sempre estará lá.
876
+
877
+ Isso pode ser um grande problema quando você está convertendo repositórios do Subversion ou Perforce para Git. Como você não baixa todo o histórico nesses sistemas, este tipo de adição traz poucas consequências. Se você fez uma importação de outro sistema ou descobriu que seu repositório é muito maior do que deveria ser, eis aqui como você pode encontrar e remover objetos grandes.
878
+
879
+ Esteja avisado: esta técnica é destrutiva para o seu histórico de commits. Ele reescreve a cada objeto commit da primeira árvore que você tem que modificar para remover uma referência de arquivo grande. Se você fizer isso, imediatamente após uma importação, antes que alguém tenha começado usar o commit, você ficará bem — caso contrário, você tem que notificar todos os contribuidores para que eles façam um rebase do trabalho deles em seus novos commits.
880
+
881
+ Para demonstrar, você vai adicionar um arquivo grande em seu repositório, removê-lo no próximo commit, encontrá-lo e removê-lo permanentemente a partir do repositório. Primeiro, adicione um objeto grande no seu histórico:
882
+
883
+ $ curl http://kernel.org/pub/software/scm/git/git-1.6.3.1.tar.bz2 > git.tbz2
884
+ $ git add git.tbz2
885
+ $ git commit -am 'added git tarball'
886
+ [master 6df7640] added git tarball
887
+ 1 files changed, 0 insertions(+), 0 deletions(-)
888
+ create mode 100644 git.tbz2
889
+
890
+ Oops - você não queria adicionar um tarball enorme no seu projeto. Melhor se livrar dele:
891
+
892
+ $ git rm git.tbz2
893
+ rm 'git.tbz2'
894
+ $ git commit -m 'oops - removed large tarball'
895
+ [master da3f30d] oops - removed large tarball
896
+ 1 files changed, 0 insertions(+), 0 deletions(-)
897
+ delete mode 100644 git.tbz2
898
+
899
+ Agora, use `gc` no seu banco de dados e veja quanto espaço você está usando:
900
+
901
+ $ git gc
902
+ Counting objects: 21, done.
903
+ Delta compression using 2 threads.
904
+ Compressing objects: 100% (16/16), done.
905
+ Writing objects: 100% (21/21), done.
906
+ Total 21 (delta 3), reused 15 (delta 1)
907
+
908
+ Você pode executar o comando `count-objects` para ver rapidamente quanto espaço você está usando:
909
+
910
+ $ git count-objects -v
911
+ count: 4
912
+ size: 16
913
+ in-pack: 21
914
+ packs: 1
915
+ size-pack: 2016
916
+ prune-packable: 0
917
+ garbage: 0
918
+
919
+ A entrada `size-pack` é do tamanho de seus packfiles em kilobytes, então você está usando 2MB. Antes do último commit, você estava usando quase 2K — claramente, removendo o arquivo do commit anterior não remove-o de seu histórico. Toda vez que alguém clonar este repositório, eles vão ter que clonar os 2MB para obter este projeto, porque você acidentalmente acrescentou um arquivo grande. Vamos nos livrar dele.
920
+
921
+ Primeiro você tem que encontrá-lo. Neste caso, você já sabe qual é o arquivo. Mas suponha que você não saiba; como você identifica o arquivo ou arquivos que estão ocupando tanto espaço? Se você executar `git gc`, todos os objetos estarão em um packfile; você pode identificar os objetos grandes, executando outro comando encanamento (plumbing) chamado `git verify-pack` e classificar pelo terceiro campo da saída, que é o tamanho do arquivo. Você também pode direcionar a saída (pipe) através do comando `tail` porque você está interessado apenas nos últimos poucos arquivos maiores:
922
+
923
+ $ git verify-pack -v .git/objects/pack/pack-3f8c0...bb.idx | sort -k 3 -n | tail -3
924
+ e3f094f522629ae358806b17daf78246c27c007b blob 1486 734 4667
925
+ 05408d195263d853f09dca71d55116663690c27c blob 12908 3478 1189
926
+ 7a9eb2fba2b1811321254ac360970fc169ba2330 blob 2056716 2056872 5401
927
+
928
+ O objeto grande está na parte inferior: 2MB. Para saber qual é o arquivo, você vai usar o comando `rev-list`, que você usou brevemente no *Capítulo 7*. Se você passar `--objects` para `rev-list`, ele lista todos os SHAs dos commits e também os SHAs dos blob com os caminhos de arquivos (paths) associados a eles. Você pode usar isso para encontrar o nome do blob:
929
+
930
+ $ git rev-list --objects --all | grep 7a9eb2fb
931
+ 7a9eb2fba2b1811321254ac360970fc169ba2330 git.tbz2
932
+
933
+ Agora, você precisa remover o arquivo de todas as árvores em que ele estiver. Você pode facilmente ver quais commits modificaram este arquivo:
934
+
935
+ $ git log --pretty=oneline --branches -- git.tbz2
936
+ da3f30d019005479c99eb4c3406225613985a1db oops - removed large tarball
937
+ 6df764092f3e7c8f5f94cbe08ee5cf42e92a0289 added git tarball
938
+
939
+ Você deve reescrever todos os commits desde `6df76` para remover completamente este arquivo do seu histórico Git. Para fazer isso, você usa `filter-branch`, que você já usou no *capítulo 6*:
940
+
941
+ $ git filter-branch --index-filter \
942
+ 'git rm --cached --ignore-unmatch git.tbz2' -- 6df7640^..
943
+ Rewrite 6df764092f3e7c8f5f94cbe08ee5cf42e92a0289 (1/2)rm 'git.tbz2'
944
+ Rewrite da3f30d019005479c99eb4c3406225613985a1db (2/2)
945
+ Ref 'refs/heads/master' was rewritten
946
+
947
+ A opção`--index-filter` é semelhante a opção `--tree-filter` utilizada no *Capítulo 6*, exceto que em vez de passar um comando que modifica os arquivos que você fez check-out no disco, você está modificando sua área de seleção (staging area) ou índice. Em vez de remover um arquivo específico com algo como `rm file`, você tem que removê-lo com `git rm --cached` — você deve removê-lo do índice, não do disco. A razão para fazê-lo desta maneira é a velocidade — porque o Git não precisa fazer o check out de cada revisão no disco antes de executar o seu filtro, o processo pode ser muito mais rápido. Você pode realizar a mesma tarefa com `--tree-filter` se você quiser. A opção `--ignore-unmatch` do `git rm` diz a ele para não mostrar erros se o padrão que você está tentando remover não estiver lá. Finalmente, você pede a `filter-branch` para reescrever seu histórico apenas a partir do commit `6df7640`, porque você sabe que é onde o problema começou. Caso contrário, ele vai começar desde o início e vai demorar mais tempo desnecessariamente.
948
+
949
+ Seu histórico já não contém uma referência para o arquivo. No entanto, seu reflog e um novo conjunto de refs que o git adicionou quando você fez o `filter-branch` em `.git/refs/original` ainda não, então você tem que removê-los e, em seguida, fazer um repack do banco de dados. Você precisa se ​​livrar de qualquer coisa que tenha um ponteiro para aqueles commits antigos antes de fazer o repack:
950
+
951
+ $ rm -Rf .git/refs/original
952
+ $ rm -Rf .git/logs/
953
+ $ git gc
954
+ Counting objects: 19, done.
955
+ Delta compression using 2 threads.
956
+ Compressing objects: 100% (14/14), done.
957
+ Writing objects: 100% (19/19), done.
958
+ Total 19 (delta 3), reused 16 (delta 1)
959
+
960
+ Vamos ver quanto espaço você economizou.
961
+
962
+ $ git count-objects -v
963
+ count: 8
964
+ size: 2040
965
+ in-pack: 19
966
+ packs: 1
967
+ size-pack: 7
968
+ prune-packable: 0
969
+ garbage: 0
970
+
971
+ O tamanho do repositório compactado reduziu para 7K, que é muito melhor do que 2MB. Pelo tamanho você pode ver que o grande objeto ainda está em seus objetos soltos, portanto não foi eliminado; mas ele não será transferido em um clone ou push posterior, e isso é o que importa. Se você realmente quiser, você pode remover o objeto completamente executando `git prune --expire`.
972
+
973
+ ## Resumo ##
974
+
975
+ Você deve ter uma compreensão muito boa do que Git faz de verdade e, até certo ponto, como ele é implementado. Este capítulo mostrou uma série de comandos de encanamento (plumbing) — comandos que são de nível inferior e mais simples do que os comandos de porcelana (porcelain) que você aprendeu no resto do livro. Compreender como Git funciona em um nível inferior deve torná-lo mais fácil de entender porque ele está fazendo o que está fazendo e também para escrever suas próprias ferramentas e scripts para criar seu próprio fluxo de trabalho.
976
+
977
+ Git como um sistema de arquivos de conteúdo endereçável é uma ferramenta muito poderosa que você pode usar facilmente como mais do que apenas um VCS. Eu espero que você possa usar seu novo conhecimento do Git para implementar a sua própria aplicação a partir desta tecnologia e se sentir mais confortável ​​usando Git de formas mais avançadas.
978
+