3

我正在写一本技术书籍。它有一个我在整本书中建立的示例项目。当然,以常规方式使用 git 是没有问题的。

但是当软件的新版本出现时:这可能意味着代码开头的某个地方有一个小改动……初始生成的代码有一个小改动。我如何在第二个变更集中进行更改并让它在整个示例中传播?

或者我可能决定在第二章更改一个变量名。这必须在以下所有章节的示例中传播。

可能有一个 git 技巧可以用来解决这个问题,所以我全神贯注于一个有用的提示。

4

3 回答 3

3

好的,由于您试图管理在 git 提交时引导用户完成的步骤,因此您基本上拥有二维历史记录。在一个维度上,当您为新版本的软件更新项目、修复示例中的错误等时,您拥有正常的 git 历史记录。在另一个维度上,您拥有引导读者完成的步骤。

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

您引导用户完成的每个修改都应该是一个分支。要更新示例,请检查该分支,制作并提交您的修改。然后,为了确保您在该示例中所做的任何更改都反映在后续步骤中,您应该按顺序检查每个后续示例的分支,并合并到您刚刚更新的分支中。重新定位将是一个错误,因为这会丢弃沿图书版本维度的历史关系,而只会保留您引导读者完成的步骤的历史。

假设您必须更新第 1 步,并且您需要在第 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

提交 B 是错误修复,提交 A 是对步骤 1 的更新。Xs 正在合并先前步骤的更新。

于 2012-11-08T20:24:15.527 回答
3

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.

于 2012-11-08T20:14:56.180 回答
1

要以这种方式修改历史,通用工具是git rebase -i. 有一个警告:你不能用它来重写第一个提交,因为你必须指定一个提交开始(不包括在内)。

运行;这将打开一个编辑器列出提交。在您需要修改的提交上将命令更改为“编辑”,然后保存并退出。git rebase -i startcommit

然后,Rebase 将“停止修改”您指定的提交;进行必要的代码更改,使用 应用它们git commit --amend,或在适当的情况下将它们作为新的附加提交提交。完成更改后,请执行git rebase --continue; 这将应用所有先前存在的“稍后”提交,并在您需要解决冲突时停止。

我强烈建议之后使用查看器查看历史记录,gitk以确保整个画面仍然是您想要的;您可能还想将最终版本与旧的最终版本git diff master@{1} master(或您使用的任何分支名称)进行比较。

于 2012-11-08T20:28:32.103 回答