wayfarer 0.4.0 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (742) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +1 -1
  3. data/.rubocop.yml +10 -0
  4. data/Gemfile.lock +21 -16
  5. data/docs/cookbook/batch_routing.md +22 -0
  6. data/docs/cookbook/consent_screen.md +36 -0
  7. data/docs/cookbook/executing_javascript.md +41 -0
  8. data/docs/cookbook/navigation.md +43 -0
  9. data/docs/cookbook/querying_html.md +3 -3
  10. data/docs/cookbook/screenshots.md +2 -2
  11. data/docs/cookbook/user_agent.md +1 -1
  12. data/docs/guides/callbacks.md +122 -15
  13. data/docs/guides/configuration.md +16 -10
  14. data/docs/guides/debugging.md +17 -0
  15. data/docs/guides/error_handling.md +22 -22
  16. data/docs/guides/jobs.md +44 -18
  17. data/docs/guides/navigation.md +73 -0
  18. data/docs/guides/networking/capybara.md +71 -0
  19. data/docs/guides/networking/custom_adapters.md +100 -0
  20. data/docs/guides/{browser_automation → networking}/ferrum.md +6 -4
  21. data/docs/guides/networking/http.md +33 -0
  22. data/docs/guides/{browser_automation → networking}/selenium.md +11 -7
  23. data/docs/guides/networking.md +77 -3
  24. data/docs/guides/pages.md +4 -4
  25. data/docs/guides/performance.md +108 -0
  26. data/docs/guides/reliability.md +41 -0
  27. data/docs/guides/routing/steering.md +30 -0
  28. data/docs/guides/tasks.md +9 -33
  29. data/docs/index.md +9 -1
  30. data/docs/reference/api/base.md +13 -127
  31. data/docs/reference/api/route.md +1 -1
  32. data/docs/reference/cli.md +0 -78
  33. data/docs/reference/configuration_keys.md +42 -0
  34. data/docs/reference/environment_variables.md +25 -27
  35. data/lib/wayfarer/base.rb +32 -32
  36. data/lib/wayfarer/callbacks.rb +71 -0
  37. data/lib/wayfarer/cli/base.rb +23 -1
  38. data/lib/wayfarer/cli/job.rb +7 -9
  39. data/lib/wayfarer/cli/route.rb +6 -4
  40. data/lib/wayfarer/cli/route_printer.rb +7 -7
  41. data/lib/wayfarer/cli/templates/job.rb.tt +3 -1
  42. data/lib/wayfarer/config/capybara.rb +10 -0
  43. data/lib/wayfarer/config/ferrum.rb +11 -0
  44. data/lib/wayfarer/config/networking.rb +26 -0
  45. data/lib/wayfarer/config/redis.rb +14 -0
  46. data/lib/wayfarer/config/root.rb +11 -0
  47. data/lib/wayfarer/config/selenium.rb +21 -0
  48. data/lib/wayfarer/config/strconv.rb +45 -0
  49. data/lib/wayfarer/config/struct.rb +72 -0
  50. data/lib/wayfarer/gc.rb +3 -8
  51. data/lib/wayfarer/handler.rb +15 -0
  52. data/lib/wayfarer/middleware/base.rb +19 -0
  53. data/lib/wayfarer/middleware/chain.rb +8 -0
  54. data/lib/wayfarer/middleware/controller.rb +40 -0
  55. data/lib/wayfarer/middleware/dedup.rb +5 -0
  56. data/lib/wayfarer/middleware/dispatch.rb +22 -0
  57. data/lib/wayfarer/middleware/fetch.rb +35 -11
  58. data/lib/wayfarer/middleware/lazy.rb +11 -0
  59. data/lib/wayfarer/middleware/normalize.rb +2 -0
  60. data/lib/wayfarer/middleware/router.rb +41 -3
  61. data/lib/wayfarer/middleware/stage.rb +6 -2
  62. data/lib/wayfarer/networking/capybara.rb +28 -0
  63. data/lib/wayfarer/networking/context.rb +37 -0
  64. data/lib/wayfarer/networking/ferrum.rb +18 -52
  65. data/lib/wayfarer/networking/follow.rb +22 -0
  66. data/lib/wayfarer/networking/http.rb +34 -0
  67. data/lib/wayfarer/networking/pool.rb +20 -14
  68. data/lib/wayfarer/networking/result.rb +1 -9
  69. data/lib/wayfarer/networking/selenium.rb +20 -47
  70. data/lib/wayfarer/networking/strategy.rb +38 -0
  71. data/lib/wayfarer/page.rb +3 -4
  72. data/lib/wayfarer/redis/pool.rb +3 -1
  73. data/lib/wayfarer/routing/dsl.rb +8 -8
  74. data/lib/wayfarer/routing/matchers/custom.rb +25 -0
  75. data/lib/wayfarer/routing/matchers/host.rb +21 -0
  76. data/lib/wayfarer/routing/matchers/path.rb +49 -0
  77. data/lib/wayfarer/routing/matchers/query.rb +63 -0
  78. data/lib/wayfarer/routing/matchers/scheme.rb +17 -0
  79. data/lib/wayfarer/routing/matchers/suffix.rb +17 -0
  80. data/lib/wayfarer/routing/matchers/url.rb +17 -0
  81. data/lib/wayfarer/routing/result.rb +0 -5
  82. data/lib/wayfarer/routing/route.rb +7 -1
  83. data/lib/wayfarer/routing/router.rb +28 -0
  84. data/lib/wayfarer/stringify.rb +13 -7
  85. data/lib/wayfarer/task.rb +4 -2
  86. data/lib/wayfarer.rb +5 -10
  87. data/spec/base_spec.rb +45 -40
  88. data/spec/callbacks_spec.rb +102 -0
  89. data/spec/cli/job_spec.rb +11 -7
  90. data/spec/config/capybara_spec.rb +18 -0
  91. data/spec/config/ferrum_spec.rb +24 -0
  92. data/spec/config/networking_spec.rb +73 -0
  93. data/spec/config/redis_spec.rb +32 -0
  94. data/spec/config/root_spec.rb +31 -0
  95. data/spec/config/selenium_spec.rb +56 -0
  96. data/spec/config/strconv_spec.rb +58 -0
  97. data/spec/config/struct_spec.rb +66 -0
  98. data/spec/factories/{queue/middleware.rb → middleware.rb} +3 -3
  99. data/spec/factories/{queue/page.rb → page.rb} +3 -3
  100. data/spec/factories/{queue/task.rb → task.rb} +0 -0
  101. data/spec/fixtures/dummy_job.rb +1 -1
  102. data/spec/gc_spec.rb +5 -7
  103. data/spec/handler_spec.rb +11 -0
  104. data/spec/integration/callbacks_spec.rb +85 -0
  105. data/spec/integration/page_spec.rb +62 -0
  106. data/spec/integration/params_spec.rb +56 -0
  107. data/spec/integration/stage_spec.rb +51 -0
  108. data/spec/integration/steering_spec.rb +57 -0
  109. data/spec/middleware/chain_spec.rb +32 -19
  110. data/spec/middleware/controller_spec.rb +86 -0
  111. data/spec/middleware/dedup_spec.rb +20 -8
  112. data/spec/middleware/dispatch_spec.rb +43 -0
  113. data/spec/middleware/fetch_spec.rb +117 -34
  114. data/spec/middleware/normalize_spec.rb +5 -4
  115. data/spec/middleware/router_spec.rb +82 -23
  116. data/spec/middleware/stage_spec.rb +42 -19
  117. data/spec/networking/capybara_spec.rb +12 -0
  118. data/spec/networking/context_spec.rb +127 -0
  119. data/spec/networking/ferrum_spec.rb +6 -22
  120. data/spec/networking/follow_spec.rb +41 -0
  121. data/spec/networking/http_spec.rb +12 -0
  122. data/spec/networking/pool_spec.rb +37 -12
  123. data/spec/networking/selenium_spec.rb +6 -22
  124. data/spec/networking/strategy.rb +170 -0
  125. data/spec/redis/pool_spec.rb +1 -1
  126. data/spec/routing/dsl_spec.rb +10 -10
  127. data/spec/routing/integration_spec.rb +22 -22
  128. data/spec/routing/{custom_matcher_spec.rb → matchers/custom_spec.rb} +4 -4
  129. data/spec/routing/{host_matcher_spec.rb → matchers/host_spec.rb} +6 -6
  130. data/spec/routing/{path_matcher_spec.rb → matchers/path_spec.rb} +6 -6
  131. data/spec/routing/{query_matcher_spec.rb → matchers/query_spec.rb} +15 -15
  132. data/spec/routing/{scheme_matcher_spec.rb → matchers/scheme_spec.rb} +4 -4
  133. data/spec/routing/{suffix_matcher_spec.rb → matchers/suffix_spec.rb} +4 -4
  134. data/spec/routing/{uri_matcher_spec.rb → matchers/uri_spec.rb} +4 -4
  135. data/spec/routing/path_finder_spec.rb +1 -1
  136. data/spec/routing/root_route_spec.rb +2 -2
  137. data/spec/routing/route_spec.rb +2 -2
  138. data/spec/routing/router_spec.rb +24 -0
  139. data/spec/spec_helpers.rb +24 -8
  140. data/spec/support/static/git-scm.com/assets/application-38b0d42ff05ffea45841edebbd14b75b89585646153808e82907c2c5c11f324b.js +772 -0
  141. data/spec/support/static/git-scm.com/assets/application-cafcf280f67db0e6d8168ba98a38da878769a9d5f37793b68ffb963a02d185e0.css +1 -0
  142. data/spec/support/static/git-scm.com/assets/modernize-b3ebe0c31c24f230dc62179d3e1030d2e57a53b1668d9382c0a27dbd44a94beb.js +20 -0
  143. data/spec/support/static/git-scm.com/book/en/v2/Appendix-A:-Git-in-Other-Environments-Git-in-Bash.html +751 -0
  144. data/spec/support/static/git-scm.com/book/en/v2/Appendix-A:-Git-in-Other-Environments-Git-in-PowerShell.html +804 -0
  145. data/spec/support/static/git-scm.com/book/en/v2/Appendix-A:-Git-in-Other-Environments-Git-in-Sublime-Text.html +728 -0
  146. data/spec/support/static/git-scm.com/book/en/v2/Appendix-A:-Git-in-Other-Environments-Git-in-Visual-Studio-Code.html +751 -0
  147. data/spec/support/static/git-scm.com/book/en/v2/Appendix-A:-Git-in-Other-Environments-Git-in-Visual-Studio.html +740 -0
  148. data/spec/support/static/git-scm.com/book/en/v2/Appendix-A:-Git-in-Other-Environments-Git-in-Zsh.html +765 -0
  149. data/spec/support/static/git-scm.com/book/en/v2/Appendix-A:-Git-in-Other-Environments-Graphical-Interfaces.html +931 -0
  150. data/spec/support/static/git-scm.com/book/en/v2/Appendix-A:-Git-in-Other-Environments-Summary.html +702 -0
  151. data/spec/support/static/git-scm.com/book/en/v2/Appendix-B:-Embedding-Git-in-your-Applications-Command-line-Git.html +720 -0
  152. data/spec/support/static/git-scm.com/book/en/v2/Appendix-B:-Embedding-Git-in-your-Applications-Dulwich.html +746 -0
  153. data/spec/support/static/git-scm.com/book/en/v2/Appendix-B:-Embedding-Git-in-your-Applications-JGit.html +889 -0
  154. data/spec/support/static/git-scm.com/book/en/v2/Appendix-B:-Embedding-Git-in-your-Applications-Libgit2.html +1003 -0
  155. data/spec/support/static/git-scm.com/book/en/v2/Appendix-B:-Embedding-Git-in-your-Applications-go-git.html +792 -0
  156. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-Administration.html +745 -0
  157. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-Basic-Snapshotting.html +840 -0
  158. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-Branching-and-Merging.html +829 -0
  159. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-Debugging.html +731 -0
  160. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-Email.html +766 -0
  161. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-External-Systems.html +721 -0
  162. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-Getting-and-Creating-Projects.html +746 -0
  163. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-Inspection-and-Comparison.html +735 -0
  164. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-Patching.html +742 -0
  165. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-Plumbing-Commands.html +715 -0
  166. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-Setup-and-Config.html +863 -0
  167. data/spec/support/static/git-scm.com/book/en/v2/Appendix-C:-Git-Commands-Sharing-and-Updating-Projects.html +802 -0
  168. data/spec/support/static/git-scm.com/book/en/v2/Customizing-Git-An-Example-Git-Enforced-Policy.html +1200 -0
  169. data/spec/support/static/git-scm.com/book/en/v2/Customizing-Git-Git-Attributes.html +1134 -0
  170. data/spec/support/static/git-scm.com/book/en/v2/Customizing-Git-Git-Configuration.html +1315 -0
  171. data/spec/support/static/git-scm.com/book/en/v2/Customizing-Git-Git-Hooks.html +876 -0
  172. data/spec/support/static/git-scm.com/book/en/v2/Customizing-Git-Summary.html +704 -0
  173. data/spec/support/static/git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project.html +1667 -0
  174. data/spec/support/static/git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows.html +859 -0
  175. data/spec/support/static/git-scm.com/book/en/v2/Distributed-Git-Maintaining-a-Project.html +1354 -0
  176. data/spec/support/static/git-scm.com/book/en/v2/Distributed-Git-Summary.html +704 -0
  177. data/spec/support/static/git-scm.com/book/en/v2/Getting-Started-A-Short-History-of-Git.html +735 -0
  178. data/spec/support/static/git-scm.com/book/en/v2/Getting-Started-About-Version-Control.html +783 -0
  179. data/spec/support/static/git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup.html +889 -0
  180. data/spec/support/static/git-scm.com/book/en/v2/Getting-Started-Getting-Help.html +750 -0
  181. data/spec/support/static/git-scm.com/book/en/v2/Getting-Started-Installing-Git.html +879 -0
  182. data/spec/support/static/git-scm.com/book/en/v2/Getting-Started-Summary.html +704 -0
  183. data/spec/support/static/git-scm.com/book/en/v2/Getting-Started-The-Command-Line.html +711 -0
  184. data/spec/support/static/git-scm.com/book/en/v2/Getting-Started-What-is-Git?.html +857 -0
  185. data/spec/support/static/git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository.html +816 -0
  186. data/spec/support/static/git-scm.com/book/en/v2/Git-Basics-Git-Aliases.html +775 -0
  187. data/spec/support/static/git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository.html +1432 -0
  188. data/spec/support/static/git-scm.com/book/en/v2/Git-Basics-Summary.html +703 -0
  189. data/spec/support/static/git-scm.com/book/en/v2/Git-Basics-Tagging.html +1049 -0
  190. data/spec/support/static/git-scm.com/book/en/v2/Git-Basics-Undoing-Things.html +998 -0
  191. data/spec/support/static/git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History.html +1172 -0
  192. data/spec/support/static/git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes.html +983 -0
  193. data/spec/support/static/git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging.html +1102 -0
  194. data/spec/support/static/git-scm.com/book/en/v2/Git-Branching-Branch-Management.html +946 -0
  195. data/spec/support/static/git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell.html +1020 -0
  196. data/spec/support/static/git-scm.com/book/en/v2/Git-Branching-Branching-Workflows.html +786 -0
  197. data/spec/support/static/git-scm.com/book/en/v2/Git-Branching-Rebasing.html +1028 -0
  198. data/spec/support/static/git-scm.com/book/en/v2/Git-Branching-Remote-Branches.html +1009 -0
  199. data/spec/support/static/git-scm.com/book/en/v2/Git-Branching-Summary.html +705 -0
  200. data/spec/support/static/git-scm.com/book/en/v2/Git-Internals-Environment-Variables.html +1009 -0
  201. data/spec/support/static/git-scm.com/book/en/v2/Git-Internals-Git-Objects.html +1209 -0
  202. data/spec/support/static/git-scm.com/book/en/v2/Git-Internals-Git-References.html +939 -0
  203. data/spec/support/static/git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery.html +1086 -0
  204. data/spec/support/static/git-scm.com/book/en/v2/Git-Internals-Packfiles.html +876 -0
  205. data/spec/support/static/git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain.html +745 -0
  206. data/spec/support/static/git-scm.com/book/en/v2/Git-Internals-Summary.html +708 -0
  207. data/spec/support/static/git-scm.com/book/en/v2/Git-Internals-The-Refspec.html +872 -0
  208. data/spec/support/static/git-scm.com/book/en/v2/Git-Internals-Transfer-Protocols.html +1043 -0
  209. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Advanced-Merging.html +1605 -0
  210. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Bundling.html +888 -0
  211. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Credential-Storage.html +1035 -0
  212. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git.html +861 -0
  213. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Interactive-Staging.html +920 -0
  214. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Replace.html +949 -0
  215. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Rerere.html +983 -0
  216. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Reset-Demystified.html +1236 -0
  217. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Revision-Selection.html +1178 -0
  218. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Rewriting-History.html +1182 -0
  219. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Searching.html +875 -0
  220. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work.html +922 -0
  221. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Stashing-and-Cleaning.html +1039 -0
  222. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Submodules.html +1864 -0
  223. data/spec/support/static/git-scm.com/book/en/v2/Git-Tools-Summary.html +705 -0
  224. data/spec/support/static/git-scm.com/book/en/v2/Git-and-Other-Systems-Git-as-a-Client.html +2656 -0
  225. data/spec/support/static/git-scm.com/book/en/v2/Git-and-Other-Systems-Migrating-to-Git.html +1741 -0
  226. data/spec/support/static/git-scm.com/book/en/v2/Git-and-Other-Systems-Summary.html +703 -0
  227. data/spec/support/static/git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key.html +759 -0
  228. data/spec/support/static/git-scm.com/book/en/v2/Git-on-the-Server-Getting-Git-on-a-Server.html +827 -0
  229. data/spec/support/static/git-scm.com/book/en/v2/Git-on-the-Server-Git-Daemon.html +775 -0
  230. data/spec/support/static/git-scm.com/book/en/v2/Git-on-the-Server-GitLab.html +872 -0
  231. data/spec/support/static/git-scm.com/book/en/v2/Git-on-the-Server-GitWeb.html +776 -0
  232. data/spec/support/static/git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server.html +870 -0
  233. data/spec/support/static/git-scm.com/book/en/v2/Git-on-the-Server-Smart-HTTP.html +789 -0
  234. data/spec/support/static/git-scm.com/book/en/v2/Git-on-the-Server-Summary.html +709 -0
  235. data/spec/support/static/git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols.html +963 -0
  236. data/spec/support/static/git-scm.com/book/en/v2/Git-on-the-Server-Third-Party-Hosted-Options.html +711 -0
  237. data/spec/support/static/git-scm.com/book/en/v2/GitHub-Account-Setup-and-Configuration.html +858 -0
  238. data/spec/support/static/git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project.html +1502 -0
  239. data/spec/support/static/git-scm.com/book/en/v2/GitHub-Maintaining-a-Project.html +1218 -0
  240. data/spec/support/static/git-scm.com/book/en/v2/GitHub-Managing-an-organization.html +797 -0
  241. data/spec/support/static/git-scm.com/book/en/v2/GitHub-Scripting-GitHub.html +1059 -0
  242. data/spec/support/static/git-scm.com/book/en/v2/GitHub-Summary.html +704 -0
  243. data/spec/support/static/git-scm.com/book/en/v2/ch00/_abort_merge.html +1605 -0
  244. data/spec/support/static/git-scm.com/book/en/v2/ch00/_add_email_addresses.html +858 -0
  245. data/spec/support/static/git-scm.com/book/en/v2/ch00/_advanced_merging.html +1605 -0
  246. data/spec/support/static/git-scm.com/book/en/v2/ch00/_an_example_git_enforced_policy.html +1200 -0
  247. data/spec/support/static/git-scm.com/book/en/v2/ch00/_annotated_tags.html +1049 -0
  248. data/spec/support/static/git-scm.com/book/en/v2/ch00/_api_comment.html +1059 -0
  249. data/spec/support/static/git-scm.com/book/en/v2/ch00/_bare_repo.html +827 -0
  250. data/spec/support/static/git-scm.com/book/en/v2/ch00/_basic_branching.html +1102 -0
  251. data/spec/support/static/git-scm.com/book/en/v2/ch00/_basic_merge_conflicts.html +1102 -0
  252. data/spec/support/static/git-scm.com/book/en/v2/ch00/_basic_merging.html +1102 -0
  253. data/spec/support/static/git-scm.com/book/en/v2/ch00/_binary_search.html +861 -0
  254. data/spec/support/static/git-scm.com/book/en/v2/ch00/_branch_management.html +946 -0
  255. data/spec/support/static/git-scm.com/book/en/v2/ch00/_branch_references.html +1178 -0
  256. data/spec/support/static/git-scm.com/book/en/v2/ch00/_build_number.html +1354 -0
  257. data/spec/support/static/git-scm.com/book/en/v2/ch00/_bundling.html +888 -0
  258. data/spec/support/static/git-scm.com/book/en/v2/ch00/_changing_multiple.html +1182 -0
  259. data/spec/support/static/git-scm.com/book/en/v2/ch00/_checking_out_conflicts.html +1605 -0
  260. data/spec/support/static/git-scm.com/book/en/v2/ch00/_checking_out_remotes.html +1354 -0
  261. data/spec/support/static/git-scm.com/book/en/v2/ch00/_checking_status.html +1432 -0
  262. data/spec/support/static/git-scm.com/book/en/v2/ch00/_cloning_submodules.html +1864 -0
  263. data/spec/support/static/git-scm.com/book/en/v2/ch00/_commit_guidelines.html +1667 -0
  264. data/spec/support/static/git-scm.com/book/en/v2/ch00/_commit_ranges.html +1178 -0
  265. data/spec/support/static/git-scm.com/book/en/v2/ch00/_commit_status.html +1059 -0
  266. data/spec/support/static/git-scm.com/book/en/v2/ch00/_committing_changes.html +1432 -0
  267. data/spec/support/static/git-scm.com/book/en/v2/ch00/_contrib_file.html +1218 -0
  268. data/spec/support/static/git-scm.com/book/en/v2/ch00/_contributing_project.html +1667 -0
  269. data/spec/support/static/git-scm.com/book/en/v2/ch00/_create_new_branch.html +1020 -0
  270. data/spec/support/static/git-scm.com/book/en/v2/ch00/_credential_caching.html +1035 -0
  271. data/spec/support/static/git-scm.com/book/en/v2/ch00/_custom_importer.html +1741 -0
  272. data/spec/support/static/git-scm.com/book/en/v2/ch00/_data_recovery.html +1086 -0
  273. data/spec/support/static/git-scm.com/book/en/v2/ch00/_delete_branches.html +1009 -0
  274. data/spec/support/static/git-scm.com/book/en/v2/ch00/_editor.html +889 -0
  275. data/spec/support/static/git-scm.com/book/en/v2/ch00/_eg_task_lists.html +1502 -0
  276. data/spec/support/static/git-scm.com/book/en/v2/ch00/_email_hooks.html +876 -0
  277. data/spec/support/static/git-scm.com/book/en/v2/ch00/_email_notification.html +1502 -0
  278. data/spec/support/static/git-scm.com/book/en/v2/ch00/_email_notifications.html +1218 -0
  279. data/spec/support/static/git-scm.com/book/en/v2/ch00/_email_pr.html +1218 -0
  280. data/spec/support/static/git-scm.com/book/en/v2/ch00/_enforcing_commit_message_format.html +1200 -0
  281. data/spec/support/static/git-scm.com/book/en/v2/ch00/_example_markdown.html +1502 -0
  282. data/spec/support/static/git-scm.com/book/en/v2/ch00/_external_merge_tools.html +1315 -0
  283. data/spec/support/static/git-scm.com/book/en/v2/ch00/_fetch_and_push_on_different_repositories.html +1502 -0
  284. data/spec/support/static/git-scm.com/book/en/v2/ch00/_fetching_and_pulling.html +983 -0
  285. data/spec/support/static/git-scm.com/book/en/v2/ch00/_file_annotation.html +861 -0
  286. data/spec/support/static/git-scm.com/book/en/v2/ch00/_first_time.html +889 -0
  287. data/spec/support/static/git-scm.com/book/en/v2/ch00/_generate_ssh_key.html +759 -0
  288. data/spec/support/static/git-scm.com/book/en/v2/ch00/_getting_a_repo.html +816 -0
  289. data/spec/support/static/git-scm.com/book/en/v2/ch00/_getting_git_on_a_server.html +827 -0
  290. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_aliases.html +775 -0
  291. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_am.html +1354 -0
  292. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_amend.html +1182 -0
  293. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_branches_overview.html +1020 -0
  294. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_clean.html +1039 -0
  295. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_cloning.html +816 -0
  296. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_commit_objects.html +1209 -0
  297. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_config.html +1315 -0
  298. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_diff_staged.html +1432 -0
  299. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_gc.html +1086 -0
  300. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_grep.html +875 -0
  301. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_help.html +750 -0
  302. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_hooks.html +876 -0
  303. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_mv.html +1432 -0
  304. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_p4.html +1741 -0
  305. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_p4_branches.html +2656 -0
  306. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_reflog.html +1178 -0
  307. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_refs.html +939 -0
  308. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_reset.html +1236 -0
  309. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_stashing.html +1039 -0
  310. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_submodules.html +1864 -0
  311. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_svn.html +2656 -0
  312. data/spec/support/static/git-scm.com/book/en/v2/ch00/_git_tagging.html +1049 -0
  313. data/spec/support/static/git-scm.com/book/en/v2/ch00/_gitlab_groups_section.html +872 -0
  314. data/spec/support/static/git-scm.com/book/en/v2/ch00/_ignoring.html +1432 -0
  315. data/spec/support/static/git-scm.com/book/en/v2/ch00/_inspecting_remote.html +983 -0
  316. data/spec/support/static/git-scm.com/book/en/v2/ch00/_integration_manager.html +859 -0
  317. data/spec/support/static/git-scm.com/book/en/v2/ch00/_interactive_staging.html +920 -0
  318. data/spec/support/static/git-scm.com/book/en/v2/ch00/_keyword_expansion.html +1134 -0
  319. data/spec/support/static/git-scm.com/book/en/v2/ch00/_libgit2_bindings.html +1003 -0
  320. data/spec/support/static/git-scm.com/book/en/v2/ch00/_manual_remerge.html +1605 -0
  321. data/spec/support/static/git-scm.com/book/en/v2/ch00/_md_code.html +1502 -0
  322. data/spec/support/static/git-scm.com/book/en/v2/ch00/_md_drag.html +1502 -0
  323. data/spec/support/static/git-scm.com/book/en/v2/ch00/_md_emoji.html +1502 -0
  324. data/spec/support/static/git-scm.com/book/en/v2/ch00/_md_quote.html +1502 -0
  325. data/spec/support/static/git-scm.com/book/en/v2/ch00/_merge_button.html +1218 -0
  326. data/spec/support/static/git-scm.com/book/en/v2/ch00/_merge_log.html +1605 -0
  327. data/spec/support/static/git-scm.com/book/en/v2/ch00/_merge_rebase_work.html +1028 -0
  328. data/spec/support/static/git-scm.com/book/en/v2/ch00/_new_repo_dropdown.html +1218 -0
  329. data/spec/support/static/git-scm.com/book/en/v2/ch00/_not_center.html +1218 -0
  330. data/spec/support/static/git-scm.com/book/en/v2/ch00/_org_page.html +797 -0
  331. data/spec/support/static/git-scm.com/book/en/v2/ch00/_other_client_hooks.html +876 -0
  332. data/spec/support/static/git-scm.com/book/en/v2/ch00/_p4_git_fusion.html +2656 -0
  333. data/spec/support/static/git-scm.com/book/en/v2/ch00/_patches_from_email.html +1354 -0
  334. data/spec/support/static/git-scm.com/book/en/v2/ch00/_personal_avatar.html +858 -0
  335. data/spec/support/static/git-scm.com/book/en/v2/ch00/_plumbing_porcelain.html +745 -0
  336. data/spec/support/static/git-scm.com/book/en/v2/ch00/_pr_closed.html +1502 -0
  337. data/spec/support/static/git-scm.com/book/en/v2/ch00/_pr_discussion.html +1502 -0
  338. data/spec/support/static/git-scm.com/book/en/v2/ch00/_pr_fail.html +1502 -0
  339. data/spec/support/static/git-scm.com/book/en/v2/ch00/_pr_final.html +1502 -0
  340. data/spec/support/static/git-scm.com/book/en/v2/ch00/_pr_references.html +1502 -0
  341. data/spec/support/static/git-scm.com/book/en/v2/ch00/_pr_references_render.html +1502 -0
  342. data/spec/support/static/git-scm.com/book/en/v2/ch00/_pr_refs.html +1218 -0
  343. data/spec/support/static/git-scm.com/book/en/v2/ch00/_pre_merge_rebase_work.html +1028 -0
  344. data/spec/support/static/git-scm.com/book/en/v2/ch00/_preparing_release.html +1354 -0
  345. data/spec/support/static/git-scm.com/book/en/v2/ch00/_private_team.html +1667 -0
  346. data/spec/support/static/git-scm.com/book/en/v2/ch00/_project_over_email.html +1667 -0
  347. data/spec/support/static/git-scm.com/book/en/v2/ch00/_public_project.html +1667 -0
  348. data/spec/support/static/git-scm.com/book/en/v2/ch00/_publishing_submodules.html +1864 -0
  349. data/spec/support/static/git-scm.com/book/en/v2/ch00/_pushing_branches.html +1009 -0
  350. data/spec/support/static/git-scm.com/book/en/v2/ch00/_pushing_refspecs.html +872 -0
  351. data/spec/support/static/git-scm.com/book/en/v2/ch00/_pushing_remotes.html +983 -0
  352. data/spec/support/static/git-scm.com/book/en/v2/ch00/_rebase_cherry_pick.html +1354 -0
  353. data/spec/support/static/git-scm.com/book/en/v2/ch00/_rebase_peril.html +1028 -0
  354. data/spec/support/static/git-scm.com/book/en/v2/ch00/_rebase_rebase.html +1028 -0
  355. data/spec/support/static/git-scm.com/book/en/v2/ch00/_rebase_rebase_work.html +1028 -0
  356. data/spec/support/static/git-scm.com/book/en/v2/ch00/_rebasing.html +1028 -0
  357. data/spec/support/static/git-scm.com/book/en/v2/ch00/_refspec.html +872 -0
  358. data/spec/support/static/git-scm.com/book/en/v2/ch00/_remote_branches.html +1009 -0
  359. data/spec/support/static/git-scm.com/book/en/v2/ch00/_remote_repos.html +983 -0
  360. data/spec/support/static/git-scm.com/book/en/v2/ch00/_removing_file_every_commit.html +1182 -0
  361. data/spec/support/static/git-scm.com/book/en/v2/ch00/_removing_files.html +1432 -0
  362. data/spec/support/static/git-scm.com/book/en/v2/ch00/_removing_objects.html +1086 -0
  363. data/spec/support/static/git-scm.com/book/en/v2/ch00/_replace.html +949 -0
  364. data/spec/support/static/git-scm.com/book/en/v2/ch00/_reverse_commit.html +1605 -0
  365. data/spec/support/static/git-scm.com/book/en/v2/ch00/_revision_selection.html +1178 -0
  366. data/spec/support/static/git-scm.com/book/en/v2/ch00/_rewriting_history.html +1182 -0
  367. data/spec/support/static/git-scm.com/book/en/v2/ch00/_searching.html +875 -0
  368. data/spec/support/static/git-scm.com/book/en/v2/ch00/_service_config.html +1059 -0
  369. data/spec/support/static/git-scm.com/book/en/v2/ch00/_services_hooks.html +1059 -0
  370. data/spec/support/static/git-scm.com/book/en/v2/ch00/_setting_up_server.html +870 -0
  371. data/spec/support/static/git-scm.com/book/en/v2/ch00/_sharing_tags.html +1049 -0
  372. data/spec/support/static/git-scm.com/book/en/v2/ch00/_signing.html +922 -0
  373. data/spec/support/static/git-scm.com/book/en/v2/ch00/_signing_commits.html +922 -0
  374. data/spec/support/static/git-scm.com/book/en/v2/ch00/_squashing.html +1182 -0
  375. data/spec/support/static/git-scm.com/book/en/v2/ch00/_starting_submodules.html +1864 -0
  376. data/spec/support/static/git-scm.com/book/en/v2/ch00/_subtree_merge.html +1605 -0
  377. data/spec/support/static/git-scm.com/book/en/v2/ch00/_switching_branches.html +1020 -0
  378. data/spec/support/static/git-scm.com/book/en/v2/ch00/_tagging_releases.html +1354 -0
  379. data/spec/support/static/git-scm.com/book/en/v2/ch00/_task_list_progress.html +1502 -0
  380. data/spec/support/static/git-scm.com/book/en/v2/ch00/_team_page.html +797 -0
  381. data/spec/support/static/git-scm.com/book/en/v2/ch00/_the_index.html +1236 -0
  382. data/spec/support/static/git-scm.com/book/en/v2/ch00/_the_shortlog.html +1354 -0
  383. data/spec/support/static/git-scm.com/book/en/v2/ch00/_topic_branch.html +786 -0
  384. data/spec/support/static/git-scm.com/book/en/v2/ch00/_tracking_branches.html +1009 -0
  385. data/spec/support/static/git-scm.com/book/en/v2/ch00/_tracking_files.html +1432 -0
  386. data/spec/support/static/git-scm.com/book/en/v2/ch00/_tree_objects.html +1209 -0
  387. data/spec/support/static/git-scm.com/book/en/v2/ch00/_triple_dot.html +1178 -0
  388. data/spec/support/static/git-scm.com/book/en/v2/ch00/_undoing.html +998 -0
  389. data/spec/support/static/git-scm.com/book/en/v2/ch00/_unstaging.html +998 -0
  390. data/spec/support/static/git-scm.com/book/en/v2/ch00/_viewing_history.html +1172 -0
  391. data/spec/support/static/git-scm.com/book/en/v2/ch00/_web_hook.html +1059 -0
  392. data/spec/support/static/git-scm.com/book/en/v2/ch00/_what_is_introduced.html +1354 -0
  393. data/spec/support/static/git-scm.com/book/en/v2/ch00/ch01-getting-started.html +783 -0
  394. data/spec/support/static/git-scm.com/book/en/v2/ch00/ch02-git-basics-chapter.html +816 -0
  395. data/spec/support/static/git-scm.com/book/en/v2/ch00/ch03-git-branching.html +1020 -0
  396. data/spec/support/static/git-scm.com/book/en/v2/ch00/ch05-distributed-git.html +859 -0
  397. data/spec/support/static/git-scm.com/book/en/v2/ch00/ch06-github.html +858 -0
  398. data/spec/support/static/git-scm.com/book/en/v2/ch00/ch06-github_flow.html +1502 -0
  399. data/spec/support/static/git-scm.com/book/en/v2/ch00/ch10-git-internals.html +745 -0
  400. data/spec/support/static/git-scm.com/book/en/v2/ch00/ch_core_editor.html +863 -0
  401. data/spec/support/static/git-scm.com/book/en/v2/ch00/divergent_history.html +1020 -0
  402. data/spec/support/static/git-scm.com/book/en/v2/ch00/double_dot.html +1178 -0
  403. data/spec/support/static/git-scm.com/book/en/v2/ch00/filters_a.html +1134 -0
  404. data/spec/support/static/git-scm.com/book/en/v2/ch00/filters_b.html +1134 -0
  405. data/spec/support/static/git-scm.com/book/en/v2/ch00/limit_options.html +1172 -0
  406. data/spec/support/static/git-scm.com/book/en/v2/ch00/log_options.html +1172 -0
  407. data/spec/support/static/git-scm.com/book/en/v2/ch00/merwf_a.html +1354 -0
  408. data/spec/support/static/git-scm.com/book/en/v2/ch00/merwf_b.html +1354 -0
  409. data/spec/support/static/git-scm.com/book/en/v2/ch00/merwf_c.html +1354 -0
  410. data/spec/support/static/git-scm.com/book/en/v2/ch00/merwf_d.html +1354 -0
  411. data/spec/support/static/git-scm.com/book/en/v2/ch00/merwf_e.html +1354 -0
  412. data/spec/support/static/git-scm.com/book/en/v2/ch00/merwf_f.html +1354 -0
  413. data/spec/support/static/git-scm.com/book/en/v2/ch00/oh_my_zsh_git.html +765 -0
  414. data/spec/support/static/git-scm.com/book/en/v2/ch00/pretty_format.html +1172 -0
  415. data/spec/support/static/git-scm.com/book/en/v2/ch00/psp_b.html +1667 -0
  416. data/spec/support/static/git-scm.com/book/en/v2/ch00/rbdiag_e.html +1028 -0
  417. data/spec/support/static/git-scm.com/book/en/v2/ch00/rbdiag_g.html +1028 -0
  418. data/spec/support/static/git-scm.com/book/en/v2/ch00/rbdiag_h.html +1028 -0
  419. data/spec/support/static/git-scm.com/book/en/v2/ch00/rbdiag_i.html +1028 -0
  420. data/spec/support/static/git-scm.com/book/en/v2/ch00/rebasing-merging-example.html +1028 -0
  421. data/spec/support/static/git-scm.com/book/en/v2/ch00/ref_rerere.html +983 -0
  422. data/spec/support/static/git-scm.com/book/en/v2/ch00/ref_the_ref.html +939 -0
  423. data/spec/support/static/git-scm.com/book/en/v2/ch00/wfdiag_b.html +859 -0
  424. data/spec/support/static/git-scm.com/book/en/v2/ch00/wfdiag_c.html +859 -0
  425. data/spec/support/static/git-scm.com/book/en/v2/ch00/what_is_git_section.html +857 -0
  426. data/spec/support/static/git-scm.com/book/en/v2/images/2fa-1.png +0 -0
  427. data/spec/support/static/git-scm.com/book/en/v2/images/account-settings.png +0 -0
  428. data/spec/support/static/git-scm.com/book/en/v2/images/advance-master.png +0 -0
  429. data/spec/support/static/git-scm.com/book/en/v2/images/advance-testing.png +0 -0
  430. data/spec/support/static/git-scm.com/book/en/v2/images/areas.png +0 -0
  431. data/spec/support/static/git-scm.com/book/en/v2/images/avatar-crop.png +0 -0
  432. data/spec/support/static/git-scm.com/book/en/v2/images/basic-branching-1.png +0 -0
  433. data/spec/support/static/git-scm.com/book/en/v2/images/basic-branching-2.png +0 -0
  434. data/spec/support/static/git-scm.com/book/en/v2/images/basic-branching-3.png +0 -0
  435. data/spec/support/static/git-scm.com/book/en/v2/images/basic-branching-4.png +0 -0
  436. data/spec/support/static/git-scm.com/book/en/v2/images/basic-branching-5.png +0 -0
  437. data/spec/support/static/git-scm.com/book/en/v2/images/basic-branching-6.png +0 -0
  438. data/spec/support/static/git-scm.com/book/en/v2/images/basic-merging-1.png +0 -0
  439. data/spec/support/static/git-scm.com/book/en/v2/images/basic-merging-2.png +0 -0
  440. data/spec/support/static/git-scm.com/book/en/v2/images/basic-rebase-1.png +0 -0
  441. data/spec/support/static/git-scm.com/book/en/v2/images/basic-rebase-2.png +0 -0
  442. data/spec/support/static/git-scm.com/book/en/v2/images/basic-rebase-3.png +0 -0
  443. data/spec/support/static/git-scm.com/book/en/v2/images/basic-rebase-4.png +0 -0
  444. data/spec/support/static/git-scm.com/book/en/v2/images/benevolent-dictator.png +0 -0
  445. data/spec/support/static/git-scm.com/book/en/v2/images/blink-01-start.png +0 -0
  446. data/spec/support/static/git-scm.com/book/en/v2/images/blink-02-pr.png +0 -0
  447. data/spec/support/static/git-scm.com/book/en/v2/images/blink-03-pull-request-open.png +0 -0
  448. data/spec/support/static/git-scm.com/book/en/v2/images/blink-04-email.png +0 -0
  449. data/spec/support/static/git-scm.com/book/en/v2/images/blink-04-pr-comment.png +0 -0
  450. data/spec/support/static/git-scm.com/book/en/v2/images/blink-05-general-comment.png +0 -0
  451. data/spec/support/static/git-scm.com/book/en/v2/images/blink-06-final.png +0 -0
  452. data/spec/support/static/git-scm.com/book/en/v2/images/branch-and-history.png +0 -0
  453. data/spec/support/static/git-scm.com/book/en/v2/images/branch_widget_mac.png +0 -0
  454. data/spec/support/static/git-scm.com/book/en/v2/images/branch_widget_win.png +0 -0
  455. data/spec/support/static/git-scm.com/book/en/v2/images/centralized.png +0 -0
  456. data/spec/support/static/git-scm.com/book/en/v2/images/centralized_workflow.png +0 -0
  457. data/spec/support/static/git-scm.com/book/en/v2/images/checkout-master.png +0 -0
  458. data/spec/support/static/git-scm.com/book/en/v2/images/clean.png +0 -0
  459. data/spec/support/static/git-scm.com/book/en/v2/images/collaborators.png +0 -0
  460. data/spec/support/static/git-scm.com/book/en/v2/images/commit-and-tree.png +0 -0
  461. data/spec/support/static/git-scm.com/book/en/v2/images/commits-and-parents.png +0 -0
  462. data/spec/support/static/git-scm.com/book/en/v2/images/data-model-1.png +0 -0
  463. data/spec/support/static/git-scm.com/book/en/v2/images/data-model-2.png +0 -0
  464. data/spec/support/static/git-scm.com/book/en/v2/images/data-model-3.png +0 -0
  465. data/spec/support/static/git-scm.com/book/en/v2/images/data-model-4.png +0 -0
  466. data/spec/support/static/git-scm.com/book/en/v2/images/deltas.png +0 -0
  467. data/spec/support/static/git-scm.com/book/en/v2/images/distributed.png +0 -0
  468. data/spec/support/static/git-scm.com/book/en/v2/images/double-dot.png +0 -0
  469. data/spec/support/static/git-scm.com/book/en/v2/images/email-settings.png +0 -0
  470. data/spec/support/static/git-scm.com/book/en/v2/images/forkbutton.png +0 -0
  471. data/spec/support/static/git-scm.com/book/en/v2/images/git-bash.png +0 -0
  472. data/spec/support/static/git-scm.com/book/en/v2/images/git-diff-check.png +0 -0
  473. data/spec/support/static/git-scm.com/book/en/v2/images/git-fusion-boot.png +0 -0
  474. data/spec/support/static/git-scm.com/book/en/v2/images/git-fusion-perforce-graph.png +0 -0
  475. data/spec/support/static/git-scm.com/book/en/v2/images/git-gui.png +0 -0
  476. data/spec/support/static/git-scm.com/book/en/v2/images/git-instaweb.png +0 -0
  477. data/spec/support/static/git-scm.com/book/en/v2/images/git-osx-installer.png +0 -0
  478. data/spec/support/static/git-scm.com/book/en/v2/images/github_mac.png +0 -0
  479. data/spec/support/static/git-scm.com/book/en/v2/images/github_win.png +0 -0
  480. data/spec/support/static/git-scm.com/book/en/v2/images/gitk.png +0 -0
  481. data/spec/support/static/git-scm.com/book/en/v2/images/gitlab-groups.png +0 -0
  482. data/spec/support/static/git-scm.com/book/en/v2/images/gitlab-menu.png +0 -0
  483. data/spec/support/static/git-scm.com/book/en/v2/images/gitlab-users.png +0 -0
  484. data/spec/support/static/git-scm.com/book/en/v2/images/head-to-master.png +0 -0
  485. data/spec/support/static/git-scm.com/book/en/v2/images/head-to-testing.png +0 -0
  486. data/spec/support/static/git-scm.com/book/en/v2/images/integration-manager.png +0 -0
  487. data/spec/support/static/git-scm.com/book/en/v2/images/interesting-rebase-1.png +0 -0
  488. data/spec/support/static/git-scm.com/book/en/v2/images/interesting-rebase-2.png +0 -0
  489. data/spec/support/static/git-scm.com/book/en/v2/images/interesting-rebase-3.png +0 -0
  490. data/spec/support/static/git-scm.com/book/en/v2/images/interesting-rebase-4.png +0 -0
  491. data/spec/support/static/git-scm.com/book/en/v2/images/interesting-rebase-5.png +0 -0
  492. data/spec/support/static/git-scm.com/book/en/v2/images/jb.png +0 -0
  493. data/spec/support/static/git-scm.com/book/en/v2/images/large-merges-1.png +0 -0
  494. data/spec/support/static/git-scm.com/book/en/v2/images/large-merges-2.png +0 -0
  495. data/spec/support/static/git-scm.com/book/en/v2/images/lifecycle.png +0 -0
  496. data/spec/support/static/git-scm.com/book/en/v2/images/local.png +0 -0
  497. data/spec/support/static/git-scm.com/book/en/v2/images/lr-branches-1.png +0 -0
  498. data/spec/support/static/git-scm.com/book/en/v2/images/lr-branches-2.png +0 -0
  499. data/spec/support/static/git-scm.com/book/en/v2/images/maint-01-email.png +0 -0
  500. data/spec/support/static/git-scm.com/book/en/v2/images/maint-02-merge.png +0 -0
  501. data/spec/support/static/git-scm.com/book/en/v2/images/maint-03-email-resp.png +0 -0
  502. data/spec/support/static/git-scm.com/book/en/v2/images/maint-04-target.png +0 -0
  503. data/spec/support/static/git-scm.com/book/en/v2/images/maint-05-mentions.png +0 -0
  504. data/spec/support/static/git-scm.com/book/en/v2/images/maint-06-unsubscribe.png +0 -0
  505. data/spec/support/static/git-scm.com/book/en/v2/images/maint-07-notifications.png +0 -0
  506. data/spec/support/static/git-scm.com/book/en/v2/images/maint-08-notifications-page.png +0 -0
  507. data/spec/support/static/git-scm.com/book/en/v2/images/maint-09-contrib.png +0 -0
  508. data/spec/support/static/git-scm.com/book/en/v2/images/maint-10-default-branch.png +0 -0
  509. data/spec/support/static/git-scm.com/book/en/v2/images/maint-11-transfer.png +0 -0
  510. data/spec/support/static/git-scm.com/book/en/v2/images/managed-team-1.png +0 -0
  511. data/spec/support/static/git-scm.com/book/en/v2/images/managed-team-2.png +0 -0
  512. data/spec/support/static/git-scm.com/book/en/v2/images/managed-team-3.png +0 -0
  513. data/spec/support/static/git-scm.com/book/en/v2/images/managed-team-flow.png +0 -0
  514. data/spec/support/static/git-scm.com/book/en/v2/images/markdown-01-example.png +0 -0
  515. data/spec/support/static/git-scm.com/book/en/v2/images/markdown-02-tasks.png +0 -0
  516. data/spec/support/static/git-scm.com/book/en/v2/images/markdown-03-task-summary.png +0 -0
  517. data/spec/support/static/git-scm.com/book/en/v2/images/markdown-04-fenced-code.png +0 -0
  518. data/spec/support/static/git-scm.com/book/en/v2/images/markdown-05-quote.png +0 -0
  519. data/spec/support/static/git-scm.com/book/en/v2/images/markdown-06-emoji-complete.png +0 -0
  520. data/spec/support/static/git-scm.com/book/en/v2/images/markdown-07-emoji.png +0 -0
  521. data/spec/support/static/git-scm.com/book/en/v2/images/markdown-08-drag-drop.png +0 -0
  522. data/spec/support/static/git-scm.com/book/en/v2/images/mentions-01-syntax.png +0 -0
  523. data/spec/support/static/git-scm.com/book/en/v2/images/mentions-02-render.png +0 -0
  524. data/spec/support/static/git-scm.com/book/en/v2/images/mentions-03-closed.png +0 -0
  525. data/spec/support/static/git-scm.com/book/en/v2/images/merging-workflows-1.png +0 -0
  526. data/spec/support/static/git-scm.com/book/en/v2/images/merging-workflows-2.png +0 -0
  527. data/spec/support/static/git-scm.com/book/en/v2/images/merging-workflows-3.png +0 -0
  528. data/spec/support/static/git-scm.com/book/en/v2/images/merging-workflows-4.png +0 -0
  529. data/spec/support/static/git-scm.com/book/en/v2/images/merging-workflows-5.png +0 -0
  530. data/spec/support/static/git-scm.com/book/en/v2/images/new-repo.png +0 -0
  531. data/spec/support/static/git-scm.com/book/en/v2/images/neworg.png +0 -0
  532. data/spec/support/static/git-scm.com/book/en/v2/images/newrepo.png +0 -0
  533. data/spec/support/static/git-scm.com/book/en/v2/images/newrepoform.png +0 -0
  534. data/spec/support/static/git-scm.com/book/en/v2/images/orgs-01-page.png +0 -0
  535. data/spec/support/static/git-scm.com/book/en/v2/images/orgs-02-teams.png +0 -0
  536. data/spec/support/static/git-scm.com/book/en/v2/images/orgs-03-audit.png +0 -0
  537. data/spec/support/static/git-scm.com/book/en/v2/images/p4merge.png +0 -0
  538. data/spec/support/static/git-scm.com/book/en/v2/images/perils-of-rebasing-1.png +0 -0
  539. data/spec/support/static/git-scm.com/book/en/v2/images/perils-of-rebasing-2.png +0 -0
  540. data/spec/support/static/git-scm.com/book/en/v2/images/perils-of-rebasing-3.png +0 -0
  541. data/spec/support/static/git-scm.com/book/en/v2/images/perils-of-rebasing-4.png +0 -0
  542. data/spec/support/static/git-scm.com/book/en/v2/images/perils-of-rebasing-5.png +0 -0
  543. data/spec/support/static/git-scm.com/book/en/v2/images/posh-git.png +0 -0
  544. data/spec/support/static/git-scm.com/book/en/v2/images/pr-01-fail.png +0 -0
  545. data/spec/support/static/git-scm.com/book/en/v2/images/pr-02-merge-fix.png +0 -0
  546. data/spec/support/static/git-scm.com/book/en/v2/images/public-small-1.png +0 -0
  547. data/spec/support/static/git-scm.com/book/en/v2/images/public-small-2.png +0 -0
  548. data/spec/support/static/git-scm.com/book/en/v2/images/public-small-3.png +0 -0
  549. data/spec/support/static/git-scm.com/book/en/v2/images/rebasing-1.png +0 -0
  550. data/spec/support/static/git-scm.com/book/en/v2/images/rebasing-2.png +0 -0
  551. data/spec/support/static/git-scm.com/book/en/v2/images/remote-branches-1.png +0 -0
  552. data/spec/support/static/git-scm.com/book/en/v2/images/remote-branches-2.png +0 -0
  553. data/spec/support/static/git-scm.com/book/en/v2/images/remote-branches-3.png +0 -0
  554. data/spec/support/static/git-scm.com/book/en/v2/images/remote-branches-4.png +0 -0
  555. data/spec/support/static/git-scm.com/book/en/v2/images/remote-branches-5.png +0 -0
  556. data/spec/support/static/git-scm.com/book/en/v2/images/replace1.png +0 -0
  557. data/spec/support/static/git-scm.com/book/en/v2/images/replace2.png +0 -0
  558. data/spec/support/static/git-scm.com/book/en/v2/images/replace3.png +0 -0
  559. data/spec/support/static/git-scm.com/book/en/v2/images/replace4.png +0 -0
  560. data/spec/support/static/git-scm.com/book/en/v2/images/replace5.png +0 -0
  561. data/spec/support/static/git-scm.com/book/en/v2/images/reposettingslink.png +0 -0
  562. data/spec/support/static/git-scm.com/book/en/v2/images/rerere1.png +0 -0
  563. data/spec/support/static/git-scm.com/book/en/v2/images/rerere2.png +0 -0
  564. data/spec/support/static/git-scm.com/book/en/v2/images/rerere3.png +0 -0
  565. data/spec/support/static/git-scm.com/book/en/v2/images/reset-checkout.png +0 -0
  566. data/spec/support/static/git-scm.com/book/en/v2/images/reset-ex1.png +0 -0
  567. data/spec/support/static/git-scm.com/book/en/v2/images/reset-ex2.png +0 -0
  568. data/spec/support/static/git-scm.com/book/en/v2/images/reset-ex3.png +0 -0
  569. data/spec/support/static/git-scm.com/book/en/v2/images/reset-ex4.png +0 -0
  570. data/spec/support/static/git-scm.com/book/en/v2/images/reset-ex5.png +0 -0
  571. data/spec/support/static/git-scm.com/book/en/v2/images/reset-ex6.png +0 -0
  572. data/spec/support/static/git-scm.com/book/en/v2/images/reset-hard.png +0 -0
  573. data/spec/support/static/git-scm.com/book/en/v2/images/reset-mixed.png +0 -0
  574. data/spec/support/static/git-scm.com/book/en/v2/images/reset-path1.png +0 -0
  575. data/spec/support/static/git-scm.com/book/en/v2/images/reset-path2.png +0 -0
  576. data/spec/support/static/git-scm.com/book/en/v2/images/reset-path3.png +0 -0
  577. data/spec/support/static/git-scm.com/book/en/v2/images/reset-soft.png +0 -0
  578. data/spec/support/static/git-scm.com/book/en/v2/images/reset-squash-r1.png +0 -0
  579. data/spec/support/static/git-scm.com/book/en/v2/images/reset-squash-r2.png +0 -0
  580. data/spec/support/static/git-scm.com/book/en/v2/images/reset-squash-r3.png +0 -0
  581. data/spec/support/static/git-scm.com/book/en/v2/images/reset-start.png +0 -0
  582. data/spec/support/static/git-scm.com/book/en/v2/images/reset-workflow.png +0 -0
  583. data/spec/support/static/git-scm.com/book/en/v2/images/scripting-01-services.png +0 -0
  584. data/spec/support/static/git-scm.com/book/en/v2/images/scripting-02-email-service.png +0 -0
  585. data/spec/support/static/git-scm.com/book/en/v2/images/scripting-03-webhook.png +0 -0
  586. data/spec/support/static/git-scm.com/book/en/v2/images/scripting-04-webhook-debug.png +0 -0
  587. data/spec/support/static/git-scm.com/book/en/v2/images/scripting-05-access-token.png +0 -0
  588. data/spec/support/static/git-scm.com/book/en/v2/images/scripting-06-comment.png +0 -0
  589. data/spec/support/static/git-scm.com/book/en/v2/images/scripting-07-status.png +0 -0
  590. data/spec/support/static/git-scm.com/book/en/v2/images/signup.png +0 -0
  591. data/spec/support/static/git-scm.com/book/en/v2/images/small-team-1.png +0 -0
  592. data/spec/support/static/git-scm.com/book/en/v2/images/small-team-2.png +0 -0
  593. data/spec/support/static/git-scm.com/book/en/v2/images/small-team-3.png +0 -0
  594. data/spec/support/static/git-scm.com/book/en/v2/images/small-team-4.png +0 -0
  595. data/spec/support/static/git-scm.com/book/en/v2/images/small-team-5.png +0 -0
  596. data/spec/support/static/git-scm.com/book/en/v2/images/small-team-6.png +0 -0
  597. data/spec/support/static/git-scm.com/book/en/v2/images/small-team-7.png +0 -0
  598. data/spec/support/static/git-scm.com/book/en/v2/images/small-team-flow.png +0 -0
  599. data/spec/support/static/git-scm.com/book/en/v2/images/smudge.png +0 -0
  600. data/spec/support/static/git-scm.com/book/en/v2/images/snapshots.png +0 -0
  601. data/spec/support/static/git-scm.com/book/en/v2/images/ssh-keys.png +0 -0
  602. data/spec/support/static/git-scm.com/book/en/v2/images/topic-branches-1.png +0 -0
  603. data/spec/support/static/git-scm.com/book/en/v2/images/topic-branches-2.png +0 -0
  604. data/spec/support/static/git-scm.com/book/en/v2/images/two-branches.png +0 -0
  605. data/spec/support/static/git-scm.com/book/en/v2/images/undomerge-reset.png +0 -0
  606. data/spec/support/static/git-scm.com/book/en/v2/images/undomerge-revert.png +0 -0
  607. data/spec/support/static/git-scm.com/book/en/v2/images/undomerge-revert2.png +0 -0
  608. data/spec/support/static/git-scm.com/book/en/v2/images/undomerge-revert3.png +0 -0
  609. data/spec/support/static/git-scm.com/book/en/v2/images/undomerge-start.png +0 -0
  610. data/spec/support/static/git-scm.com/book/en/v2/images/your-profile.png +0 -0
  611. data/spec/support/static/git-scm.com/book/en/v2/images/zsh-oh-my.png +0 -0
  612. data/spec/support/static/git-scm.com/book/en/v2/images/zsh-prompt.png +0 -0
  613. data/spec/support/static/git-scm.com/book/en/v2.html +688 -0
  614. data/spec/support/static/git-scm.com/favicon.ico +0 -0
  615. data/spec/support/static/git-scm.com/images/bg/body.jpg +0 -0
  616. data/spec/support/static/git-scm.com/images/bg/isometric-grid.png +0 -0
  617. data/spec/support/static/git-scm.com/images/bg/isometric-grid@2x.png +0 -0
  618. data/spec/support/static/git-scm.com/images/bg/search-header.jpg +0 -0
  619. data/spec/support/static/git-scm.com/images/company-project-logos/android.png +0 -0
  620. data/spec/support/static/git-scm.com/images/company-project-logos/android@2x.png +0 -0
  621. data/spec/support/static/git-scm.com/images/company-project-logos/eclipse.png +0 -0
  622. data/spec/support/static/git-scm.com/images/company-project-logos/eclipse@2x.png +0 -0
  623. data/spec/support/static/git-scm.com/images/company-project-logos/facebook.png +0 -0
  624. data/spec/support/static/git-scm.com/images/company-project-logos/facebook@2x.png +0 -0
  625. data/spec/support/static/git-scm.com/images/company-project-logos/gnome.png +0 -0
  626. data/spec/support/static/git-scm.com/images/company-project-logos/gnome@2x.png +0 -0
  627. data/spec/support/static/git-scm.com/images/company-project-logos/google.png +0 -0
  628. data/spec/support/static/git-scm.com/images/company-project-logos/google@2x.png +0 -0
  629. data/spec/support/static/git-scm.com/images/company-project-logos/kde.png +0 -0
  630. data/spec/support/static/git-scm.com/images/company-project-logos/kde@2x.png +0 -0
  631. data/spec/support/static/git-scm.com/images/company-project-logos/linked-in.png +0 -0
  632. data/spec/support/static/git-scm.com/images/company-project-logos/linked-in@2x.png +0 -0
  633. data/spec/support/static/git-scm.com/images/company-project-logos/linux.png +0 -0
  634. data/spec/support/static/git-scm.com/images/company-project-logos/linux@2x.png +0 -0
  635. data/spec/support/static/git-scm.com/images/company-project-logos/microsoft.png +0 -0
  636. data/spec/support/static/git-scm.com/images/company-project-logos/microsoft@2x.png +0 -0
  637. data/spec/support/static/git-scm.com/images/company-project-logos/netflix.png +0 -0
  638. data/spec/support/static/git-scm.com/images/company-project-logos/netflix@2x.png +0 -0
  639. data/spec/support/static/git-scm.com/images/company-project-logos/perl.png +0 -0
  640. data/spec/support/static/git-scm.com/images/company-project-logos/perl@2x.png +0 -0
  641. data/spec/support/static/git-scm.com/images/company-project-logos/postgresql.png +0 -0
  642. data/spec/support/static/git-scm.com/images/company-project-logos/postgresql@2x.png +0 -0
  643. data/spec/support/static/git-scm.com/images/company-project-logos/qt.png +0 -0
  644. data/spec/support/static/git-scm.com/images/company-project-logos/qt@2x.png +0 -0
  645. data/spec/support/static/git-scm.com/images/company-project-logos/rails.png +0 -0
  646. data/spec/support/static/git-scm.com/images/company-project-logos/rails@2x.png +0 -0
  647. data/spec/support/static/git-scm.com/images/company-project-logos/twitter.png +0 -0
  648. data/spec/support/static/git-scm.com/images/company-project-logos/twitter@2x.png +0 -0
  649. data/spec/support/static/git-scm.com/images/company-project-logos/x.png +0 -0
  650. data/spec/support/static/git-scm.com/images/company-project-logos/x@2x.png +0 -0
  651. data/spec/support/static/git-scm.com/images/epub.png +0 -0
  652. data/spec/support/static/git-scm.com/images/icons/admin-sm.png +0 -0
  653. data/spec/support/static/git-scm.com/images/icons/admin-sm@2x.png +0 -0
  654. data/spec/support/static/git-scm.com/images/icons/apple.png +0 -0
  655. data/spec/support/static/git-scm.com/images/icons/apple@2x.png +0 -0
  656. data/spec/support/static/git-scm.com/images/icons/book.png +0 -0
  657. data/spec/support/static/git-scm.com/images/icons/book@2x.png +0 -0
  658. data/spec/support/static/git-scm.com/images/icons/box.png +0 -0
  659. data/spec/support/static/git-scm.com/images/icons/box@2x.png +0 -0
  660. data/spec/support/static/git-scm.com/images/icons/branch-sm.png +0 -0
  661. data/spec/support/static/git-scm.com/images/icons/branch-sm@2x.png +0 -0
  662. data/spec/support/static/git-scm.com/images/icons/camera-sm.png +0 -0
  663. data/spec/support/static/git-scm.com/images/icons/camera-sm@2x.png +0 -0
  664. data/spec/support/static/git-scm.com/images/icons/chevron-up@2x.png +0 -0
  665. data/spec/support/static/git-scm.com/images/icons/code.png +0 -0
  666. data/spec/support/static/git-scm.com/images/icons/code@2x.png +0 -0
  667. data/spec/support/static/git-scm.com/images/icons/debugging-sm.png +0 -0
  668. data/spec/support/static/git-scm.com/images/icons/debugging-sm@2x.png +0 -0
  669. data/spec/support/static/git-scm.com/images/icons/document.png +0 -0
  670. data/spec/support/static/git-scm.com/images/icons/document@2x.png +0 -0
  671. data/spec/support/static/git-scm.com/images/icons/download.png +0 -0
  672. data/spec/support/static/git-scm.com/images/icons/email-sm.png +0 -0
  673. data/spec/support/static/git-scm.com/images/icons/email-sm@2x.png +0 -0
  674. data/spec/support/static/git-scm.com/images/icons/external-sm.png +0 -0
  675. data/spec/support/static/git-scm.com/images/icons/external-sm@2x.png +0 -0
  676. data/spec/support/static/git-scm.com/images/icons/gui.png +0 -0
  677. data/spec/support/static/git-scm.com/images/icons/gui@2x.png +0 -0
  678. data/spec/support/static/git-scm.com/images/icons/info.png +0 -0
  679. data/spec/support/static/git-scm.com/images/icons/info@2x.png +0 -0
  680. data/spec/support/static/git-scm.com/images/icons/inspection-sm.png +0 -0
  681. data/spec/support/static/git-scm.com/images/icons/inspection-sm@2x.png +0 -0
  682. data/spec/support/static/git-scm.com/images/icons/linux.png +0 -0
  683. data/spec/support/static/git-scm.com/images/icons/linux@2x.png +0 -0
  684. data/spec/support/static/git-scm.com/images/icons/nav-circles.png +0 -0
  685. data/spec/support/static/git-scm.com/images/icons/nav-circles@2x.png +0 -0
  686. data/spec/support/static/git-scm.com/images/icons/patching-sm.png +0 -0
  687. data/spec/support/static/git-scm.com/images/icons/patching-sm@2x.png +0 -0
  688. data/spec/support/static/git-scm.com/images/icons/plumbing-sm.png +0 -0
  689. data/spec/support/static/git-scm.com/images/icons/plumbing-sm@2x.png +0 -0
  690. data/spec/support/static/git-scm.com/images/icons/projects-sm.png +0 -0
  691. data/spec/support/static/git-scm.com/images/icons/projects-sm@2x.png +0 -0
  692. data/spec/support/static/git-scm.com/images/icons/search.png +0 -0
  693. data/spec/support/static/git-scm.com/images/icons/search@2x.png +0 -0
  694. data/spec/support/static/git-scm.com/images/icons/server-admin-sm.png +0 -0
  695. data/spec/support/static/git-scm.com/images/icons/server-admin-sm@2x.png +0 -0
  696. data/spec/support/static/git-scm.com/images/icons/setup-sm.png +0 -0
  697. data/spec/support/static/git-scm.com/images/icons/setup-sm@2x.png +0 -0
  698. data/spec/support/static/git-scm.com/images/icons/sharing-sm.png +0 -0
  699. data/spec/support/static/git-scm.com/images/icons/sharing-sm@2x.png +0 -0
  700. data/spec/support/static/git-scm.com/images/icons/sidebar.png +0 -0
  701. data/spec/support/static/git-scm.com/images/icons/sidebar@2x.png +0 -0
  702. data/spec/support/static/git-scm.com/images/icons/source-code.png +0 -0
  703. data/spec/support/static/git-scm.com/images/icons/source-code@2x.png +0 -0
  704. data/spec/support/static/git-scm.com/images/icons/windows.png +0 -0
  705. data/spec/support/static/git-scm.com/images/icons/windows@2x.png +0 -0
  706. data/spec/support/static/git-scm.com/images/logo@2x.png +0 -0
  707. data/spec/support/static/git-scm.com/images/mobi.png +0 -0
  708. data/spec/support/static/git-scm.com/images/monitor-default.png +0 -0
  709. data/spec/support/static/git-scm.com/images/monitor-default@2x.png +0 -0
  710. data/spec/support/static/git-scm.com/images/monitor-linux.png +0 -0
  711. data/spec/support/static/git-scm.com/images/monitor-linux@2x.png +0 -0
  712. data/spec/support/static/git-scm.com/images/monitor-mac.png +0 -0
  713. data/spec/support/static/git-scm.com/images/monitor-mac@2x.png +0 -0
  714. data/spec/support/static/git-scm.com/images/monitor-windows.png +0 -0
  715. data/spec/support/static/git-scm.com/images/monitor-windows@2x.png +0 -0
  716. data/spec/support/static/git-scm.com/images/pdf.png +0 -0
  717. data/spec/support/static/git-scm.com/images/progit2.png +0 -0
  718. data/spec/support/static/git-scm.com/images/sidebar-divider.png +0 -0
  719. data/spec/support/static/git-scm.com/images/sidebar-divider@2x.png +0 -0
  720. data/spec/support/static/git-scm.com/robots.txt +0 -0
  721. data/spec/task_spec.rb +7 -0
  722. data/spec/wayfarer_spec.rb +1 -1
  723. data/wayfarer.gemspec +9 -8
  724. metadata +692 -47
  725. data/docs/guides/browser_automation/capybara.md +0 -3
  726. data/lib/wayfarer/config.rb +0 -67
  727. data/lib/wayfarer/middleware/worker.rb +0 -47
  728. data/lib/wayfarer/networking/healer.rb +0 -21
  729. data/lib/wayfarer/networking/net_http.rb +0 -52
  730. data/lib/wayfarer/routing/custom_matcher.rb +0 -21
  731. data/lib/wayfarer/routing/host_matcher.rb +0 -23
  732. data/lib/wayfarer/routing/path_matcher.rb +0 -46
  733. data/lib/wayfarer/routing/query_matcher.rb +0 -67
  734. data/lib/wayfarer/routing/scheme_matcher.rb +0 -21
  735. data/lib/wayfarer/routing/suffix_matcher.rb +0 -21
  736. data/lib/wayfarer/routing/url_matcher.rb +0 -21
  737. data/spec/config_spec.rb +0 -144
  738. data/spec/factories/queue/chain.rb +0 -11
  739. data/spec/middleware/worker_spec.rb +0 -90
  740. data/spec/networking/adapter.rb +0 -135
  741. data/spec/networking/healer_spec.rb +0 -46
  742. data/spec/networking/net_http_spec.rb +0 -37
