Skip to content

Translate 07-git-tools replace (Originally #101) #233

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 25 additions & 25 deletions book/07-git-tools/sections/replace.asc
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[[_replace]]
=== Replace
=== 替换

Git's objects are unchangable, but it does provide an interesting way to pretend to replace objects in it's database with other objects.
Git 对象是不可改变的,但它提供一种有趣的方式来用其他对象假装替换数据库中的 Git 对象。

The `replace` command lets you specify an object in Git and say "every time you see this, pretend it's this other thing". This is most commonly useful for replacing one commit in your history with another one.
`replace` 命令可以让你在 Git 中指定一个对象并可以声称“每次你遇到这个 Git 对象时,假装它是其他的东西”。在你用一个不同的提交替换历史中的一个提交时,这会非常有用。

For example, let's say you have a huge code history and want to split your repository into one short history for new developers and one much longer and larger history for people interested in data mining. You can graft one history onto the other by `replace`ing the earliest commit in the new line with the latest commit on the older one. This is nice because it means that you don't actually have to rewrite every commit in the new history, as you would normally have to do to join them together (because the parentage effects the SHAs).
例如,你有一个大型的代码历史并想把自己的仓库分成一个短的历史和一个更大更长久的历史,短历史供新的开发者使用,后者给喜欢数据挖掘的人使用。 你可以通过用新仓库中最早的提交 `replace` 老仓库中最新的提交来连接历史,这种方式可以把一条历史移植到其他历史上。这意味着你不用在新历史中真正替换每一个提交(因为历史来源会影响 SHA 的值),你可以加入他们。

Let's try this out. Let's take an existing repository, split it into two repositories, one recent and one historical, and then we'll see how we can recombine them without modifying the recent repositories SHA values via `replace`.
让我们来试试吧!首先获取一个已经存在的仓库,并将其分成两个仓库,一个是最近的仓库,一个是历史版本的仓库。然后我们将看到如何在不更改仓库 SHA 值的情况下通过 `replace` 命令来合并他们。

We'll use a simple repository with five simple commits:
我们将使用一个拥有 5 个提交的简单仓库:

[source,console]
----
Expand All @@ -21,11 +21,11 @@ c6e1e95 fourth commit
c1822cf first commit
----

We want to break this up into two lines of history. One line goes from commit one to commit four - that will be the historical one. The second line will just be commits four and five - that will be the recent history.
我们想将其分成拆分成两条历史。第一个到第四个提交的作为第一个历史版本,第四、第五个提交的作为最近的第二个历史版本。

image::images/replace1.png[]

Well, creating the historical history is easy, we can just put a branch in the history and then push that branch to the master branch of a new remote repository.
创建历史版本的历史很容易,我们可以只将一个历史中的分支推送到一个新的远程仓库的 master 分支。

[source,console]
----
Expand All @@ -40,7 +40,7 @@ c1822cf first commit

image::images/replace2.png[]

Now we can push the new `history` branch to the `master` branch of our new repository:
现在我们可以把这个新的 `history` 分支推送到我们新仓库的 `master` 分支:

[source,console]
----
Expand All @@ -56,7 +56,7 @@ To git@github.com:schacon/project-history.git
* [new branch] history -> master
----

OK, so our history is published. Now the harder part is truncating our recent history down so it's smaller. We need an overlap so we can replace a commit in one with an equivalent commit in the other, so we're going to truncate this to just commits four and five (so commit four overlaps).
这样一来,我们的历史版本就发布了。稍难的部分则是删减我们最近的历史来让它变得更小。我们需要一个重叠以便于用一个相等的提交来替换另一个提交,这样一来,我们将截断到第四、五个提交。

[source,console]
----
Expand All @@ -68,9 +68,9 @@ c6e1e95 (history) fourth commit
c1822cf first commit
----

It's useful in this case to create a base commit that has instructions on how to expand the history, so other developers know what to do if they hit the first commit in the truncated history and need more. So, what we're going to do is create an initial commit object as our base point with instructions, then rebase the remaining commits (four and five) on top of it.
在这种情况下,创建一个能够指导扩展历史的基础提交是很有用的。这样一来,如果其他的开发者想要修改第一次提交或者其他操作时就知道要做些什么。 因此,接下来我们要做的是用命令创建一个最初的提交对象,然后将剩下的提交(第四、第五个提交)变基到它的上面。

To do that, we need to choose a point to split at, which for us is the third commit, which is `9c68fdc` in SHA-speak. So, our base commit will be based off of that tree. We can create our base commit using the `commit-tree` command, which just takes a tree and will give us a brand new, parentless commit object SHA back.
为了这么做,我们需要选择一个点去拆分,对于我们而言是第三个提交(SHA 是 `9c68fdc`)。因此我们的提交将基于此提交树。我们可以使用 `commit-tree` 命令来创建基础提交,这样我们就有了一个树,并返回一个全新的、无父节点的 SHA 提交对象。

[source,console]
----
Expand All @@ -80,12 +80,12 @@ $ echo 'get history from blah blah blah' | git commit-tree 9c68fdc^{tree}

[NOTE]
=====
The `commit-tree` command is one of a set of commands that are commonly referred to as 'plumbing' commands. These are commands that are not generally meant to be used directly, but instead are used by **other** Git commands to do smaller jobs. On occasions when we're doing weirder things like this, they allow us to do really low-level things but are not meant for daily use. You can read more about plumbing commands in <<_plumbing_porcelain>>
`commit-tree` 命令属于底层指令。有许多指令并非直接使用,而是被 **其他的** Git 命令用来做更小一些的工作。有时当我们做一些像这样的奇怪事情时,它们允许我们做一些不适用于日常使用但真正底层的东西。更多关于底层命令的内容请参见 <<_plumbing_porcelain>>
=====

image::images/replace3.png[]

OK, so now that we have a base commit, we can rebase the rest of our history on top of that with `git rebase --onto`. The `--onto` argument will be the SHA we just got back from `commit-tree` and the rebase point will be the third commit (the parent of the first commit we want to keep, `9c68fdc`):
现在我们已经有一个基础提交了,我们可以通过 `git rebase --onto` 命令来将剩余的历史变基到基础提交之上。`--onto` 参数是刚才 `commit-tree` 命令返回的 SHA 值,变基点会成为第三个提交(我们想留下的第一个提交的父提交,`9c68fdc`):

[source,console]
----
Expand All @@ -97,10 +97,10 @@ Applying: fifth commit

image::images/replace4.png[]

OK, so now we've re-written our recent history on top of a throw away base commit that now has instructions in it on how to reconstitute the entire history if we wanted to. We can push that new history to a new project and now when people clone that repository, they will only see the most recent two commits and then a base commit with instructions.
我们已经用基础提交重写了最近的历史,基础提交包括如何重新组成整个历史的说明。我们可以将新历史推送到新项目中,当其他人克隆这个仓库时,他们仅能看到最近两次提交以及一个包含上述说明的基础提交。

Let's now switch roles to someone cloning the project for the first time who wants the entire history.
To get the history data after cloning this truncated repository, one would have to add a second remote for the historical repository and fetch:
现在我们将以想获得整个历史的人的身份来初次克隆这个项目。
在克隆这个截断后的仓库后为了得到历史数据,需要添加第二个远程的历史版本库并对其做获取操作:

[source,console]
----
Expand All @@ -118,7 +118,7 @@ From https://github.com/schacon/project-history
* [new branch] master -> project-history/master
----

Now the collaborator would have their recent commits in the `master` branch and the historical commits in the `project-history/master` branch.
现在,协作者在 `master` 分支中拥有他们最近的提交并且在 `project-history/master` 分支中拥有过去的提交。

[source,console]
----
Expand All @@ -134,14 +134,14 @@ c6e1e95 fourth commit
c1822cf first commit
----

To combine them, you can simply call `git replace` with the commit you want to replace and then the commit you want to replace it with. So we want to replace the "fourth" commit in the master branch with the "fourth" commit in the `project-history/master` branch:
为了合并它们,你可以使用 `git replace` 命令加上你想替换的提交信息来进行替换。这样一来,我们就可以将 master 分支中的第四个提交替换为 `project-history/master` 分支中的“第四个”提交。

[source,console]
----
$ git replace 81a708d c6e1e95
----

Now, if you look at the history of the `master` branch, it appears to look like this:
现在,查看 `master` 分支中的历史信息,显示如下:

[source,console]
----
Expand All @@ -153,11 +153,11 @@ e146b5f fifth commit
c1822cf first commit
----

Cool, right? Without having to change all the SHAs upstream, we were able to replace one commit in our history with an entirely different commit and all the normal tools (`bisect`, `blame`, etc) will work how we would expect them to.
很酷,是不是?不用改变上游的 SHA 我们就能用一个提交来替换历史中的所有不同的提交,并且所有的工具(`bisect``blame` 等)也都奏效。

image::images/replace5.png[]

Interestingly, it still shows `81a708d` as the SHA, even though it's actually using the `c6e1e95` commit data that we replaced it with. Even if you run a command like `cat-file`, it will show you the replaced data:
有趣的是,即使是使用了 `c6e1e95` 提交数据来进行替换,它的 SHA 仍显示为 `81a708d`。即使你运行了 `cat-file` 命令,它仍会显示你替换的数据:

[source,console]
----
Expand All @@ -170,9 +170,9 @@ committer Scott Chacon <schacon@gmail.com> 1268712581 -0700
fourth commit
----

Remember that the actual parent of `81a708d` was our placeholder commit (`622e88e`), not `9c68fdce` as it states here.
请记住,`81a708d` 真正的父提交是 `622e882` 占位提交,而非呈现的 `9c68fdce` 提交。

Another interesting thing is that this data is kept in our references:
另一个有趣的事情是数据将会以以下引用显示:

[source,console]
----
Expand All @@ -184,4 +184,4 @@ e146b5f14e79d4935160c0e83fb9ebe526b8da0d commit refs/remotes/origin/master
c6e1e95051d41771a649f3145423f8809d1a74d4 commit refs/replace/81a708dd0e167a3f691541c7a6463343bc457040
----

This means that it's easy to share our replacement with others, because we can push this to our server and other people can easily download it. This is not that helpful in the history grafting scenario we've gone over here (since everyone would be downloading both histories anyhow, so why separate them?) but it can be useful in other circumstances.
这意味着我们可以轻而易举的和其他人分享替换,因为我们可以将替换推送到服务器中并且其他人可以轻松地下载。也许在历史移植情况下不是很有用(既然每个人都乐意下载最新版本和历史版本,为何还要拆分他们呢?),但在其他情况下仍然很有用。
2 changes: 1 addition & 1 deletion status.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"sections/debugging.asc": 100,
"sections/interactive-staging.asc": 0,
"sections/notes.asc": 0,
"sections/replace.asc": 0,
"sections/replace.asc": 100,
"sections/rerere.asc": 0,
"sections/reset.asc": 0,
"sections/revision-selection.asc": 100,
Expand Down