Blame view

README.md 3.73 KB
039733c1   Lars Tiede   demo step by step
1
2
  ### This is the parent that uses "git submodule".
  
7d188012   Lars Tiede   demo text
3
4
5
6
7
8
9
10
11
  Here's how you can re-trace the demo given at utviklerlunsj.
  
  First, make yourself a directory and clone the repository into it:
  
  ```bash
  git clone git@source.uit.no:lars.tiede/lunsjdemo_parent_with_submodule.git .
  ```
  
  Now reset your working copy of this repository to the commit right before we added the submodule:
039733c1   Lars Tiede   demo step by step
12
13
14
15
16
  
  ```bash
  git reset --hard 375c69b8e9ffb36b79c0d7cc0121d622c5b169aa
  ```
  
80f26660   Lars Tiede   instructions with...
17
18
19
20
21
22
23
  Okay, now there shouldn't be any my\_lib. Let's make ourselves a branch in order to not mess up the master branch:
  
  ```bash
  git checkout -b YOU_CHOOSE
  ```
  
  Now add my\_lib as a submodule:
039733c1   Lars Tiede   demo step by step
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  
  ```bash
  git submodule add git@source.uit.no:lars.tiede/lunsjdemo_my_lib.git my_lib
  git status # shows new metadata file .gitmodules and new *file* my_lib
  git commit -m "[parent_with_submodule] added my_lib submodule"
  ```
  
  After committing, we can inspect what git actually did:
  
  ```bash
  git show # all changes in last commit, note that git doesn't save the contents of my_lib but rather a reference to a commit SHA
  git cat-file -p HEAD^{tree} # this is (some of) what git actually stored in the last commit. Note the special "type" of my_lib - if it was a file, it would be "blob", if it was a directory, it would be "tree".
  ```
  
  You'll find that in the directory 'my\_lib', you are in a different repository:
  
  ```bash
  git remote -v # shows that origin is "parent_with_submodule"
  cd my_lib
  git remote -v # shows that origin is "my_lib"
  cd ..
  ```
  
  The outputs of 'git log' and 'git status' will differ as well.
  
  Now do some random change in my\_lib and commit it. When you then do a 'git status' in parent, it will show that my\_lib has changed ("new commits"). 'git diff my\_lib' will show the change to the referenced commit SHA.
  
  Now we will deliberately do something awful and commit parent *and push it to origin*.
  
  ```bash
  git add my_lib
  git commit -m "new version of my_lib"
80f26660   Lars Tiede   instructions with...
56
  git push --set-upstream origin YOUR_BRANCH_NAME
039733c1   Lars Tiede   demo step by step
57
58
59
60
61
62
63
64
  ```
  
  Now what do you think will happen when somebody wants to clone that? Let's try:
  
  ```bash
  cd ..
  mkdir temp_clone
  cd temp_clone
80f26660   Lars Tiede   instructions with...
65
  git clone -b YOUR_BRANCH_NAME --recursive git@source.uit.no:lars.tiede/lunsjdemo_parent_with_submodule.git .
039733c1   Lars Tiede   demo step by step
66
67
68
69
70
71
72
73
74
  ```
  
  Notice the '--recursive' option? You have to do that in order to not only clone parent, but also all submodules of parent. Yes, you and your users will forget about that constantly. This is the biggest headache with submodules. But there's another. Check this at the end of the output:
  
  ```bash
  fatal: reference is not a tree: 5870fc7691231edf23517055b09768e00e123bf7
  Unable to checkout '5870fc7691231edf23517055b09768e00e123bf7' in submodule path 'my_lib'
  ```
  
80f26660   Lars Tiede   instructions with...
75
  (Your hash will differ). Git couldn't clone the referenced commit of my\_lib *because it did not find it*. And that is because we did not push (i.e. publish) our changes to my\_lib before we published our changes to parent. **Always push children before you push parent** in order to make sure that the published parent always points to commits of children that are already published..
039733c1   Lars Tiede   demo step by step
76
77
78
79
80
81
82
83
84
  
  So here's how we fix this: push the child, then update the submodules in our temporary working copy. Pushing the child is easy, here's how you pull and update submodules in temp\_clone:
  
  ```bash
  git submodule update --init --recursive
  ```
  
  That command clones submodules if they haven't been cloned yet, and it pulls a new commit when parent's reference has changed. So that command is what you also have to do after every 'git pull' of parent. This is the second big headache with submodules: you have to remember to update the submodules after 'git pull'.
  
80f26660   Lars Tiede   instructions with...
85
86
87
88
89
90
91
  But that's basically it, now you know how submodules work. Delete your branch now so that there is no pollution here:
  
  ```bash
  git push origin --delete YOUR_BRANCH_NAME
  ```
  
  Finally, you can delete temp\_clone.