@@ -0,0 +1,1864 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <!-- Global site tag (gtag.js) - Google Analytics -->
6
+ <script async src="https://www.googletagmanager.com/gtag/js?id=UA-49925874-3"></script>
7
+ <script>
8
+ window.dataLayer = window.dataLayer || [];
9
+ function gtag(){dataLayer.push(arguments);}
10
+ gtag('js', new Date());
11
+
12
+ gtag('config', 'UA-49925874-3');
13
+ </script>
14
+
15
+ <meta charset='utf-8'>
16
+ <meta content='IE=edge,chrome=1' http-equiv='X-UA-Compatible'>
17
+ <meta name="viewport" content="width=device-width, initial-scale=1">
18
+ <title>Git - Submodules</title>
19
+
20
+ <link href='../../../../favicon.ico' rel='shortcut icon' type='image/x-icon'>
21
+
22
+ <link rel="stylesheet" media="screen" href="../../../../assets/application-cafcf280f67db0e6d8168ba98a38da878769a9d5f37793b68ffb963a02d185e0.css" />
23
+ <script src="../../../../assets/modernize-b3ebe0c31c24f230dc62179d3e1030d2e57a53b1668d9382c0a27dbd44a94beb.js"></script>
24
+ <!--[if (gte IE 6)&(lte IE 8)]>
25
+ <script src="/javascripts/selectivizr-min.js"></script>
26
+ <![endif]-->
27
+
28
+ </head>
29
+
30
+ <body id="documentation">
31
+
32
+ <div class="inner">
33
+ <header>
34
+
35
+ <a href="https://git-scm.com/"><img src="../../../../images/logo@2x.png" width="110" height="46" alt="Git" /></a>
36
+ <span id="tagline"></span>
37
+ <script type="text/javascript">
38
+ var taglines = ["fast-version-control","everything-is-local","distributed-even-if-your-workflow-isnt","local-branching-on-the-cheap","distributed-is-the-new-centralized"];
39
+ var tagline = taglines[Math.floor(Math.random() * taglines.length)];
40
+ document.getElementById('tagline').innerHTML = '--' + tagline;
41
+ </script>
42
+ <form id="search" action="https://git-scm.com/search/results">
43
+ <input id="search-text" name="search" placeholder="Search entire site..." autocomplete="off" type="text" />
44
+ </form>
45
+ <div id="search-results"></div>
46
+
47
+ </header>
48
+
49
+ </div> <!-- .inner -->
50
+
51
+ <div class="inner">
52
+ <div id="content-wrapper">
53
+ <button class="sidebar-btn"></button>
54
+ <aside class="sidebar" id="sidebar">
55
+ <nav>
56
+ <ul>
57
+ <li>
58
+ <a href="https://git-scm.com/about">About</a>
59
+ <ul class="">
60
+ <li>
61
+ <a href="https://git-scm.com/about">Branching and Merging</a>
62
+ </li>
63
+ <li>
64
+ <a href="https://git-scm.com/about/small-and-fast">Small and Fast</a>
65
+ </li>
66
+ <li>
67
+ <a href="https://git-scm.com/about/distributed">Distributed</a>
68
+ </li>
69
+ <li>
70
+ <a href="https://git-scm.com/about/info-assurance">Data Assurance</a>
71
+ </li>
72
+ <li>
73
+ <a href="https://git-scm.com/about/staging-area">Staging Area</a>
74
+ </li>
75
+ <li>
76
+ <a href="https://git-scm.com/about/free-and-open-source">Free and Open Source</a>
77
+ </li>
78
+ <li>
79
+ <a href="https://git-scm.com/about/trademark">Trademark</a>
80
+ </li>
81
+ </ul>
82
+ </li>
83
+ <li>
84
+ <a class="active" href="https://git-scm.com/doc">Documentation</a>
85
+ <ul class="expanded">
86
+ <li>
87
+ <a href="https://git-scm.com/docs">Reference</a>
88
+ </li>
89
+ <li>
90
+ <a class="active" href="https://git-scm.com/book">Book</a>
91
+ </li>
92
+ <li>
93
+ <a href="https://git-scm.com/videos">Videos</a>
94
+ </li>
95
+ <li>
96
+ <a href="https://git-scm.com/doc/ext">External Links</a>
97
+ </li>
98
+ </ul>
99
+ </li>
100
+ <li>
101
+ <a href="https://git-scm.com/downloads">Downloads</a>
102
+ <ul class="">
103
+ <li>
104
+ <a href="https://git-scm.com/downloads/guis">GUI Clients</a>
105
+ </li>
106
+ <li>
107
+ <a href="https://git-scm.com/downloads/logos">Logos</a>
108
+ </li>
109
+ </ul>
110
+ </li>
111
+ <li>
112
+ <a href="https://git-scm.com/community">Community</a>
113
+ </li>
114
+ </ul>
115
+ <hr class="sidebar">
116
+ <p>
117
+ This book is available in
118
+ <a href="https://git-scm.com/book/en">English</a>.
119
+ </p>
120
+ <p>
121
+ Full translation available in
122
+ <table>
123
+ <tr><td><a href="https://git-scm.com/book/az">azərbaycan dili</a>,</td></tr>
124
+ <tr><td><a href="https://git-scm.com/book/bg">български език</a>,</td></tr>
125
+ <tr><td><a href="https://git-scm.com/book/de">Deutsch</a>,</td></tr>
126
+ <tr><td><a href="https://git-scm.com/book/es">Español</a>,</td></tr>
127
+ <tr><td><a href="https://git-scm.com/book/fr">Français</a>,</td></tr>
128
+ <tr><td><a href="https://git-scm.com/book/gr">Ελληνικά</a>,</td></tr>
129
+ <tr><td><a href="https://git-scm.com/book/ja">日本語</a>,</td></tr>
130
+ <tr><td><a href="https://git-scm.com/book/ko">한국어</a>,</td></tr>
131
+ <tr><td><a href="https://git-scm.com/book/nl">Nederlands</a>,</td></tr>
132
+ <tr><td><a href="https://git-scm.com/book/ru">Русский</a>,</td></tr>
133
+ <tr><td><a href="https://git-scm.com/book/sl">Slovenščina</a>,</td></tr>
134
+ <tr><td><a href="https://git-scm.com/book/tl">Tagalog</a>,</td></tr>
135
+ <tr><td><a href="https://git-scm.com/book/uk">Українська</a></td></tr>
136
+ <tr><td><a href="https://git-scm.com/book/zh">简体中文</a>,</td></tr>
137
+ </table>
138
+ </p>
139
+ <p>
140
+ Partial translations available in
141
+ <table>
142
+ <tr><td><a href="https://git-scm.com/book/cs">Čeština</a>,</td></tr>
143
+ <tr><td><a href="https://git-scm.com/book/mk">Македонски</a>,</td></tr>
144
+ <tr><td><a href="https://git-scm.com/book/pl">Polski</a>,</td></tr>
145
+ <tr><td><a href="https://git-scm.com/book/sr">Српски</a>,</td></tr>
146
+ <tr><td><a href="https://git-scm.com/book/uz">Ўзбекча</a>,</td></tr>
147
+ <tr><td><a href="https://git-scm.com/book/zh-tw">繁體中文</a>,</td></tr>
148
+ </table>
149
+ </p>
150
+ <p>
151
+ Translations started for
152
+ <table>
153
+ <tr><td><a href="https://git-scm.com/book/be">Беларуская</a>,</td></tr>
154
+ <tr><td><a href="https://git-scm.com/book/fa" dir="rtl">فارسی</a>,</td></tr>
155
+ <tr><td><a href="https://git-scm.com/book/id">Indonesian</a>,</td></tr>
156
+ <tr><td><a href="https://git-scm.com/book/it">Italiano</a>,</td></tr>
157
+ <tr><td><a href="https://git-scm.com/book/ms">Bahasa Melayu</a>,</td></tr>
158
+ <tr><td><a href="https://git-scm.com/book/pt-br">Português (Brasil)</a>,</td></tr>
159
+ <tr><td><a href="https://git-scm.com/book/pt-pt">Português (Portugal)</a>,</td></tr>
160
+ <tr><td><a href="https://git-scm.com/book/sv">Svenska</a>,</td></tr>
161
+ <tr><td><a href="https://git-scm.com/book/tr">Türkçe</a>.</td></tr>
162
+ </table>
163
+ </p>
164
+ <hr class="sidebar"/>
165
+ <p>
166
+ The source of this book is <a href="https://github.com/progit/progit2">hosted on GitHub.</a></br>
167
+ Patches, suggestions and comments are welcome.
168
+ </p>
169
+
170
+
171
+ </nav>
172
+ </aside>
173
+
174
+ <div id="content">
175
+
176
+
177
+ <div id='book-chapters'>
178
+ <a class="dropdown-trigger" id="book-chapters-trigger" data-panel-id="chapters-dropdown" href="_publishing_submodules.html#">Chapters ▾</a>
179
+ <div class='dropdown-panel' id='chapters-dropdown'>
180
+ <div class="three-column">
181
+ <div class='column-left'>
182
+ <ol class='book-toc'>
183
+ <li class='chapter'>
184
+ <h2>1. <a href="ch01-getting-started.html">Getting Started</a></h2>
185
+ <ol>
186
+ <li>
187
+ 1.1
188
+ <a href="ch01-getting-started.html" >About Version Control </a>
189
+ </li>
190
+ <li>
191
+ 1.2
192
+ <a href="../Getting-Started-A-Short-History-of-Git.html" >A Short History of Git </a>
193
+ </li>
194
+ <li>
195
+ 1.3
196
+ <a href="what_is_git_section.html" >What is Git? </a>
197
+ </li>
198
+ <li>
199
+ 1.4
200
+ <a href="../Getting-Started-The-Command-Line.html" >The Command Line </a>
201
+ </li>
202
+ <li>
203
+ 1.5
204
+ <a href="../Getting-Started-Installing-Git.html" >Installing Git </a>
205
+ </li>
206
+ <li>
207
+ 1.6
208
+ <a href="_editor.html" >First-Time Git Setup </a>
209
+ </li>
210
+ <li>
211
+ 1.7
212
+ <a href="_git_help.html" >Getting Help </a>
213
+ </li>
214
+ <li>
215
+ 1.8
216
+ <a href="../Getting-Started-Summary.html" >Summary </a>
217
+ </li>
218
+ </ol>
219
+ </li>
220
+ <li class='chapter'>
221
+ <h2>2. <a href="_git_cloning.html">Git Basics</a></h2>
222
+ <ol>
223
+ <li>
224
+ 2.1
225
+ <a href="_git_cloning.html" >Getting a Git Repository </a>
226
+ </li>
227
+ <li>
228
+ 2.2
229
+ <a href="_git_mv.html" >Recording Changes to the Repository </a>
230
+ </li>
231
+ <li>
232
+ 2.3
233
+ <a href="_viewing_history.html" >Viewing the Commit History </a>
234
+ </li>
235
+ <li>
236
+ 2.4
237
+ <a href="_unstaging.html" >Undoing Things </a>
238
+ </li>
239
+ <li>
240
+ 2.5
241
+ <a href="_remote_repos.html" >Working with Remotes </a>
242
+ </li>
243
+ <li>
244
+ 2.6
245
+ <a href="_annotated_tags.html" >Tagging </a>
246
+ </li>
247
+ <li>
248
+ 2.7
249
+ <a href="_git_aliases.html" >Git Aliases </a>
250
+ </li>
251
+ <li>
252
+ 2.8
253
+ <a href="../Git-Basics-Summary.html" >Summary </a>
254
+ </li>
255
+ </ol>
256
+ </li>
257
+ <li class='chapter'>
258
+ <h2>3. <a href="_switching_branches.html">Git Branching</a></h2>
259
+ <ol>
260
+ <li>
261
+ 3.1
262
+ <a href="_switching_branches.html" >Branches in a Nutshell </a>
263
+ </li>
264
+ <li>
265
+ 3.2
266
+ <a href="_basic_branching.html" >Basic Branching and Merging </a>
267
+ </li>
268
+ <li>
269
+ 3.3
270
+ <a href="_branch_management.html" >Branch Management </a>
271
+ </li>
272
+ <li>
273
+ 3.4
274
+ <a href="_topic_branch.html" >Branching Workflows </a>
275
+ </li>
276
+ <li>
277
+ 3.5
278
+ <a href="_delete_branches.html" >Remote Branches </a>
279
+ </li>
280
+ <li>
281
+ 3.6
282
+ <a href="_rebase_rebase.html" >Rebasing </a>
283
+ </li>
284
+ <li>
285
+ 3.7
286
+ <a href="../Git-Branching-Summary.html" >Summary </a>
287
+ </li>
288
+ </ol>
289
+ </li>
290
+ <li class='chapter'>
291
+ <h2>4. <a href="../Git-on-the-Server-The-Protocols.html">Git on the Server</a></h2>
292
+ <ol>
293
+ <li>
294
+ 4.1
295
+ <a href="../Git-on-the-Server-The-Protocols.html" >The Protocols </a>
296
+ </li>
297
+ <li>
298
+ 4.2
299
+ <a href="_bare_repo.html" >Getting Git on a Server </a>
300
+ </li>
301
+ <li>
302
+ 4.3
303
+ <a href="_generate_ssh_key.html" >Generating Your SSH Public Key </a>
304
+ </li>
305
+ <li>
306
+ 4.4
307
+ <a href="_setting_up_server.html" >Setting Up the Server </a>
308
+ </li>
309
+ <li>
310
+ 4.5
311
+ <a href="../Git-on-the-Server-Git-Daemon.html" >Git Daemon </a>
312
+ </li>
313
+ <li>
314
+ 4.6
315
+ <a href="../Git-on-the-Server-Smart-HTTP.html" >Smart HTTP </a>
316
+ </li>
317
+ <li>
318
+ 4.7
319
+ <a href="../Git-on-the-Server-GitWeb.html" >GitWeb </a>
320
+ </li>
321
+ <li>
322
+ 4.8
323
+ <a href="_gitlab_groups_section.html" >GitLab </a>
324
+ </li>
325
+ <li>
326
+ 4.9
327
+ <a href="../Git-on-the-Server-Third-Party-Hosted-Options.html" >Third Party Hosted Options </a>
328
+ </li>
329
+ <li>
330
+ 4.10
331
+ <a href="../Git-on-the-Server-Summary.html" >Summary </a>
332
+ </li>
333
+ </ol>
334
+ </li>
335
+ <li class='chapter'>
336
+ <h2>5. <a href="_integration_manager.html">Distributed Git</a></h2>
337
+ <ol>
338
+ <li>
339
+ 5.1
340
+ <a href="_integration_manager.html" >Distributed Workflows </a>
341
+ </li>
342
+ <li>
343
+ 5.2
344
+ <a href="_project_over_email.html" >Contributing to a Project </a>
345
+ </li>
346
+ <li>
347
+ 5.3
348
+ <a href="_git_am.html" >Maintaining a Project </a>
349
+ </li>
350
+ <li>
351
+ 5.4
352
+ <a href="../Distributed-Git-Summary.html" >Summary </a>
353
+ </li>
354
+ </ol>
355
+ </li>
356
+ </ol>
357
+
358
+ </div>
359
+ <div class='column-middle'>
360
+ <ol class='book-toc'>
361
+ <li class='chapter'>
362
+ <h2>6. <a href="_personal_avatar.html">GitHub</a></h2>
363
+ <ol>
364
+ <li>
365
+ 6.1
366
+ <a href="_personal_avatar.html" >Account Setup and Configuration </a>
367
+ </li>
368
+ <li>
369
+ 6.2
370
+ <a href="_fetch_and_push_on_different_repositories.html" >Contributing to a Project </a>
371
+ </li>
372
+ <li>
373
+ 6.3
374
+ <a href="_email_notifications.html" >Maintaining a Project </a>
375
+ </li>
376
+ <li>
377
+ 6.4
378
+ <a href="_team_page.html" >Managing an organization </a>
379
+ </li>
380
+ <li>
381
+ 6.5
382
+ <a href="_commit_status.html" >Scripting GitHub </a>
383
+ </li>
384
+ <li>
385
+ 6.6
386
+ <a href="../GitHub-Summary.html" >Summary </a>
387
+ </li>
388
+ </ol>
389
+ </li>
390
+ <li class='chapter'>
391
+ <h2>7. <a href="_git_reflog.html">Git Tools</a></h2>
392
+ <ol>
393
+ <li>
394
+ 7.1
395
+ <a href="_git_reflog.html" >Revision Selection </a>
396
+ </li>
397
+ <li>
398
+ 7.2
399
+ <a href="_interactive_staging.html" >Interactive Staging </a>
400
+ </li>
401
+ <li>
402
+ 7.3
403
+ <a href="_git_clean.html" >Stashing and Cleaning </a>
404
+ </li>
405
+ <li>
406
+ 7.4
407
+ <a href="_signing_commits.html" >Signing Your Work </a>
408
+ </li>
409
+ <li>
410
+ 7.5
411
+ <a href="_git_grep.html" >Searching </a>
412
+ </li>
413
+ <li>
414
+ 7.6
415
+ <a href="_removing_file_every_commit.html" >Rewriting History </a>
416
+ </li>
417
+ <li>
418
+ 7.7
419
+ <a href="_the_index.html" >Reset Demystified </a>
420
+ </li>
421
+ <li>
422
+ 7.8
423
+ <a href="_reverse_commit.html" >Advanced Merging </a>
424
+ </li>
425
+ <li>
426
+ 7.9
427
+ <a href="ref_rerere.html" >Rerere </a>
428
+ </li>
429
+ <li>
430
+ 7.10
431
+ <a href="_file_annotation.html" >Debugging with Git </a>
432
+ </li>
433
+ <li>
434
+ 7.11
435
+ <a href="_publishing_submodules.html" class=active>Submodules </a>
436
+ </li>
437
+ <li>
438
+ 7.12
439
+ <a href="_bundling.html" >Bundling </a>
440
+ </li>
441
+ <li>
442
+ 7.13
443
+ <a href="_replace.html" >Replace </a>
444
+ </li>
445
+ <li>
446
+ 7.14
447
+ <a href="_credential_caching.html" >Credential Storage </a>
448
+ </li>
449
+ <li>
450
+ 7.15
451
+ <a href="../Git-Tools-Summary.html" >Summary </a>
452
+ </li>
453
+ </ol>
454
+ </li>
455
+ <li class='chapter'>
456
+ <h2>8. <a href="_external_merge_tools.html">Customizing Git</a></h2>
457
+ <ol>
458
+ <li>
459
+ 8.1
460
+ <a href="_external_merge_tools.html" >Git Configuration </a>
461
+ </li>
462
+ <li>
463
+ 8.2
464
+ <a href="_keyword_expansion.html" >Git Attributes </a>
465
+ </li>
466
+ <li>
467
+ 8.3
468
+ <a href="_email_hooks.html" >Git Hooks </a>
469
+ </li>
470
+ <li>
471
+ 8.4
472
+ <a href="_enforcing_commit_message_format.html" >An Example Git-Enforced Policy </a>
473
+ </li>
474
+ <li>
475
+ 8.5
476
+ <a href="../Customizing-Git-Summary.html" >Summary </a>
477
+ </li>
478
+ </ol>
479
+ </li>
480
+ <li class='chapter'>
481
+ <h2>9. <a href="_git_svn.html">Git and Other Systems</a></h2>
482
+ <ol>
483
+ <li>
484
+ 9.1
485
+ <a href="_git_svn.html" >Git as a Client </a>
486
+ </li>
487
+ <li>
488
+ 9.2
489
+ <a href="_git_p4.html" >Migrating to Git </a>
490
+ </li>
491
+ <li>
492
+ 9.3
493
+ <a href="../Git-and-Other-Systems-Summary.html" >Summary </a>
494
+ </li>
495
+ </ol>
496
+ </li>
497
+ <li class='chapter'>
498
+ <h2>10. <a href="_plumbing_porcelain.html">Git Internals</a></h2>
499
+ <ol>
500
+ <li>
501
+ 10.1
502
+ <a href="_plumbing_porcelain.html" >Plumbing and Porcelain </a>
503
+ </li>
504
+ <li>
505
+ 10.2
506
+ <a href="_git_commit_objects.html" >Git Objects </a>
507
+ </li>
508
+ <li>
509
+ 10.3
510
+ <a href="ref_the_ref.html" >Git References </a>
511
+ </li>
512
+ <li>
513
+ 10.4
514
+ <a href="../Git-Internals-Packfiles.html" >Packfiles </a>
515
+ </li>
516
+ <li>
517
+ 10.5
518
+ <a href="_pushing_refspecs.html" >The Refspec </a>
519
+ </li>
520
+ <li>
521
+ 10.6
522
+ <a href="../Git-Internals-Transfer-Protocols.html" >Transfer Protocols </a>
523
+ </li>
524
+ <li>
525
+ 10.7
526
+ <a href="_git_gc.html" >Maintenance and Data Recovery </a>
527
+ </li>
528
+ <li>
529
+ 10.8
530
+ <a href="../Git-Internals-Environment-Variables.html" >Environment Variables </a>
531
+ </li>
532
+ <li>
533
+ 10.9
534
+ <a href="../Git-Internals-Summary.html" >Summary </a>
535
+ </li>
536
+ </ol>
537
+ </li>
538
+ </ol>
539
+
540
+ </div>
541
+ <div class='column-right'>
542
+ <ol class='book-toc'>
543
+ <li class='chapter'>
544
+ <h2>A1. <a href="../Appendix-A:-Git-in-Other-Environments-Graphical-Interfaces.html">Appendix A: Git in Other Environments</a></h2>
545
+ <ol>
546
+ <li>
547
+ A1.1
548
+ <a href="../Appendix-A:-Git-in-Other-Environments-Graphical-Interfaces.html" >Graphical Interfaces </a>
549
+ </li>
550
+ <li>
551
+ A1.2
552
+ <a href="../Appendix-A:-Git-in-Other-Environments-Git-in-Visual-Studio.html" >Git in Visual Studio </a>
553
+ </li>
554
+ <li>
555
+ A1.3
556
+ <a href="../Appendix-A:-Git-in-Other-Environments-Git-in-Visual-Studio-Code.html" >Git in Visual Studio Code </a>
557
+ </li>
558
+ <li>
559
+ A1.4
560
+ <a href="../Appendix-A:-Git-in-Other-Environments-Git-in-IntelliJ-%252F-PyCharm-%252F-WebStorm-%252F-PhpStorm-%252F-RubyMine.html" >Git in IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine </a>
561
+ </li>
562
+ <li>
563
+ A1.5
564
+ <a href="../Appendix-A:-Git-in-Other-Environments-Git-in-Sublime-Text.html" >Git in Sublime Text </a>
565
+ </li>
566
+ <li>
567
+ A1.6
568
+ <a href="../Appendix-A:-Git-in-Other-Environments-Git-in-Bash.html" >Git in Bash </a>
569
+ </li>
570
+ <li>
571
+ A1.7
572
+ <a href="oh_my_zsh_git.html" >Git in Zsh </a>
573
+ </li>
574
+ <li>
575
+ A1.8
576
+ <a href="../Appendix-A:-Git-in-Other-Environments-Git-in-PowerShell.html" >Git in PowerShell </a>
577
+ </li>
578
+ <li>
579
+ A1.9
580
+ <a href="../Appendix-A:-Git-in-Other-Environments-Summary.html" >Summary </a>
581
+ </li>
582
+ </ol>
583
+ </li>
584
+ <li class='chapter'>
585
+ <h2>A2. <a href="../Appendix-B:-Embedding-Git-in-your-Applications-Command-line-Git.html">Appendix B: Embedding Git in your Applications</a></h2>
586
+ <ol>
587
+ <li>
588
+ A2.1
589
+ <a href="../Appendix-B:-Embedding-Git-in-your-Applications-Command-line-Git.html" >Command-line Git </a>
590
+ </li>
591
+ <li>
592
+ A2.2
593
+ <a href="_libgit2_bindings.html" >Libgit2 </a>
594
+ </li>
595
+ <li>
596
+ A2.3
597
+ <a href="../Appendix-B:-Embedding-Git-in-your-Applications-JGit.html" >JGit </a>
598
+ </li>
599
+ <li>
600
+ A2.4
601
+ <a href="../Appendix-B:-Embedding-Git-in-your-Applications-go-git.html" >go-git </a>
602
+ </li>
603
+ <li>
604
+ A2.5
605
+ <a href="../Appendix-B:-Embedding-Git-in-your-Applications-Dulwich.html" >Dulwich </a>
606
+ </li>
607
+ </ol>
608
+ </li>
609
+ <li class='chapter'>
610
+ <h2>A3. <a href="ch_core_editor.html">Appendix C: Git Commands</a></h2>
611
+ <ol>
612
+ <li>
613
+ A3.1
614
+ <a href="ch_core_editor.html" >Setup and Config </a>
615
+ </li>
616
+ <li>
617
+ A3.2
618
+ <a href="../Appendix-C:-Git-Commands-Getting-and-Creating-Projects.html" >Getting and Creating Projects </a>
619
+ </li>
620
+ <li>
621
+ A3.3
622
+ <a href="../Appendix-C:-Git-Commands-Basic-Snapshotting.html" >Basic Snapshotting </a>
623
+ </li>
624
+ <li>
625
+ A3.4
626
+ <a href="../Appendix-C:-Git-Commands-Branching-and-Merging.html" >Branching and Merging </a>
627
+ </li>
628
+ <li>
629
+ A3.5
630
+ <a href="../Appendix-C:-Git-Commands-Sharing-and-Updating-Projects.html" >Sharing and Updating Projects </a>
631
+ </li>
632
+ <li>
633
+ A3.6
634
+ <a href="../Appendix-C:-Git-Commands-Inspection-and-Comparison.html" >Inspection and Comparison </a>
635
+ </li>
636
+ <li>
637
+ A3.7
638
+ <a href="../Appendix-C:-Git-Commands-Debugging.html" >Debugging </a>
639
+ </li>
640
+ <li>
641
+ A3.8
642
+ <a href="../Appendix-C:-Git-Commands-Patching.html" >Patching </a>
643
+ </li>
644
+ <li>
645
+ A3.9
646
+ <a href="../Appendix-C:-Git-Commands-Email.html" >Email </a>
647
+ </li>
648
+ <li>
649
+ A3.10
650
+ <a href="../Appendix-C:-Git-Commands-External-Systems.html" >External Systems </a>
651
+ </li>
652
+ <li>
653
+ A3.11
654
+ <a href="../Appendix-C:-Git-Commands-Administration.html" >Administration </a>
655
+ </li>
656
+ <li>
657
+ A3.12
658
+ <a href="../Appendix-C:-Git-Commands-Plumbing-Commands.html" >Plumbing Commands </a>
659
+ </li>
660
+ </ol>
661
+ </li>
662
+ </ol>
663
+
664
+ </div>
665
+ </div>
666
+ </div>
667
+
668
+ <span class="light" id="edition">
669
+ 2nd Edition
670
+ </span>
671
+ </div>
672
+
673
+ <div id='main' class="book edition2">
674
+ <h1>7.11 Git Tools - Submodules</h1>
675
+ <div>
676
+ <h2 id="_git_submodules">Submodules</h2>
677
+ <div class="paragraph">
678
+ <p>It often happens that while working on one project, you need to use another project from within it.
679
+ Perhaps it’s a library that a third party developed or that you’re developing separately and using in multiple parent projects.
680
+ A common issue arises in these scenarios: you want to be able to treat the two projects as separate yet still be able to use one from within the other.</p>
681
+ </div>
682
+ <div class="paragraph">
683
+ <p>Here’s an example.
684
+ Suppose you’re developing a website and creating Atom feeds.
685
+ Instead of writing your own Atom-generating code, you decide to use a library.
686
+ You’re likely to have to either include this code from a shared library like a CPAN install or Ruby gem, or copy the source code into your own project tree.
687
+ The issue with including the library is that it’s difficult to customize the library in any way and often more difficult to deploy it, because you need to make sure every client has that library available.
688
+ The issue with copying the code into your own project is that any custom changes you make are difficult to merge when upstream changes become available.</p>
689
+ </div>
690
+ <div class="paragraph">
691
+ <p>Git addresses this issue using submodules.
692
+ Submodules allow you to keep a Git repository as a subdirectory of another Git repository.
693
+ This lets you clone another repository into your project and keep your commits separate.</p>
694
+ </div>
695
+ <div class="sect3">
696
+ <h3 id="_starting_submodules">Starting with Submodules</h3>
697
+ <div class="paragraph">
698
+ <p>We’ll walk through developing a simple project that has been split up into a main project and a few sub-projects.</p>
699
+ </div>
700
+ <div class="paragraph">
701
+ <p>Let’s start by adding an existing Git repository as a submodule of the repository that we’re working on.
702
+ To add a new submodule you use the <code>git submodule add</code> command with the absolute or relative URL of the project you would like to start tracking.
703
+ In this example, we’ll add a library called “DbConnector”.</p>
704
+ </div>
705
+ <div class="listingblock">
706
+ <div class="content">
707
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git submodule add https://github.com/chaconinc/DbConnector
708
+ Cloning into 'DbConnector'...
709
+ remote: Counting objects: 11, done.
710
+ remote: Compressing objects: 100% (10/10), done.
711
+ remote: Total 11 (delta 0), reused 11 (delta 0)
712
+ Unpacking objects: 100% (11/11), done.
713
+ Checking connectivity... done.</code></pre>
714
+ </div>
715
+ </div>
716
+ <div class="paragraph">
717
+ <p>By default, submodules will add the subproject into a directory named the same as the repository, in this case “DbConnector”.
718
+ You can add a different path at the end of the command if you want it to go elsewhere.</p>
719
+ </div>
720
+ <div class="paragraph">
721
+ <p>If you run <code>git status</code> at this point, you’ll notice a few things.</p>
722
+ </div>
723
+ <div class="listingblock">
724
+ <div class="content">
725
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git status
726
+ On branch master
727
+ Your branch is up-to-date with 'origin/master'.
728
+
729
+ Changes to be committed:
730
+ (use "git reset HEAD &lt;file&gt;..." to unstage)
731
+
732
+ new file: .gitmodules
733
+ new file: DbConnector</code></pre>
734
+ </div>
735
+ </div>
736
+ <div class="paragraph">
737
+ <p>First you should notice the new <code>.gitmodules</code> file.
738
+ This is a configuration file that stores the mapping between the project’s URL and the local subdirectory you’ve pulled it into:</p>
739
+ </div>
740
+ <div class="listingblock">
741
+ <div class="content">
742
+ <pre class="highlight"><code class="language-ini" data-lang="ini">[submodule "DbConnector"]
743
+ path = DbConnector
744
+ url = https://github.com/chaconinc/DbConnector</code></pre>
745
+ </div>
746
+ </div>
747
+ <div class="paragraph">
748
+ <p>If you have multiple submodules, you’ll have multiple entries in this file.
749
+ It’s important to note that this file is version-controlled with your other files, like your <code>.gitignore</code> file.
750
+ It’s pushed and pulled with the rest of your project.
751
+ This is how other people who clone this project know where to get the submodule projects from.</p>
752
+ </div>
753
+ <div class="admonitionblock note">
754
+ <table>
755
+ <tr>
756
+ <td class="icon">
757
+ <div class="title">Note</div>
758
+ </td>
759
+ <td class="content">
760
+ <div class="paragraph">
761
+ <p>Since the URL in the .gitmodules file is what other people will first try to clone/fetch from, make sure to use a URL that they can access if possible.
762
+ For example, if you use a different URL to push to than others would to pull from, use the one that others have access to.
763
+ You can overwrite this value locally with <code>git config submodule.DbConnector.url PRIVATE_URL</code> for your own use.
764
+ When applicable, a relative URL can be helpful.</p>
765
+ </div>
766
+ </td>
767
+ </tr>
768
+ </table>
769
+ </div>
770
+ <div class="paragraph">
771
+ <p>The other listing in the <code>git status</code> output is the project folder entry.
772
+ If you run <code>git diff</code> on that, you see something interesting:</p>
773
+ </div>
774
+ <div class="listingblock">
775
+ <div class="content">
776
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git diff --cached DbConnector
777
+ diff --git a/DbConnector b/DbConnector
778
+ new file mode 160000
779
+ index 0000000..c3f01dc
780
+ --- /dev/null
781
+ +++ b/DbConnector
782
+ @@ -0,0 +1 @@
783
+ +Subproject commit c3f01dc8862123d317dd46284b05b6892c7b29bc</code></pre>
784
+ </div>
785
+ </div>
786
+ <div class="paragraph">
787
+ <p>Although <code>DbConnector</code> is a subdirectory in your working directory, Git sees it as a submodule and doesn’t track its contents when you’re not in that directory.
788
+ Instead, Git sees it as a particular commit from that repository.</p>
789
+ </div>
790
+ <div class="paragraph">
791
+ <p>If you want a little nicer diff output, you can pass the <code>--submodule</code> option to <code>git diff</code>.</p>
792
+ </div>
793
+ <div class="listingblock">
794
+ <div class="content">
795
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git diff --cached --submodule
796
+ diff --git a/.gitmodules b/.gitmodules
797
+ new file mode 100644
798
+ index 0000000..71fc376
799
+ --- /dev/null
800
+ +++ b/.gitmodules
801
+ @@ -0,0 +1,3 @@
802
+ +[submodule "DbConnector"]
803
+ + path = DbConnector
804
+ + url = https://github.com/chaconinc/DbConnector
805
+ Submodule DbConnector 0000000...c3f01dc (new submodule)</code></pre>
806
+ </div>
807
+ </div>
808
+ <div class="paragraph">
809
+ <p>When you commit, you see something like this:</p>
810
+ </div>
811
+ <div class="listingblock">
812
+ <div class="content">
813
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git commit -am 'Add DbConnector module'
814
+ [master fb9093c] Add DbConnector module
815
+ 2 files changed, 4 insertions(+)
816
+ create mode 100644 .gitmodules
817
+ create mode 160000 DbConnector</code></pre>
818
+ </div>
819
+ </div>
820
+ <div class="paragraph">
821
+ <p>Notice the <code>160000</code> mode for the <code>DbConnector</code> entry.
822
+ That is a special mode in Git that basically means you’re recording a commit as a directory entry rather than a subdirectory or a file.</p>
823
+ </div>
824
+ <div class="paragraph">
825
+ <p>Lastly, push these changes:</p>
826
+ </div>
827
+ <div class="listingblock">
828
+ <div class="content">
829
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git push origin master</code></pre>
830
+ </div>
831
+ </div>
832
+ </div>
833
+ <div class="sect3">
834
+ <h3 id="_cloning_submodules">Cloning a Project with Submodules</h3>
835
+ <div class="paragraph">
836
+ <p>Here we’ll clone a project with a submodule in it.
837
+ When you clone such a project, by default you get the directories that contain submodules, but none of the files within them yet:</p>
838
+ </div>
839
+ <div class="listingblock">
840
+ <div class="content">
841
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git clone https://github.com/chaconinc/MainProject
842
+ Cloning into 'MainProject'...
843
+ remote: Counting objects: 14, done.
844
+ remote: Compressing objects: 100% (13/13), done.
845
+ remote: Total 14 (delta 1), reused 13 (delta 0)
846
+ Unpacking objects: 100% (14/14), done.
847
+ Checking connectivity... done.
848
+ $ cd MainProject
849
+ $ ls -la
850
+ total 16
851
+ drwxr-xr-x 9 schacon staff 306 Sep 17 15:21 .
852
+ drwxr-xr-x 7 schacon staff 238 Sep 17 15:21 ..
853
+ drwxr-xr-x 13 schacon staff 442 Sep 17 15:21 .git
854
+ -rw-r--r-- 1 schacon staff 92 Sep 17 15:21 .gitmodules
855
+ drwxr-xr-x 2 schacon staff 68 Sep 17 15:21 DbConnector
856
+ -rw-r--r-- 1 schacon staff 756 Sep 17 15:21 Makefile
857
+ drwxr-xr-x 3 schacon staff 102 Sep 17 15:21 includes
858
+ drwxr-xr-x 4 schacon staff 136 Sep 17 15:21 scripts
859
+ drwxr-xr-x 4 schacon staff 136 Sep 17 15:21 src
860
+ $ cd DbConnector/
861
+ $ ls
862
+ $</code></pre>
863
+ </div>
864
+ </div>
865
+ <div class="paragraph">
866
+ <p>The <code>DbConnector</code> directory is there, but empty.
867
+ You must run two commands: <code>git submodule init</code> to initialize your local configuration file, and <code>git submodule update</code> to fetch all the data from that project and check out the appropriate commit listed in your superproject:</p>
868
+ </div>
869
+ <div class="listingblock">
870
+ <div class="content">
871
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git submodule init
872
+ Submodule 'DbConnector' (https://github.com/chaconinc/DbConnector) registered for path 'DbConnector'
873
+ $ git submodule update
874
+ Cloning into 'DbConnector'...
875
+ remote: Counting objects: 11, done.
876
+ remote: Compressing objects: 100% (10/10), done.
877
+ remote: Total 11 (delta 0), reused 11 (delta 0)
878
+ Unpacking objects: 100% (11/11), done.
879
+ Checking connectivity... done.
880
+ Submodule path 'DbConnector': checked out 'c3f01dc8862123d317dd46284b05b6892c7b29bc'</code></pre>
881
+ </div>
882
+ </div>
883
+ <div class="paragraph">
884
+ <p>Now your <code>DbConnector</code> subdirectory is at the exact state it was in when you committed earlier.</p>
885
+ </div>
886
+ <div class="paragraph">
887
+ <p>There is another way to do this which is a little simpler, however.
888
+ If you pass <code>--recurse-submodules</code> to the <code>git clone</code> command, it will automatically initialize and update each submodule in the repository, including nested submodules if any of the submodules in the repository have submodules themselves.</p>
889
+ </div>
890
+ <div class="listingblock">
891
+ <div class="content">
892
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git clone --recurse-submodules https://github.com/chaconinc/MainProject
893
+ Cloning into 'MainProject'...
894
+ remote: Counting objects: 14, done.
895
+ remote: Compressing objects: 100% (13/13), done.
896
+ remote: Total 14 (delta 1), reused 13 (delta 0)
897
+ Unpacking objects: 100% (14/14), done.
898
+ Checking connectivity... done.
899
+ Submodule 'DbConnector' (https://github.com/chaconinc/DbConnector) registered for path 'DbConnector'
900
+ Cloning into 'DbConnector'...
901
+ remote: Counting objects: 11, done.
902
+ remote: Compressing objects: 100% (10/10), done.
903
+ remote: Total 11 (delta 0), reused 11 (delta 0)
904
+ Unpacking objects: 100% (11/11), done.
905
+ Checking connectivity... done.
906
+ Submodule path 'DbConnector': checked out 'c3f01dc8862123d317dd46284b05b6892c7b29bc'</code></pre>
907
+ </div>
908
+ </div>
909
+ <div class="paragraph">
910
+ <p>If you already cloned the project and forgot <code>--recurse-submodules</code>, you can combine the <code>git submodule init</code> and <code>git submodule update</code> steps by running <code>git submodule update --init</code>.
911
+ To also initialize, fetch and checkout any nested submodules, you can use the foolproof <code>git submodule update --init --recursive</code>.</p>
912
+ </div>
913
+ </div>
914
+ <div class="sect3">
915
+ <h3 id="_working_on_a_project_with_submodules">Working on a Project with Submodules</h3>
916
+ <div class="paragraph">
917
+ <p>Now we have a copy of a project with submodules in it and will collaborate with our teammates on both the main project and the submodule project.</p>
918
+ </div>
919
+ <div class="sect4">
920
+ <h4 id="_pulling_in_upstream_changes_from_the_submodule_remote">Pulling in Upstream Changes from the Submodule Remote</h4>
921
+ <div class="paragraph">
922
+ <p>The simplest model of using submodules in a project would be if you were simply consuming a subproject and wanted to get updates from it from time to time but were not actually modifying anything in your checkout.
923
+ Let’s walk through a simple example there.</p>
924
+ </div>
925
+ <div class="paragraph">
926
+ <p>If you want to check for new work in a submodule, you can go into the directory and run <code>git fetch</code> and <code>git merge</code> the upstream branch to update the local code.</p>
927
+ </div>
928
+ <div class="listingblock">
929
+ <div class="content">
930
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git fetch
931
+ From https://github.com/chaconinc/DbConnector
932
+ c3f01dc..d0354fc master -&gt; origin/master
933
+ $ git merge origin/master
934
+ Updating c3f01dc..d0354fc
935
+ Fast-forward
936
+ scripts/connect.sh | 1 +
937
+ src/db.c | 1 +
938
+ 2 files changed, 2 insertions(+)</code></pre>
939
+ </div>
940
+ </div>
941
+ <div class="paragraph">
942
+ <p>Now if you go back into the main project and run <code>git diff --submodule</code> you can see that the submodule was updated and get a list of commits that were added to it.
943
+ If you don’t want to type <code>--submodule</code> every time you run <code>git diff</code>, you can set it as the default format by setting the <code>diff.submodule</code> config value to “log”.</p>
944
+ </div>
945
+ <div class="listingblock">
946
+ <div class="content">
947
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git config --global diff.submodule log
948
+ $ git diff
949
+ Submodule DbConnector c3f01dc..d0354fc:
950
+ &gt; more efficient db routine
951
+ &gt; better connection routine</code></pre>
952
+ </div>
953
+ </div>
954
+ <div class="paragraph">
955
+ <p>If you commit at this point then you will lock the submodule into having the new code when other people update.</p>
956
+ </div>
957
+ <div class="paragraph">
958
+ <p>There is an easier way to do this as well, if you prefer to not manually fetch and merge in the subdirectory.
959
+ If you run <code>git submodule update --remote</code>, Git will go into your submodules and fetch and update for you.</p>
960
+ </div>
961
+ <div class="listingblock">
962
+ <div class="content">
963
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git submodule update --remote DbConnector
964
+ remote: Counting objects: 4, done.
965
+ remote: Compressing objects: 100% (2/2), done.
966
+ remote: Total 4 (delta 2), reused 4 (delta 2)
967
+ Unpacking objects: 100% (4/4), done.
968
+ From https://github.com/chaconinc/DbConnector
969
+ 3f19983..d0354fc master -&gt; origin/master
970
+ Submodule path 'DbConnector': checked out 'd0354fc054692d3906c85c3af05ddce39a1c0644'</code></pre>
971
+ </div>
972
+ </div>
973
+ <div class="paragraph">
974
+ <p>This command will by default assume that you want to update the checkout to the <code>master</code> branch of the submodule repository.
975
+ You can, however, set this to something different if you want.
976
+ For example, if you want to have the DbConnector submodule track that repository’s “stable” branch, you can set it in either your <code>.gitmodules</code> file (so everyone else also tracks it), or just in your local <code>.git/config</code> file.
977
+ Let’s set it in the <code>.gitmodules</code> file:</p>
978
+ </div>
979
+ <div class="listingblock">
980
+ <div class="content">
981
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git config -f .gitmodules submodule.DbConnector.branch stable
982
+
983
+ $ git submodule update --remote
984
+ remote: Counting objects: 4, done.
985
+ remote: Compressing objects: 100% (2/2), done.
986
+ remote: Total 4 (delta 2), reused 4 (delta 2)
987
+ Unpacking objects: 100% (4/4), done.
988
+ From https://github.com/chaconinc/DbConnector
989
+ 27cf5d3..c87d55d stable -&gt; origin/stable
990
+ Submodule path 'DbConnector': checked out 'c87d55d4c6d4b05ee34fbc8cb6f7bf4585ae6687'</code></pre>
991
+ </div>
992
+ </div>
993
+ <div class="paragraph">
994
+ <p>If you leave off the <code>-f .gitmodules</code> it will only make the change for you, but it probably makes more sense to track that information with the repository so everyone else does as well.</p>
995
+ </div>
996
+ <div class="paragraph">
997
+ <p>When we run <code>git status</code> at this point, Git will show us that we have “new commits” on the submodule.</p>
998
+ </div>
999
+ <div class="listingblock">
1000
+ <div class="content">
1001
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git status
1002
+ On branch master
1003
+ Your branch is up-to-date with 'origin/master'.
1004
+
1005
+ Changes not staged for commit:
1006
+ (use "git add &lt;file&gt;..." to update what will be committed)
1007
+ (use "git checkout -- &lt;file&gt;..." to discard changes in working directory)
1008
+
1009
+ modified: .gitmodules
1010
+ modified: DbConnector (new commits)
1011
+
1012
+ no changes added to commit (use "git add" and/or "git commit -a")</code></pre>
1013
+ </div>
1014
+ </div>
1015
+ <div class="paragraph">
1016
+ <p>If you set the configuration setting <code>status.submodulesummary</code>, Git will also show you a short summary of changes to your submodules:</p>
1017
+ </div>
1018
+ <div class="listingblock">
1019
+ <div class="content">
1020
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git config status.submodulesummary 1
1021
+
1022
+ $ git status
1023
+ On branch master
1024
+ Your branch is up-to-date with 'origin/master'.
1025
+
1026
+ Changes not staged for commit:
1027
+ (use "git add &lt;file&gt;..." to update what will be committed)
1028
+ (use "git checkout -- &lt;file&gt;..." to discard changes in working directory)
1029
+
1030
+ modified: .gitmodules
1031
+ modified: DbConnector (new commits)
1032
+
1033
+ Submodules changed but not updated:
1034
+
1035
+ * DbConnector c3f01dc...c87d55d (4):
1036
+ &gt; catch non-null terminated lines</code></pre>
1037
+ </div>
1038
+ </div>
1039
+ <div class="paragraph">
1040
+ <p>At this point if you run <code>git diff</code> we can see both that we have modified our <code>.gitmodules</code> file and also that there are a number of commits that we’ve pulled down and are ready to commit to our submodule project.</p>
1041
+ </div>
1042
+ <div class="listingblock">
1043
+ <div class="content">
1044
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git diff
1045
+ diff --git a/.gitmodules b/.gitmodules
1046
+ index 6fc0b3d..fd1cc29 100644
1047
+ --- a/.gitmodules
1048
+ +++ b/.gitmodules
1049
+ @@ -1,3 +1,4 @@
1050
+ [submodule "DbConnector"]
1051
+ path = DbConnector
1052
+ url = https://github.com/chaconinc/DbConnector
1053
+ + branch = stable
1054
+ Submodule DbConnector c3f01dc..c87d55d:
1055
+ &gt; catch non-null terminated lines
1056
+ &gt; more robust error handling
1057
+ &gt; more efficient db routine
1058
+ &gt; better connection routine</code></pre>
1059
+ </div>
1060
+ </div>
1061
+ <div class="paragraph">
1062
+ <p>This is pretty cool as we can actually see the log of commits that we’re about to commit to in our submodule.
1063
+ Once committed, you can see this information after the fact as well when you run <code>git log -p</code>.</p>
1064
+ </div>
1065
+ <div class="listingblock">
1066
+ <div class="content">
1067
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git log -p --submodule
1068
+ commit 0a24cfc121a8a3c118e0105ae4ae4c00281cf7ae
1069
+ Author: Scott Chacon &lt;schacon@gmail.com&gt;
1070
+ Date: Wed Sep 17 16:37:02 2014 +0200
1071
+
1072
+ updating DbConnector for bug fixes
1073
+
1074
+ diff --git a/.gitmodules b/.gitmodules
1075
+ index 6fc0b3d..fd1cc29 100644
1076
+ --- a/.gitmodules
1077
+ +++ b/.gitmodules
1078
+ @@ -1,3 +1,4 @@
1079
+ [submodule "DbConnector"]
1080
+ path = DbConnector
1081
+ url = https://github.com/chaconinc/DbConnector
1082
+ + branch = stable
1083
+ Submodule DbConnector c3f01dc..c87d55d:
1084
+ &gt; catch non-null terminated lines
1085
+ &gt; more robust error handling
1086
+ &gt; more efficient db routine
1087
+ &gt; better connection routine</code></pre>
1088
+ </div>
1089
+ </div>
1090
+ <div class="paragraph">
1091
+ <p>Git will by default try to update <strong>all</strong> of your submodules when you run <code>git submodule update --remote</code>.
1092
+ If you have a lot of them, you may want to pass the name of just the submodule you want to try to update.</p>
1093
+ </div>
1094
+ </div>
1095
+ <div class="sect4">
1096
+ <h4 id="_pulling_upstream_changes_from_the_project_remote">Pulling Upstream Changes from the Project Remote</h4>
1097
+ <div class="paragraph">
1098
+ <p>Let’s now step into the shoes of your collaborator, who has their own local clone of the MainProject repository.
1099
+ Simply executing <code>git pull</code> to get your newly committed changes is not enough:</p>
1100
+ </div>
1101
+ <div class="listingblock">
1102
+ <div class="content">
1103
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git pull
1104
+ From https://github.com/chaconinc/MainProject
1105
+ fb9093c..0a24cfc master -&gt; origin/master
1106
+ Fetching submodule DbConnector
1107
+ From https://github.com/chaconinc/DbConnector
1108
+ c3f01dc..c87d55d stable -&gt; origin/stable
1109
+ Updating fb9093c..0a24cfc
1110
+ Fast-forward
1111
+ .gitmodules | 2 +-
1112
+ DbConnector | 2 +-
1113
+ 2 files changed, 2 insertions(+), 2 deletions(-)
1114
+
1115
+ $ git status
1116
+ On branch master
1117
+ Your branch is up-to-date with 'origin/master'.
1118
+ Changes not staged for commit:
1119
+ (use "git add &lt;file&gt;..." to update what will be committed)
1120
+ (use "git checkout -- &lt;file&gt;..." to discard changes in working directory)
1121
+
1122
+ modified: DbConnector (new commits)
1123
+
1124
+ Submodules changed but not updated:
1125
+
1126
+ * DbConnector c87d55d...c3f01dc (4):
1127
+ &lt; catch non-null terminated lines
1128
+ &lt; more robust error handling
1129
+ &lt; more efficient db routine
1130
+ &lt; better connection routine
1131
+
1132
+ no changes added to commit (use "git add" and/or "git commit -a")</code></pre>
1133
+ </div>
1134
+ </div>
1135
+ <div class="paragraph">
1136
+ <p>By default, the <code>git pull</code> command recursively fetches submodules changes, as we can see in the output of the first command above.
1137
+ However, it does not <strong>update</strong> the submodules.
1138
+ This is shown by the output of the <code>git status</code> command, which shows the submodule is “modified”, and has “new commits”.
1139
+ What’s more, the brackets showing the new commits point left (&lt;), indicating that these commits are recorded in MainProject but are not present in the local DbConnector checkout.
1140
+ To finalize the update, you need to run <code>git submodule update</code>:</p>
1141
+ </div>
1142
+ <div class="listingblock">
1143
+ <div class="content">
1144
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git submodule update --init --recursive
1145
+ Submodule path 'vendor/plugins/demo': checked out '48679c6302815f6c76f1fe30625d795d9e55fc56'
1146
+
1147
+ $ git status
1148
+ On branch master
1149
+ Your branch is up-to-date with 'origin/master'.
1150
+ nothing to commit, working tree clean</code></pre>
1151
+ </div>
1152
+ </div>
1153
+ <div class="paragraph">
1154
+ <p>Note that to be on the safe side, you should run <code>git submodule update</code> with the <code>--init</code> flag in case the MainProject commits you just pulled added new submodules, and with the <code>--recursive</code> flag if any submodules have nested submodules.</p>
1155
+ </div>
1156
+ <div class="paragraph">
1157
+ <p>If you want to automate this process, you can add the <code>--recurse-submodules</code> flag to the <code>git pull</code> command (since Git 2.14).
1158
+ This will make Git run <code>git submodule update</code> right after the pull, putting the submodules in the correct state.
1159
+ Moreover, if you want to make Git always pull with <code>--recurse-submodules</code>, you can set the configuration option <code>submodule.recurse</code> to true (this works for <code>git pull</code> since Git 2.15).
1160
+ This option will make Git use the <code>--recurse-submodules</code> flag for all commands that support it (except <code>clone</code>).</p>
1161
+ </div>
1162
+ <div class="paragraph">
1163
+ <p>There is a special situation that can happen when pulling superproject updates: it could be that the upstream repository has changed the URL of the submodule in the <code>.gitmodules</code> file in one of the commits you pull.
1164
+ This can happen for example if the submodule project changes its hosting platform.
1165
+ In that case, it is possible for <code>git pull --recurse-submodules</code>, or <code>git submodule update</code>, to fail if the superproject references a submodule commit that is not found in the submodule remote locally configured in your repository.
1166
+ In order to remedy this situation, the <code>git submodule sync</code> command is required:</p>
1167
+ </div>
1168
+ <div class="listingblock">
1169
+ <div class="content">
1170
+ <pre class="highlight"><code class="language-console" data-lang="console"># copy the new URL to your local config
1171
+ $ git submodule sync --recursive
1172
+ # update the submodule from the new URL
1173
+ $ git submodule update --init --recursive</code></pre>
1174
+ </div>
1175
+ </div>
1176
+ </div>
1177
+ <div class="sect4">
1178
+ <h4 id="_working_on_a_submodule">Working on a Submodule</h4>
1179
+ <div class="paragraph">
1180
+ <p>It’s quite likely that if you’re using submodules, you’re doing so because you really want to work on the code in the submodule at the same time as you’re working on the code in the main project (or across several submodules).
1181
+ Otherwise you would probably instead be using a simpler dependency management system (such as Maven or Rubygems).</p>
1182
+ </div>
1183
+ <div class="paragraph">
1184
+ <p>So now let’s go through an example of making changes to the submodule at the same time as the main project and committing and publishing those changes at the same time.</p>
1185
+ </div>
1186
+ <div class="paragraph">
1187
+ <p>So far, when we’ve run the <code>git submodule update</code> command to fetch changes from the submodule repositories, Git would get the changes and update the files in the subdirectory but will leave the sub-repository in what’s called a “detached HEAD” state.
1188
+ This means that there is no local working branch (like <code>master</code>, for example) tracking changes.
1189
+ With no working branch tracking changes, that means even if you commit changes to the submodule, those changes will quite possibly be lost the next time you run <code>git submodule update</code>.
1190
+ You have to do some extra steps if you want changes in a submodule to be tracked.</p>
1191
+ </div>
1192
+ <div class="paragraph">
1193
+ <p>In order to set up your submodule to be easier to go in and hack on, you need to do two things.
1194
+ You need to go into each submodule and check out a branch to work on.
1195
+ Then you need to tell Git what to do if you have made changes and then <code>git submodule update --remote</code> pulls in new work from upstream.
1196
+ The options are that you can merge them into your local work, or you can try to rebase your local work on top of the new changes.</p>
1197
+ </div>
1198
+ <div class="paragraph">
1199
+ <p>First of all, let’s go into our submodule directory and check out a branch.</p>
1200
+ </div>
1201
+ <div class="listingblock">
1202
+ <div class="content">
1203
+ <pre class="highlight"><code class="language-console" data-lang="console">$ cd DbConnector/
1204
+ $ git checkout stable
1205
+ Switched to branch 'stable'</code></pre>
1206
+ </div>
1207
+ </div>
1208
+ <div class="paragraph">
1209
+ <p>Let’s try updating our submodule with the “merge” option.
1210
+ To specify it manually, we can just add the <code>--merge</code> option to our <code>update</code> call.
1211
+ Here we’ll see that there was a change on the server for this submodule and it gets merged in.</p>
1212
+ </div>
1213
+ <div class="listingblock">
1214
+ <div class="content">
1215
+ <pre class="highlight"><code class="language-console" data-lang="console">$ cd ..
1216
+ $ git submodule update --remote --merge
1217
+ remote: Counting objects: 4, done.
1218
+ remote: Compressing objects: 100% (2/2), done.
1219
+ remote: Total 4 (delta 2), reused 4 (delta 2)
1220
+ Unpacking objects: 100% (4/4), done.
1221
+ From https://github.com/chaconinc/DbConnector
1222
+ c87d55d..92c7337 stable -&gt; origin/stable
1223
+ Updating c87d55d..92c7337
1224
+ Fast-forward
1225
+ src/main.c | 1 +
1226
+ 1 file changed, 1 insertion(+)
1227
+ Submodule path 'DbConnector': merged in '92c7337b30ef9e0893e758dac2459d07362ab5ea'</code></pre>
1228
+ </div>
1229
+ </div>
1230
+ <div class="paragraph">
1231
+ <p>If we go into the DbConnector directory, we have the new changes already merged into our local <code>stable</code> branch.
1232
+ Now let’s see what happens when we make our own local change to the library and someone else pushes another change upstream at the same time.</p>
1233
+ </div>
1234
+ <div class="listingblock">
1235
+ <div class="content">
1236
+ <pre class="highlight"><code class="language-console" data-lang="console">$ cd DbConnector/
1237
+ $ vim src/db.c
1238
+ $ git commit -am 'Unicode support'
1239
+ [stable f906e16] Unicode support
1240
+ 1 file changed, 1 insertion(+)</code></pre>
1241
+ </div>
1242
+ </div>
1243
+ <div class="paragraph">
1244
+ <p>Now if we update our submodule we can see what happens when we have made a local change and upstream also has a change we need to incorporate.</p>
1245
+ </div>
1246
+ <div class="listingblock">
1247
+ <div class="content">
1248
+ <pre class="highlight"><code class="language-console" data-lang="console">$ cd ..
1249
+ $ git submodule update --remote --rebase
1250
+ First, rewinding head to replay your work on top of it...
1251
+ Applying: Unicode support
1252
+ Submodule path 'DbConnector': rebased into '5d60ef9bbebf5a0c1c1050f242ceeb54ad58da94'</code></pre>
1253
+ </div>
1254
+ </div>
1255
+ <div class="paragraph">
1256
+ <p>If you forget the <code>--rebase</code> or <code>--merge</code>, Git will just update the submodule to whatever is on the server and reset your project to a detached HEAD state.</p>
1257
+ </div>
1258
+ <div class="listingblock">
1259
+ <div class="content">
1260
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git submodule update --remote
1261
+ Submodule path 'DbConnector': checked out '5d60ef9bbebf5a0c1c1050f242ceeb54ad58da94'</code></pre>
1262
+ </div>
1263
+ </div>
1264
+ <div class="paragraph">
1265
+ <p>If this happens, don’t worry, you can simply go back into the directory and check out your branch again (which will still contain your work) and merge or rebase <code>origin/stable</code> (or whatever remote branch you want) manually.</p>
1266
+ </div>
1267
+ <div class="paragraph">
1268
+ <p>If you haven’t committed your changes in your submodule and you run a submodule update that would cause issues, Git will fetch the changes but not overwrite unsaved work in your submodule directory.</p>
1269
+ </div>
1270
+ <div class="listingblock">
1271
+ <div class="content">
1272
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git submodule update --remote
1273
+ remote: Counting objects: 4, done.
1274
+ remote: Compressing objects: 100% (3/3), done.
1275
+ remote: Total 4 (delta 0), reused 4 (delta 0)
1276
+ Unpacking objects: 100% (4/4), done.
1277
+ From https://github.com/chaconinc/DbConnector
1278
+ 5d60ef9..c75e92a stable -&gt; origin/stable
1279
+ error: Your local changes to the following files would be overwritten by checkout:
1280
+ scripts/setup.sh
1281
+ Please, commit your changes or stash them before you can switch branches.
1282
+ Aborting
1283
+ Unable to checkout 'c75e92a2b3855c9e5b66f915308390d9db204aca' in submodule path 'DbConnector'</code></pre>
1284
+ </div>
1285
+ </div>
1286
+ <div class="paragraph">
1287
+ <p>If you made changes that conflict with something changed upstream, Git will let you know when you run the update.</p>
1288
+ </div>
1289
+ <div class="listingblock">
1290
+ <div class="content">
1291
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git submodule update --remote --merge
1292
+ Auto-merging scripts/setup.sh
1293
+ CONFLICT (content): Merge conflict in scripts/setup.sh
1294
+ Recorded preimage for 'scripts/setup.sh'
1295
+ Automatic merge failed; fix conflicts and then commit the result.
1296
+ Unable to merge 'c75e92a2b3855c9e5b66f915308390d9db204aca' in submodule path 'DbConnector'</code></pre>
1297
+ </div>
1298
+ </div>
1299
+ <div class="paragraph">
1300
+ <p>You can go into the submodule directory and fix the conflict just as you normally would.</p>
1301
+ </div>
1302
+ </div>
1303
+ <div class="sect4">
1304
+ <h4 id="_publishing_submodules">Publishing Submodule Changes</h4>
1305
+ <div class="paragraph">
1306
+ <p>Now we have some changes in our submodule directory.
1307
+ Some of these were brought in from upstream by our updates and others were made locally and aren’t available to anyone else yet as we haven’t pushed them yet.</p>
1308
+ </div>
1309
+ <div class="listingblock">
1310
+ <div class="content">
1311
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git diff
1312
+ Submodule DbConnector c87d55d..82d2ad3:
1313
+ &gt; Merge from origin/stable
1314
+ &gt; Update setup script
1315
+ &gt; Unicode support
1316
+ &gt; Remove unnecessary method
1317
+ &gt; Add new option for conn pooling</code></pre>
1318
+ </div>
1319
+ </div>
1320
+ <div class="paragraph">
1321
+ <p>If we commit in the main project and push it up without pushing the submodule changes up as well, other people who try to check out our changes are going to be in trouble since they will have no way to get the submodule changes that are depended on.
1322
+ Those changes will only exist on our local copy.</p>
1323
+ </div>
1324
+ <div class="paragraph">
1325
+ <p>In order to make sure this doesn’t happen, you can ask Git to check that all your submodules have been pushed properly before pushing the main project.
1326
+ The <code>git push</code> command takes the <code>--recurse-submodules</code> argument which can be set to either “check” or “on-demand”.
1327
+ The “check” option will make <code>push</code> simply fail if any of the committed submodule changes haven’t been pushed.</p>
1328
+ </div>
1329
+ <div class="listingblock">
1330
+ <div class="content">
1331
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git push --recurse-submodules=check
1332
+ The following submodule paths contain changes that can
1333
+ not be found on any remote:
1334
+ DbConnector
1335
+
1336
+ Please try
1337
+
1338
+ git push --recurse-submodules=on-demand
1339
+
1340
+ or cd to the path and use
1341
+
1342
+ git push
1343
+
1344
+ to push them to a remote.</code></pre>
1345
+ </div>
1346
+ </div>
1347
+ <div class="paragraph">
1348
+ <p>As you can see, it also gives us some helpful advice on what we might want to do next.
1349
+ The simple option is to go into each submodule and manually push to the remotes to make sure they’re externally available and then try this push again.
1350
+ If you want the check behavior to happen for all pushes, you can make this behavior the default by doing <code>git config push.recurseSubmodules check</code>.</p>
1351
+ </div>
1352
+ <div class="paragraph">
1353
+ <p>The other option is to use the “on-demand” value, which will try to do this for you.</p>
1354
+ </div>
1355
+ <div class="listingblock">
1356
+ <div class="content">
1357
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git push --recurse-submodules=on-demand
1358
+ Pushing submodule 'DbConnector'
1359
+ Counting objects: 9, done.
1360
+ Delta compression using up to 8 threads.
1361
+ Compressing objects: 100% (8/8), done.
1362
+ Writing objects: 100% (9/9), 917 bytes | 0 bytes/s, done.
1363
+ Total 9 (delta 3), reused 0 (delta 0)
1364
+ To https://github.com/chaconinc/DbConnector
1365
+ c75e92a..82d2ad3 stable -&gt; stable
1366
+ Counting objects: 2, done.
1367
+ Delta compression using up to 8 threads.
1368
+ Compressing objects: 100% (2/2), done.
1369
+ Writing objects: 100% (2/2), 266 bytes | 0 bytes/s, done.
1370
+ Total 2 (delta 1), reused 0 (delta 0)
1371
+ To https://github.com/chaconinc/MainProject
1372
+ 3d6d338..9a377d1 master -&gt; master</code></pre>
1373
+ </div>
1374
+ </div>
1375
+ <div class="paragraph">
1376
+ <p>As you can see there, Git went into the DbConnector module and pushed it before pushing the main project.
1377
+ If that submodule push fails for some reason, the main project push will also fail.
1378
+ You can make this behavior the default by doing <code>git config push.recurseSubmodules on-demand</code>.</p>
1379
+ </div>
1380
+ </div>
1381
+ <div class="sect4">
1382
+ <h4 id="_merging_submodule_changes">Merging Submodule Changes</h4>
1383
+ <div class="paragraph">
1384
+ <p>If you change a submodule reference at the same time as someone else, you may run into some problems.
1385
+ That is, if the submodule histories have diverged and are committed to diverging branches in a superproject, it may take a bit of work for you to fix.</p>
1386
+ </div>
1387
+ <div class="paragraph">
1388
+ <p>If one of the commits is a direct ancestor of the other (a fast-forward merge), then Git will simply choose the latter for the merge, so that works fine.</p>
1389
+ </div>
1390
+ <div class="paragraph">
1391
+ <p>Git will not attempt even a trivial merge for you, however.
1392
+ If the submodule commits diverge and need to be merged, you will get something that looks like this:</p>
1393
+ </div>
1394
+ <div class="listingblock">
1395
+ <div class="content">
1396
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git pull
1397
+ remote: Counting objects: 2, done.
1398
+ remote: Compressing objects: 100% (1/1), done.
1399
+ remote: Total 2 (delta 1), reused 2 (delta 1)
1400
+ Unpacking objects: 100% (2/2), done.
1401
+ From https://github.com/chaconinc/MainProject
1402
+ 9a377d1..eb974f8 master -&gt; origin/master
1403
+ Fetching submodule DbConnector
1404
+ warning: Failed to merge submodule DbConnector (merge following commits not found)
1405
+ Auto-merging DbConnector
1406
+ CONFLICT (submodule): Merge conflict in DbConnector
1407
+ Automatic merge failed; fix conflicts and then commit the result.</code></pre>
1408
+ </div>
1409
+ </div>
1410
+ <div class="paragraph">
1411
+ <p>So basically what has happened here is that Git has figured out that the two branches record points in the submodule’s history that are divergent and need to be merged.
1412
+ It explains it as “merge following commits not found”, which is confusing but we’ll explain why that is in a bit.</p>
1413
+ </div>
1414
+ <div class="paragraph">
1415
+ <p>To solve the problem, you need to figure out what state the submodule should be in.
1416
+ Strangely, Git doesn’t really give you much information to help out here, not even the SHA-1s of the commits of both sides of the history.
1417
+ Fortunately, it’s simple to figure out.
1418
+ If you run <code>git diff</code> you can get the SHA-1s of the commits recorded in both branches you were trying to merge.</p>
1419
+ </div>
1420
+ <div class="listingblock">
1421
+ <div class="content">
1422
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git diff
1423
+ diff --cc DbConnector
1424
+ index eb41d76,c771610..0000000
1425
+ --- a/DbConnector
1426
+ +++ b/DbConnector</code></pre>
1427
+ </div>
1428
+ </div>
1429
+ <div class="paragraph">
1430
+ <p>So, in this case, <code>eb41d76</code> is the commit in our submodule that <strong>we</strong> had and <code>c771610</code> is the commit that upstream had.
1431
+ If we go into our submodule directory, it should already be on <code>eb41d76</code> as the merge would not have touched it.
1432
+ If for whatever reason it’s not, you can simply create and checkout a branch pointing to it.</p>
1433
+ </div>
1434
+ <div class="paragraph">
1435
+ <p>What is important is the SHA-1 of the commit from the other side.
1436
+ This is what you’ll have to merge in and resolve.
1437
+ You can either just try the merge with the SHA-1 directly, or you can create a branch for it and then try to merge that in.
1438
+ We would suggest the latter, even if only to make a nicer merge commit message.</p>
1439
+ </div>
1440
+ <div class="paragraph">
1441
+ <p>So, we will go into our submodule directory, create a branch named “try-merge” based on that second SHA-1 from <code>git diff</code>, and manually merge.</p>
1442
+ </div>
1443
+ <div class="listingblock">
1444
+ <div class="content">
1445
+ <pre class="highlight"><code class="language-console" data-lang="console">$ cd DbConnector
1446
+
1447
+ $ git rev-parse HEAD
1448
+ eb41d764bccf88be77aced643c13a7fa86714135
1449
+
1450
+ $ git branch try-merge c771610
1451
+
1452
+ $ git merge try-merge
1453
+ Auto-merging src/main.c
1454
+ CONFLICT (content): Merge conflict in src/main.c
1455
+ Recorded preimage for 'src/main.c'
1456
+ Automatic merge failed; fix conflicts and then commit the result.</code></pre>
1457
+ </div>
1458
+ </div>
1459
+ <div class="paragraph">
1460
+ <p>We got an actual merge conflict here, so if we resolve that and commit it, then we can simply update the main project with the result.</p>
1461
+ </div>
1462
+ <div class="listingblock">
1463
+ <div class="content">
1464
+ <pre class="highlight"><code class="language-console" data-lang="console">$ vim src/main.c <b class="conum">(1)</b>
1465
+ $ git add src/main.c
1466
+ $ git commit -am 'merged our changes'
1467
+ Recorded resolution for 'src/main.c'.
1468
+ [master 9fd905e] merged our changes
1469
+
1470
+ $ cd .. <b class="conum">(2)</b>
1471
+ $ git diff <b class="conum">(3)</b>
1472
+ diff --cc DbConnector
1473
+ index eb41d76,c771610..0000000
1474
+ --- a/DbConnector
1475
+ +++ b/DbConnector
1476
+ @@@ -1,1 -1,1 +1,1 @@@
1477
+ - Subproject commit eb41d764bccf88be77aced643c13a7fa86714135
1478
+ -Subproject commit c77161012afbbe1f58b5053316ead08f4b7e6d1d
1479
+ ++Subproject commit 9fd905e5d7f45a0d4cbc43d1ee550f16a30e825a
1480
+ $ git add DbConnector <b class="conum">(4)</b>
1481
+
1482
+ $ git commit -m "Merge Tom's Changes" <b class="conum">(5)</b>
1483
+ [master 10d2c60] Merge Tom's Changes</code></pre>
1484
+ </div>
1485
+ </div>
1486
+ <div class="colist arabic">
1487
+ <ol>
1488
+ <li>
1489
+ <p>First we resolve the conflict.</p>
1490
+ </li>
1491
+ <li>
1492
+ <p>Then we go back to the main project directory.</p>
1493
+ </li>
1494
+ <li>
1495
+ <p>We can check the SHA-1s again.</p>
1496
+ </li>
1497
+ <li>
1498
+ <p>Resolve the conflicted submodule entry.</p>
1499
+ </li>
1500
+ <li>
1501
+ <p>Commit our merge.</p>
1502
+ </li>
1503
+ </ol>
1504
+ </div>
1505
+ <div class="paragraph">
1506
+ <p>It can be a bit confusing, but it’s really not very hard.</p>
1507
+ </div>
1508
+ <div class="paragraph">
1509
+ <p>Interestingly, there is another case that Git handles.
1510
+ If a merge commit exists in the submodule directory that contains <strong>both</strong> commits in its history, Git will suggest it to you as a possible solution.
1511
+ It sees that at some point in the submodule project, someone merged branches containing these two commits, so maybe you’ll want that one.</p>
1512
+ </div>
1513
+ <div class="paragraph">
1514
+ <p>This is why the error message from before was “merge following commits not found”, because it could not do <strong>this</strong>.
1515
+ It’s confusing because who would expect it to <strong>try</strong> to do this?</p>
1516
+ </div>
1517
+ <div class="paragraph">
1518
+ <p>If it does find a single acceptable merge commit, you’ll see something like this:</p>
1519
+ </div>
1520
+ <div class="listingblock">
1521
+ <div class="content">
1522
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git merge origin/master
1523
+ warning: Failed to merge submodule DbConnector (not fast-forward)
1524
+ Found a possible merge resolution for the submodule:
1525
+ 9fd905e5d7f45a0d4cbc43d1ee550f16a30e825a: &gt; merged our changes
1526
+ If this is correct simply add it to the index for example
1527
+ by using:
1528
+
1529
+ git update-index --cacheinfo 160000 9fd905e5d7f45a0d4cbc43d1ee550f16a30e825a "DbConnector"
1530
+
1531
+ which will accept this suggestion.
1532
+ Auto-merging DbConnector
1533
+ CONFLICT (submodule): Merge conflict in DbConnector
1534
+ Automatic merge failed; fix conflicts and then commit the result.</code></pre>
1535
+ </div>
1536
+ </div>
1537
+ <div class="paragraph">
1538
+ <p>The suggested command Git is providing will update the index as though you had run <code>git add</code> (which clears the conflict), then commit.
1539
+ You probably shouldn’t do this though.
1540
+ You can just as easily go into the submodule directory, see what the difference is, fast-forward to this commit, test it properly, and then commit it.</p>
1541
+ </div>
1542
+ <div class="listingblock">
1543
+ <div class="content">
1544
+ <pre class="highlight"><code class="language-console" data-lang="console">$ cd DbConnector/
1545
+ $ git merge 9fd905e
1546
+ Updating eb41d76..9fd905e
1547
+ Fast-forward
1548
+
1549
+ $ cd ..
1550
+ $ git add DbConnector
1551
+ $ git commit -am 'Fast forward to a common submodule child'</code></pre>
1552
+ </div>
1553
+ </div>
1554
+ <div class="paragraph">
1555
+ <p>This accomplishes the same thing, but at least this way you can verify that it works and you have the code in your submodule directory when you’re done.</p>
1556
+ </div>
1557
+ </div>
1558
+ </div>
1559
+ <div class="sect3">
1560
+ <h3 id="_submodule_tips">Submodule Tips</h3>
1561
+ <div class="paragraph">
1562
+ <p>There are a few things you can do to make working with submodules a little easier.</p>
1563
+ </div>
1564
+ <div class="sect4">
1565
+ <h4 id="_submodule_foreach">Submodule Foreach</h4>
1566
+ <div class="paragraph">
1567
+ <p>There is a <code>foreach</code> submodule command to run some arbitrary command in each submodule.
1568
+ This can be really helpful if you have a number of submodules in the same project.</p>
1569
+ </div>
1570
+ <div class="paragraph">
1571
+ <p>For example, let’s say we want to start a new feature or do a bugfix and we have work going on in several submodules.
1572
+ We can easily stash all the work in all our submodules.</p>
1573
+ </div>
1574
+ <div class="listingblock">
1575
+ <div class="content">
1576
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git submodule foreach 'git stash'
1577
+ Entering 'CryptoLibrary'
1578
+ No local changes to save
1579
+ Entering 'DbConnector'
1580
+ Saved working directory and index state WIP on stable: 82d2ad3 Merge from origin/stable
1581
+ HEAD is now at 82d2ad3 Merge from origin/stable</code></pre>
1582
+ </div>
1583
+ </div>
1584
+ <div class="paragraph">
1585
+ <p>Then we can create a new branch and switch to it in all our submodules.</p>
1586
+ </div>
1587
+ <div class="listingblock">
1588
+ <div class="content">
1589
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git submodule foreach 'git checkout -b featureA'
1590
+ Entering 'CryptoLibrary'
1591
+ Switched to a new branch 'featureA'
1592
+ Entering 'DbConnector'
1593
+ Switched to a new branch 'featureA'</code></pre>
1594
+ </div>
1595
+ </div>
1596
+ <div class="paragraph">
1597
+ <p>You get the idea.
1598
+ One really useful thing you can do is produce a nice unified diff of what is changed in your main project and all your subprojects as well.</p>
1599
+ </div>
1600
+ <div class="listingblock">
1601
+ <div class="content">
1602
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git diff; git submodule foreach 'git diff'
1603
+ Submodule DbConnector contains modified content
1604
+ diff --git a/src/main.c b/src/main.c
1605
+ index 210f1ae..1f0acdc 100644
1606
+ --- a/src/main.c
1607
+ +++ b/src/main.c
1608
+ @@ -245,6 +245,8 @@ static int handle_alias(int *argcp, const char ***argv)
1609
+
1610
+ commit_pager_choice();
1611
+
1612
+ + url = url_decode(url_orig);
1613
+ +
1614
+ /* build alias_argv */
1615
+ alias_argv = xmalloc(sizeof(*alias_argv) * (argc + 1));
1616
+ alias_argv[0] = alias_string + 1;
1617
+ Entering 'DbConnector'
1618
+ diff --git a/src/db.c b/src/db.c
1619
+ index 1aaefb6..5297645 100644
1620
+ --- a/src/db.c
1621
+ +++ b/src/db.c
1622
+ @@ -93,6 +93,11 @@ char *url_decode_mem(const char *url, int len)
1623
+ return url_decode_internal(&amp;url, len, NULL, &amp;out, 0);
1624
+ }
1625
+
1626
+ +char *url_decode(const char *url)
1627
+ +{
1628
+ + return url_decode_mem(url, strlen(url));
1629
+ +}
1630
+ +
1631
+ char *url_decode_parameter_name(const char **query)
1632
+ {
1633
+ struct strbuf out = STRBUF_INIT;</code></pre>
1634
+ </div>
1635
+ </div>
1636
+ <div class="paragraph">
1637
+ <p>Here we can see that we’re defining a function in a submodule and calling it in the main project.
1638
+ This is obviously a simplified example, but hopefully it gives you an idea of how this may be useful.</p>
1639
+ </div>
1640
+ </div>
1641
+ <div class="sect4">
1642
+ <h4 id="_useful_aliases">Useful Aliases</h4>
1643
+ <div class="paragraph">
1644
+ <p>You may want to set up some aliases for some of these commands as they can be quite long and you can’t set configuration options for most of them to make them defaults.
1645
+ We covered setting up Git aliases in <a href="_git_aliases.html">Git Aliases</a>, but here is an example of what you may want to set up if you plan on working with submodules in Git a lot.</p>
1646
+ </div>
1647
+ <div class="listingblock">
1648
+ <div class="content">
1649
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git config alias.sdiff '!'"git diff &amp;&amp; git submodule foreach 'git diff'"
1650
+ $ git config alias.spush 'push --recurse-submodules=on-demand'
1651
+ $ git config alias.supdate 'submodule update --remote --merge'</code></pre>
1652
+ </div>
1653
+ </div>
1654
+ <div class="paragraph">
1655
+ <p>This way you can simply run <code>git supdate</code> when you want to update your submodules, or <code>git spush</code> to push with submodule dependency checking.</p>
1656
+ </div>
1657
+ </div>
1658
+ </div>
1659
+ <div class="sect3">
1660
+ <h3 id="_issues_with_submodules">Issues with Submodules</h3>
1661
+ <div class="paragraph">
1662
+ <p>Using submodules isn’t without hiccups, however.</p>
1663
+ </div>
1664
+ <div class="sect4">
1665
+ <h4 id="_switching_branches_2">Switching branches</h4>
1666
+ <div class="paragraph">
1667
+ <p>For instance, switching branches with submodules in them can also be tricky with Git versions older than Git 2.13.
1668
+ If you create a new branch, add a submodule there, and then switch back to a branch without that submodule, you still have the submodule directory as an untracked directory:</p>
1669
+ </div>
1670
+ <div class="listingblock">
1671
+ <div class="content">
1672
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git --version
1673
+ git version 2.12.2
1674
+
1675
+ $ git checkout -b add-crypto
1676
+ Switched to a new branch 'add-crypto'
1677
+
1678
+ $ git submodule add https://github.com/chaconinc/CryptoLibrary
1679
+ Cloning into 'CryptoLibrary'...
1680
+ ...
1681
+
1682
+ $ git commit -am 'Add crypto library'
1683
+ [add-crypto 4445836] Add crypto library
1684
+ 2 files changed, 4 insertions(+)
1685
+ create mode 160000 CryptoLibrary
1686
+
1687
+ $ git checkout master
1688
+ warning: unable to rmdir CryptoLibrary: Directory not empty
1689
+ Switched to branch 'master'
1690
+ Your branch is up-to-date with 'origin/master'.
1691
+
1692
+ $ git status
1693
+ On branch master
1694
+ Your branch is up-to-date with 'origin/master'.
1695
+
1696
+ Untracked files:
1697
+ (use "git add &lt;file&gt;..." to include in what will be committed)
1698
+
1699
+ CryptoLibrary/
1700
+
1701
+ nothing added to commit but untracked files present (use "git add" to track)</code></pre>
1702
+ </div>
1703
+ </div>
1704
+ <div class="paragraph">
1705
+ <p>Removing the directory isn’t difficult, but it can be a bit confusing to have that in there.
1706
+ If you do remove it and then switch back to the branch that has that submodule, you will need to run <code>submodule update --init</code> to repopulate it.</p>
1707
+ </div>
1708
+ <div class="listingblock">
1709
+ <div class="content">
1710
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git clean -ffdx
1711
+ Removing CryptoLibrary/
1712
+
1713
+ $ git checkout add-crypto
1714
+ Switched to branch 'add-crypto'
1715
+
1716
+ $ ls CryptoLibrary/
1717
+
1718
+ $ git submodule update --init
1719
+ Submodule path 'CryptoLibrary': checked out 'b8dda6aa182ea4464f3f3264b11e0268545172af'
1720
+
1721
+ $ ls CryptoLibrary/
1722
+ Makefile includes scripts src</code></pre>
1723
+ </div>
1724
+ </div>
1725
+ <div class="paragraph">
1726
+ <p>Again, not really very difficult, but it can be a little confusing.</p>
1727
+ </div>
1728
+ <div class="paragraph">
1729
+ <p>Newer Git versions (Git &gt;= 2.13) simplify all this by adding the <code>--recurse-submodules</code> flag to the <code>git checkout</code> command, which takes care of placing the submodules in the right state for the branch we are switching to.</p>
1730
+ </div>
1731
+ <div class="listingblock">
1732
+ <div class="content">
1733
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git --version
1734
+ git version 2.13.3
1735
+
1736
+ $ git checkout -b add-crypto
1737
+ Switched to a new branch 'add-crypto'
1738
+
1739
+ $ git submodule add https://github.com/chaconinc/CryptoLibrary
1740
+ Cloning into 'CryptoLibrary'...
1741
+ ...
1742
+
1743
+ $ git commit -am 'Add crypto library'
1744
+ [add-crypto 4445836] Add crypto library
1745
+ 2 files changed, 4 insertions(+)
1746
+ create mode 160000 CryptoLibrary
1747
+
1748
+ $ git checkout --recurse-submodules master
1749
+ Switched to branch 'master'
1750
+ Your branch is up-to-date with 'origin/master'.
1751
+
1752
+ $ git status
1753
+ On branch master
1754
+ Your branch is up-to-date with 'origin/master'.
1755
+
1756
+ nothing to commit, working tree clean</code></pre>
1757
+ </div>
1758
+ </div>
1759
+ <div class="paragraph">
1760
+ <p>Using the <code>--recurse-submodules</code> flag of <code>git checkout</code> can also be useful when you work on several branches in the superproject, each having your submodule pointing at different commits.
1761
+ Indeed, if you switch between branches that record the submodule at different commits, upon executing <code>git status</code> the submodule will appear as “modified”, and indicate “new commits”.
1762
+ That is because the submodule state is by default not carried over when switching branches.</p>
1763
+ </div>
1764
+ <div class="paragraph">
1765
+ <p>This can be really confusing, so it’s a good idea to always <code>git checkout --recurse-submodules</code> when your project has submodules.
1766
+ For older Git versions that do not have the <code>--recurse-submodules</code> flag, after the checkout you can use <code>git submodule update --init --recursive</code> to put the submodules in the right state.</p>
1767
+ </div>
1768
+ <div class="paragraph">
1769
+ <p>Luckily, you can tell Git (&gt;=2.14) to always use the <code>--recurse-submodules</code> flag by setting the configuration option <code>submodule.recurse</code>: <code>git config submodule.recurse true</code>.
1770
+ As noted above, this will also make Git recurse into submodules for every command that has a <code>--recurse-submodules</code> option (except <code>git clone</code>).</p>
1771
+ </div>
1772
+ </div>
1773
+ <div class="sect4">
1774
+ <h4 id="_switching_from_subdirectories_to_submodules">Switching from subdirectories to submodules</h4>
1775
+ <div class="paragraph">
1776
+ <p>The other main caveat that many people run into involves switching from subdirectories to submodules.
1777
+ If you’ve been tracking files in your project and you want to move them out into a submodule, you must be careful or Git will get angry at you.
1778
+ Assume that you have files in a subdirectory of your project, and you want to switch it to a submodule.
1779
+ If you delete the subdirectory and then run <code>submodule add</code>, Git yells at you:</p>
1780
+ </div>
1781
+ <div class="listingblock">
1782
+ <div class="content">
1783
+ <pre class="highlight"><code class="language-console" data-lang="console">$ rm -Rf CryptoLibrary/
1784
+ $ git submodule add https://github.com/chaconinc/CryptoLibrary
1785
+ 'CryptoLibrary' already exists in the index</code></pre>
1786
+ </div>
1787
+ </div>
1788
+ <div class="paragraph">
1789
+ <p>You have to unstage the <code>CryptoLibrary</code> directory first.
1790
+ Then you can add the submodule:</p>
1791
+ </div>
1792
+ <div class="listingblock">
1793
+ <div class="content">
1794
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git rm -r CryptoLibrary
1795
+ $ git submodule add https://github.com/chaconinc/CryptoLibrary
1796
+ Cloning into 'CryptoLibrary'...
1797
+ remote: Counting objects: 11, done.
1798
+ remote: Compressing objects: 100% (10/10), done.
1799
+ remote: Total 11 (delta 0), reused 11 (delta 0)
1800
+ Unpacking objects: 100% (11/11), done.
1801
+ Checking connectivity... done.</code></pre>
1802
+ </div>
1803
+ </div>
1804
+ <div class="paragraph">
1805
+ <p>Now suppose you did that in a branch.
1806
+ If you try to switch back to a branch where those files are still in the actual tree rather than a submodule – you get this error:</p>
1807
+ </div>
1808
+ <div class="listingblock">
1809
+ <div class="content">
1810
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git checkout master
1811
+ error: The following untracked working tree files would be overwritten by checkout:
1812
+ CryptoLibrary/Makefile
1813
+ CryptoLibrary/includes/crypto.h
1814
+ ...
1815
+ Please move or remove them before you can switch branches.
1816
+ Aborting</code></pre>
1817
+ </div>
1818
+ </div>
1819
+ <div class="paragraph">
1820
+ <p>You can force it to switch with <code>checkout -f</code>, but be careful that you don’t have unsaved changes in there as they could be overwritten with that command.</p>
1821
+ </div>
1822
+ <div class="listingblock">
1823
+ <div class="content">
1824
+ <pre class="highlight"><code class="language-console" data-lang="console">$ git checkout -f master
1825
+ warning: unable to rmdir CryptoLibrary: Directory not empty
1826
+ Switched to branch 'master'</code></pre>
1827
+ </div>
1828
+ </div>
1829
+ <div class="paragraph">
1830
+ <p>Then, when you switch back, you get an empty <code>CryptoLibrary</code> directory for some reason and <code>git submodule update</code> may not fix it either.
1831
+ You may need to go into your submodule directory and run a <code>git checkout .</code> to get all your files back.
1832
+ You could run this in a <code>submodule foreach</code> script to run it for multiple submodules.</p>
1833
+ </div>
1834
+ <div class="paragraph">
1835
+ <p>It’s important to note that submodules these days keep all their Git data in the top project’s <code>.git</code> directory, so unlike much older versions of Git, destroying a submodule directory won’t lose any commits or branches that you had.</p>
1836
+ </div>
1837
+ <div class="paragraph">
1838
+ <p>With these tools, submodules can be a fairly simple and effective method for developing on several related but still separate projects simultaneously.</p>
1839
+ </div>
1840
+ </div>
1841
+ </div>
1842
+ <div id="nav"><a href="_file_annotation.html">prev</a> | <a href="_bundling.html">next</a></div></div>
1843
+ </div>
1844
+
1845
+ </div>
1846
+ </div>
1847
+ <footer>
1848
+ <div class="site-source">
1849
+ <a href="https://git-scm.com/site">About this site</a><br>
1850
+ Patches, suggestions, and comments are welcome.
1851
+ </div>
1852
+ <div class="sfc-member">
1853
+ Git is a member of <a href="https://git-scm.com/sfc">Software Freedom Conservancy</a>
1854
+ </div>
1855
+ </footer>
1856
+ <a href="_publishing_submodules.html#top" class="no-js scrollToTop" id="scrollToTop" data-label="Scroll to top">
1857
+ <img src="../../../../images/icons/chevron-up@2x.png" width="20" height="20" alt="scroll-to-top"/>
1858
+ </a>
1859
+ <script src="../../../../assets/application-38b0d42ff05ffea45841edebbd14b75b89585646153808e82907c2c5c11f324b.js"></script>
1860
+
1861
+ </div>
1862
+
1863
+ </body>
1864
+ </html>