40 | | The following table, based on actual tests run using git version 1.8.4.msysgit.0, shows the effects on a submodule of the above commands. |
| 40 | See {wiki:#Effectsofgitsubmoduleupdate Effects of {{{git submodule update}}}] for details. |
| 41 | |
| 42 | To get more information about a submodule: |
| 43 | |
| 44 | {{{ |
| 45 | cd modular-boost |
| 46 | git submodule summary |
| 47 | }}} |
| 48 | |
| 49 | If for some reason you wanted to test against the current head of {{{master}}} for all libraries, disregarding the super-project state, the {{{git submodule update}}} command would be changed to: |
| 50 | |
| 51 | {{{ |
| 52 | git submodule foreach --recursive "git checkout master; git pull" |
| 53 | }}} |
| 54 | |
| 55 | === Check out the development branch of your library === |
| 56 | |
| 57 | You can see what branch {{{mylib}}} is currently on like this: |
| 58 | |
| 59 | {{{ |
| 60 | cd modular-boost/libs/mylib |
| 61 | git branch |
| 62 | }}} |
| 63 | |
| 64 | Then if you need to change the branch to a development branch such as {{{develop}}}, do this: |
| 65 | |
| 66 | {{{ |
| 67 | cd modular-boost/libs/mylib |
| 68 | git checkout develop |
| 69 | }}} |
| 70 | |
| 71 | You only have to do that once; your local repo working copy will sit on the branch until it is explicitly changed by a command you give. |
| 72 | |
| 73 | Of course, you don't have to change the directory before every command, and from here on this tutorial will assume the directory has not been changed since the prior example. |
| 74 | |
| 75 | If there is any possibility the branch head content in the public upstream repo has changed, you also will want to update content: |
| 76 | |
| 77 | {{{ |
| 78 | cd modular-boost/libs/mylib |
| 79 | git pull |
| 80 | }}} |
| 81 | |
| 82 | From this point on, it is assumed you have already done a {{{cd modular-boost/libs/mylib}}}. |
| 83 | |
| 84 | === Testing locally === |
| 85 | |
| 86 | Unless you are 100% sure of the state of your library's regression tests, it is a good idea to run the regression tests before making any changes to the library: |
| 87 | |
| 88 | {{{ |
| 89 | pushd test |
| 90 | b2 |
| 91 | popd |
| 92 | }}} |
| 93 | |
| 94 | === Checking status === |
| 95 | |
| 96 | Before making changes, it is a good idea to check status. Here is what that looks like on Windows; the |
| 97 | message you get may vary somewhat: |
| 98 | |
| 99 | {{{ |
| 100 | >git status |
| 101 | # On branch develop |
| 102 | nothing to commit, working directory clean |
| 103 | }}} |
| 104 | |
| 105 | === Fix a simple bug directly on {{{develop}}} === |
| 106 | |
| 107 | For simple bugs, particularly in projects with a single maintainer, it is common practice to fix bugs directly in the {{{develop}}} branch. Creating a test case with your favorite editor, testing the test case, fixing the bug, testing the fix, and then iterating if necessary is no different than with any programming environment. |
| 108 | |
| 109 | Once the fix is complete, you then commit the fix locally and push from your local repo up to your public boostorg repo on GitHub. These same commands would be used for any Git project, modular or not, so hopefully you are already somewhat familiar with them: |
| 110 | |
| 111 | {{{ |
| 112 | cd modular-boost/libs/mylib |
| 113 | git commit -a -m "my bug fix" |
| 114 | git push |
| 115 | }}} |
| 116 | |
| 117 | There are some significant disadvantages to this simple approach: |
| 118 | * The fix is now made to {{{develop}}} but you must remember to merge it to a release branch or directly to {{{master}}}. It is very easy to forget to do that merge, particularly if this is a mature library you are not working with very often. |
| 119 | * Users who need the bug fix right away are forced to jump through hoops to retrieve the fix from {{{develop}}}. |
| 120 | |
| 121 | Putting out a point release solves both of those problems. Read on... |
| 122 | |
| 123 | === Fix a bug using a hot-fix branch === |
| 124 | |
| 125 | Fixing a bug directly on the {{{develop}}} branch is fine, if that's the library's policy, but if the bug is messy, multiple maintainers are involved, interruptions are expected, or other complexities are present, then it is better practice to work on the bug in a separate branch. And doing that on a hot-fix branch solves the problems mentioned at the end of the prior section. |
| 126 | |
| 127 | The operational distinction between a bug-fix branch and a hot-fix branch is that a bug-fix branch is branched from {{{develop}}} and then at completion merged back to {{{develop}}}, while a hot-fix branch is branched from {{{master}}} and then at completion is merged to both {{{master}}} and {{{develop}}}. With either approach, the branch is deleted after it has been merged. |
| 128 | |
| 129 | {{{ |
| 130 | git checkout master |
| 131 | git checkout -b hotfix/complex-boo-boo |
| 132 | }}} |
| 133 | |
| 134 | This creates the branch {{{hotfix/complex-boo-boo}}}, and switches to it. Incidentally, {{{hotfix/}}} is part of the name, not a directory specifier. The new branch is based on branch {{{master}}} because the working copy was on branch {{{master}}} at the time of the branch. |
| 135 | |
| 136 | Since the bug is complex, it may take some time to fix and may go through several cycles of fixes, tests, and commits. |
| 137 | |
| 138 | Once the bug is fixed and a final commit is done, then it is time to merge the {{{hotfix/complex-boo-boo}}} branch into {{{master}}} and {{{develop}}}: |
| 139 | |
| 140 | {{{ |
| 141 | git checkout master |
| 142 | git merge hotfix/complex-boo-boo |
| 143 | git push |
| 144 | git checkout develop |
| 145 | git merge hotfix/complex-boo-boo |
| 146 | git push |
| 147 | git branch -d hotfix/complex-boo-boo |
| 148 | }}} |
| 149 | |
| 150 | === Start work on a new feature === |
| 151 | |
| 152 | Developers are encouraged to create a (possibly private) branch to work on new features, even simple ones, since development of new features on the {{{develop}}} branch might leave it unstable for longer that expected. Using the Git Flow convention, the branch will be named {{{feature/add-checksum-option}}}. |
| 153 | |
| 154 | {{{ |
| 155 | git checkout develop |
| 156 | git checkout -b feature/add-checksum-option |
| 157 | }}} |
| 158 | |
| 159 | When you create the branch, or perhaps later, you may decide the branch should be public (i.e. be present in the library's public boostorg repo) so that you can share the branch with others or just to back it up. If so, set that up by running: |
| 160 | |
| 161 | {{{ |
| 162 | git push --set-upstream origin feature/add-checksum-option |
| 163 | }}} |
| 164 | |
| 165 | Whether or not {{{--set-upstream origin bugfix/complex-boo-boo}}} is actually needed depends on the {{{branch.autosetupmerge}}} configuration variable that isn't discussed here. If you don't supply {{{--set-upstream origin bugfix/complex-boo-boo}}} on your first {{{push}}} and it turns out to be needed, you will get an error message explaining that. |
| 166 | |
| 167 | |
| 168 | The usual cycle of coding, testing, commits, and pushes (if public) then begins. If other work needs to be done, a {{{stash}}} or {{{commit}}} may be done to save work-in-progress, and the working copy switched to another branch for awhile. If significant fixes or other enhancements have been made to {{{develop}}} over time, it may be useful to merge {{{develop}}} into the feature branch so that the eventual merge back to {{{develop}}} has less conflicts. Here is how the merge from {{{develop}}} to {{{feature/add-checksum-option}}} is done: |
| 169 | |
| 170 | {{{ |
| 171 | git checkout feature/add-checksum-option |
| 172 | git merge develop |
| 173 | }}} |
| 174 | |
| 175 | == First post-svn conversion merge to {{{master}}} == |
| 176 | |
| 177 | When you are ready to merge the {{{develop}}} branch to {{{master}}} (or better yet a release branch that's branched off {{{master}}}), there's a bit of housekeeping to be done the first time after the conversion from svn so that future merges proceed smoothly. We're going to create a merge point between |
| 178 | the develop and master branches so that Git knows the last point the two branches were in synch. Once we've done that Git will perform a merge by replaying the commits on develop on top of master, starting from the last known merge: in other words Git will perform the tricky stuff of figuring out what to merge for us. |
| 179 | |
| 180 | * Navigate to the history for your library on !GitHub, starting with branch master. For example the Config library [https://github.com/boostorg/config/commits/master can be seen here]. |
| 181 | * Look down through the commit history and make a note of the last merge in svn land. In our example, it was on October 25th 2013. |
| 182 | * Use the dropdown box to change the history to point to the develop branch. [https://github.com/boostorg/config/commits/develop Config library can be seen here]. |
| 183 | * Find the last commit '''before the date noted above'''. Click on the commit message for that commit to go to the actual diff for that change, [https://github.com/boostorg/config/commit/67f6b934f161dc5da2039004986a14d9217afae4 in our example here]. The SHA1 for that commit is shown below and to the right of the commit message, in this case it's {{{67f6b934f161dc5da2039004986a14d9217afae4}}}. Copy that SHA1 to your clipboard. |
| 184 | |
| 185 | Create a merge to that specific commit. Begin by changing your library to the master branch: |
| 186 | |
| 187 | {{{ |
| 188 | git checkout master |
| 189 | }}} |
| 190 | |
| 191 | Now create a merge to the specific commit above; since we don't really want to actually change the master branch we'll use the {{{-s ours}}} option to avoid any conflicts: |
| 192 | |
| 193 | {{{ |
| 194 | git merge --no-ff --no-commit -s ours 67f6b934f161dc5da2039004986a14d9217afae4 |
| 195 | }}} |
| 196 | |
| 197 | You can now use {{{git status}}} and {{{git diff}}} to check for modifications, in this case there are none. Now make the commit and push to !GitHub: |
| 198 | |
| 199 | {{{ |
| 200 | git commit -am "Create first merge point for Git" |
| 201 | git push |
| 202 | }}} |
| 203 | |
| 204 | Then navigate to your libraries history again, and check that the merge shows up, [https://github.com/boostorg/config/commits/master our config example is here]. |
| 205 | You're now ready for "routine" merges to proceed as per Git Flow (or whatever other strategy you wish to use). |
| 206 | |
| 207 | === Lightweight library release === |
| 208 | |
| 209 | Small, simple libraries and simple releases just merge {{{develop}}} into {{{master}}}, tag {{{master}}}, and declare victory. |
| 210 | |
| 211 | {{{ |
| 212 | git checkout master |
| 213 | git merge --no-ff develop |
| 214 | git tag -a 1.56.1 |
| 215 | }}} |
| 216 | |
| 217 | === Heavyweight library release === |
| 218 | |
| 219 | Large, complex libraries, particularly those with multiple developers working in parallel, need to use a release procedure that scales up better than the lightweight procedure. The Git Flow approach is recommended. Find out more at [wiki:StartModWorkflow Modular Boost Library Workflow Overview] and be sure to study the examples given in [http://nvie.com/posts/a-successful-git-branching-model/ Vincent Driessen's original blog posting]. |
| 220 | |
| 221 | == Effects of {{{git submodule update}}}== |
| 222 | |
| 223 | The following table, based on actual tests run using git version 1.8.4.msysgit.0, shows the effects on a submodule of: |
| 224 | |
| 225 | {{{ |
| 226 | cd modular-boost |
| 227 | git checkout master |
| 228 | git pull |
| 229 | git submodule update |
| 230 | }}} |
62 | | To get more information about submodules: |
63 | | |
64 | | {{{ |
65 | | cd modular-boost |
66 | | git submodule summary |
67 | | }}} |
68 | | |
69 | | If for some reason you wanted to test against the current head of {{{master}}} for all libraries, disregarding the super-project state, the {{{git submodule update}}} command would be changed to: |
70 | | |
71 | | {{{ |
72 | | git submodule foreach --recursive "git checkout master; git pull" |
73 | | }}} |
74 | | |
75 | | === Check out the development branch of your library === |
76 | | |
77 | | You can see what branch {{{mylib}}} is currently on like this: |
78 | | |
79 | | {{{ |
80 | | cd modular-boost/libs/mylib |
81 | | git branch |
82 | | }}} |
83 | | |
84 | | Then if you need to change the branch to a development branch such as {{{develop}}}, do this: |
85 | | |
86 | | {{{ |
87 | | cd modular-boost/libs/mylib |
88 | | git checkout develop |
89 | | }}} |
90 | | |
91 | | You only have to do that once; your local repo working copy will sit on the branch until it is explicitly changed by a command you give. |
92 | | |
93 | | Of course, you don't have to change the directory before every command, and from here on this tutorial will assume the directory has not been changed since the prior example. |
94 | | |
95 | | If there is any possibility the branch head content in the public upstream repo has changed, you also will want to update content: |
96 | | |
97 | | {{{ |
98 | | cd modular-boost/libs/mylib |
99 | | git pull |
100 | | }}} |
101 | | |
102 | | From this point on, it is assumed you have already done a {{{cd modular-boost/libs/mylib}}}. |
103 | | |
104 | | === Testing locally === |
105 | | |
106 | | Unless you are 100% sure of the state of your library's regression tests, it is a good idea to run the regression tests before making any changes to the library: |
107 | | |
108 | | {{{ |
109 | | pushd test |
110 | | b2 |
111 | | popd |
112 | | }}} |
113 | | |
114 | | === Checking status === |
115 | | |
116 | | Before making changes, it is a good idea to check status. Here is what that looks like on Windows; the |
117 | | message you get may vary somewhat: |
118 | | |
119 | | {{{ |
120 | | >git status |
121 | | # On branch develop |
122 | | nothing to commit, working directory clean |
123 | | }}} |
124 | | |
125 | | === Fix a simple bug directly on {{{develop}}} === |
126 | | |
127 | | For simple bugs, particularly in projects with a single maintainer, it is common practice to fix bugs directly in the {{{develop}}} branch. Creating a test case with your favorite editor, testing the test case, fixing the bug, testing the fix, and then iterating if necessary is no different than with any programming environment. |
128 | | |
129 | | Once the fix is complete, you then commit the fix locally and push from your local repo up to your public boostorg repo on GitHub. These same commands would be used for any Git project, modular or not, so hopefully you are already somewhat familiar with them: |
130 | | |
131 | | {{{ |
132 | | cd modular-boost/libs/mylib |
133 | | git commit -a -m "my bug fix" |
134 | | git push |
135 | | }}} |
136 | | |
137 | | There are some significant disadvantages to this simple approach: |
138 | | * The fix is now made to {{{develop}}} but you must remember to merge it to a release branch or directly to {{{master}}}. It is very easy to forget to do that merge, particularly if this is a mature library you are not working with very often. |
139 | | * Users who need the bug fix right away are forced to jump through hoops to retrieve the fix from {{{develop}}}. |
140 | | |
141 | | Putting out a point release solves both of those problems. Read on... |
142 | | |
143 | | === Fix a bug using a hot-fix branch === |
144 | | |
145 | | Fixing a bug directly on the {{{develop}}} branch is fine, if that's the library's policy, but if the bug is messy, multiple maintainers are involved, interruptions are expected, or other complexities are present, then it is better practice to work on the bug in a separate branch. And doing that on a hot-fix branch solves the problems mentioned at the end of the prior section. |
146 | | |
147 | | The operational distinction between a bug-fix branch and a hot-fix branch is that a bug-fix branch is branched from {{{develop}}} and then at completion merged back to {{{develop}}}, while a hot-fix branch is branched from {{{master}}} and then at completion is merged to both {{{master}}} and {{{develop}}}. With either approach, the branch is deleted after it has been merged. |
148 | | |
149 | | {{{ |
150 | | git checkout master |
151 | | git checkout -b hotfix/complex-boo-boo |
152 | | }}} |
153 | | |
154 | | This creates the branch {{{hotfix/complex-boo-boo}}}, and switches to it. Incidentally, {{{hotfix/}}} is part of the name, not a directory specifier. The new branch is based on branch {{{master}}} because the working copy was on branch {{{master}}} at the time of the branch. |
155 | | |
156 | | Since the bug is complex, it may take some time to fix and may go through several cycles of fixes, tests, and commits. |
157 | | |
158 | | Once the bug is fixed and a final commit is done, then it is time to merge the {{{hotfix/complex-boo-boo}}} branch into {{{master}}} and {{{develop}}}: |
159 | | |
160 | | {{{ |
161 | | git checkout master |
162 | | git merge hotfix/complex-boo-boo |
163 | | git push |
164 | | git checkout develop |
165 | | git merge hotfix/complex-boo-boo |
166 | | git push |
167 | | git branch -d hotfix/complex-boo-boo |
168 | | }}} |
169 | | |
170 | | === Start work on a new feature === |
171 | | |
172 | | Developers are encouraged to create a (possibly private) branch to work on new features, even simple ones, since development of new features on the {{{develop}}} branch might leave it unstable for longer that expected. Using the Git Flow convention, the branch will be named {{{feature/add-checksum-option}}}. |
173 | | |
174 | | {{{ |
175 | | git checkout develop |
176 | | git checkout -b feature/add-checksum-option |
177 | | }}} |
178 | | |
179 | | When you create the branch, or perhaps later, you may decide the branch should be public (i.e. be present in the library's public boostorg repo) so that you can share the branch with others or just to back it up. If so, set that up by running: |
180 | | |
181 | | {{{ |
182 | | git push --set-upstream origin feature/add-checksum-option |
183 | | }}} |
184 | | |
185 | | Whether or not {{{--set-upstream origin bugfix/complex-boo-boo}}} is actually needed depends on the {{{branch.autosetupmerge}}} configuration variable that isn't discussed here. If you don't supply {{{--set-upstream origin bugfix/complex-boo-boo}}} on your first {{{push}}} and it turns out to be needed, you will get an error message explaining that. |
186 | | |
187 | | |
188 | | The usual cycle of coding, testing, commits, and pushes (if public) then begins. If other work needs to be done, a {{{stash}}} or {{{commit}}} may be done to save work-in-progress, and the working copy switched to another branch for awhile. If significant fixes or other enhancements have been made to {{{develop}}} over time, it may be useful to merge {{{develop}}} into the feature branch so that the eventual merge back to {{{develop}}} has less conflicts. Here is how the merge from {{{develop}}} to {{{feature/add-checksum-option}}} is done: |
189 | | |
190 | | {{{ |
191 | | git checkout feature/add-checksum-option |
192 | | git merge develop |
193 | | }}} |
194 | | |
195 | | == First post-svn conversion merge to {{{master}}} == |
196 | | |
197 | | When you are ready to merge the {{{develop}}} branch to {{{master}}} (or better yet a release branch that's branched off {{{master}}}), there's a bit of housekeeping to be done the first time after the conversion from svn so that future merges proceed smoothly. We're going to create a merge point between |
198 | | the develop and master branches so that Git knows the last point the two branches were in synch. Once we've done that Git will perform a merge by replaying the commits on develop on top of master, starting from the last known merge: in other words Git will perform the tricky stuff of figuring out what to merge for us. |
199 | | |
200 | | * Navigate to the history for your library on !GitHub, starting with branch master. For example the Config library [https://github.com/boostorg/config/commits/master can be seen here]. |
201 | | * Look down through the commit history and make a note of the last merge in svn land. In our example, it was on October 25th 2013. |
202 | | * Use the dropdown box to change the history to point to the develop branch. [https://github.com/boostorg/config/commits/develop Config library can be seen here]. |
203 | | * Find the last commit '''before the date noted above'''. Click on the commit message for that commit to go to the actual diff for that change, [https://github.com/boostorg/config/commit/67f6b934f161dc5da2039004986a14d9217afae4 in our example here]. The SHA1 for that commit is shown below and to the right of the commit message, in this case it's {{{67f6b934f161dc5da2039004986a14d9217afae4}}}. Copy that SHA1 to your clipboard. |
204 | | |
205 | | Create a merge to that specific commit. Begin by changing your library to the master branch: |
206 | | |
207 | | {{{ |
208 | | git checkout master |
209 | | }}} |
210 | | |
211 | | Now create a merge to the specific commit above; since we don't really want to actually change the master branch we'll use the {{{-s ours}}} option to avoid any conflicts: |
212 | | |
213 | | {{{ |
214 | | git merge --no-ff --no-commit -s ours 67f6b934f161dc5da2039004986a14d9217afae4 |
215 | | }}} |
216 | | |
217 | | You can now use {{{git status}}} and {{{git diff}}} to check for modifications, in this case there are none. Now make the commit and push to !GitHub: |
218 | | |
219 | | {{{ |
220 | | git commit -am "Create first merge point for Git" |
221 | | git push |
222 | | }}} |
223 | | |
224 | | Then navigate to your libraries history again, and check that the merge shows up, [https://github.com/boostorg/config/commits/master our config example is here]. |
225 | | You're now ready for "routine" merges to proceed as per Git Flow (or whatever other strategy you wish to use). |
226 | | |
227 | | === Lightweight library release === |
228 | | |
229 | | Small, simple libraries and simple releases just merge {{{develop}}} into {{{master}}}, tag {{{master}}}, and declare victory. |
230 | | |
231 | | {{{ |
232 | | git checkout master |
233 | | git merge --no-ff develop |
234 | | git tag -a 1.56.1 |
235 | | }}} |
236 | | |
237 | | === Heavyweight library release === |
238 | | |
239 | | Large, complex libraries, particularly those with multiple developers working in parallel, need to use a release procedure that scales up better than the lightweight procedure. The Git Flow approach is recommended. Find out more at [wiki:StartModWorkflow Modular Boost Library Workflow Overview] and be sure to study the examples given in [http://nvie.com/posts/a-successful-git-branching-model/ Vincent Driessen's original blog posting]. |