I'm writing a technical book. It has an example project that I build up throughout the book. Using git in the regular way is no problem of course.
But when a new version of the software comes out: that could mean a small change somewhere right in the beginning of the code... A small change in the initial generated code. How do I make that change in, say, the second changeset and have it propagate throughout the examples?
Or I might decide to change a variable name in chapter two. That has to propagate in all the following chapters' examples.
There's probably a git trick I can use to pull this off, so I'm all ears for a useful tip.
It sounds like you're arranging the Git repository so that a "commit" corresponds to a "chapter" (or something similar). Assume that each revision is tagged with a tag name chapter-x for the following:
First, go back to the chapter you want to change:
git checkout chapter-2
Make the change to the code, and commit it, amending the original chapter-2 commit:
# edit file here
git add test.c
git commit --amend
Update the chapter-2 tag to point to the new, amended commit:
git tag chapter-2
Switch back to the end of your book:
git checkout master
and finally, rebase against the new chapter-2:
git rebase chapter-2
This will rewrite chapters 3 and beyond so that they are based off the change you made in chapter 2. Note that you may encounter a lot of conflicts doing this (especially if, in later chapters, you modify code involving whatever you changed in chapter 2). Git can help, but unfortunately it can't do all the work for you.
Okay, since you're trying to manage the steps you walk the user through as git commits you essentially have a two dimensional history. On one dimension you have the normal git history as you update your project for new versions of the software, fix bugs in the examples, etc. On a separate dimension you have the steps that you walk the reader through.
O-->O-->O-->O-->O Third edition
^ ^ ^ ^ ^
| | | | |
O-->O-->O-->O-->O Second edition
^ ^ ^ ^ ^
| | | | |
O-->O-->O-->O-->O First edition
^ ^ ^ ^ ^
| | | | |
| | | | Add Step 5
| | | Add Step 4
| | Add Step 3
| Add Step 2
Step 1
Each modification you walk the user through should be a branch. To update an example, check out that branch, make, and commit your modification. Then to ensure that whatever changes you made in that example are reflected in later steps, you should, in order, checkout the branch for each later example, and merge in the branch you just updated. Rebasing would be a mistake because that discards history relationships along the book edition dimension and only maintains the history of the steps you walk reader through.
Say you have to update step 1 and there's a bug fix you need to make in step 3
git checkout step_1
# update step_1
git commit -a -m "update initialization example for v9.0"
git checkout step_2
git merge step_1
git checkout step_3
# bug fix
git commit -a -m "fix bug reported by reader..."
git merge step_2
git checkout step_4
git merge step_3
git checkout step_5
git merge step_4
git tag fourth_edition
>X-->X-->X Fourth edition
/ ^ ^ ^
/ | | |
A-->X B | |
^ ^ ^ | |
| | | | |
O-->O-->O-->O-->O Third edition
^ ^ ^ ^ ^
| | | | |
O-->O-->O-->O-->O Second edition
^ ^ ^ ^ ^
| | | | |
O-->O-->O-->O-->O First edition
commit B is the bug fix and commit A is the update to step 1. Xs are merging in updates from previous steps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With