diff --git a/book/07-git-tools/sections/revision-selection.asc b/book/07-git-tools/sections/revision-selection.asc index f77a7f4..4f5feb7 100644 --- a/book/07-git-tools/sections/revision-selection.asc +++ b/book/07-git-tools/sections/revision-selection.asc @@ -1,19 +1,19 @@ [[r_revision_selection]] -=== Revision Selection +=== 選擇修訂版本 -Git allows you to specify specific commits or a range of commits in several ways. -They aren’t necessarily obvious but are helpful to know. +你能夠以 Git 使用多種方式來指定一個提交(commit)或某些範圍內的提交。 +雖然不見得必要,但了解是有益處的。 -==== Single Revisions +==== 單一修訂版本 -You can obviously refer to a commit by the SHA-1 hash that it’s given, but there are more human-friendly ways to refer to commits as well. -This section outlines the various ways you can refer to a single commit. +很顯然地,你可以利用每個提交的 SHA-1 雜湊值來指定它,不過還有更多方便、直覺的方法一樣可以辦到。 +這個章節將會介紹各種取得單一提交的方法。 -==== Short SHA-1 +==== 簡短的 SHA-1 -Git is smart enough to figure out what commit you meant to type if you provide the first few characters, as long as your partial SHA-1 is at least four characters long and unambiguous – that is, only one object in the current repository begins with that partial SHA-1. +如果你輸入 SHA-1 的前幾個字元,Git 可以聰明地判斷這是哪一個提交,前提是提供的 SHA-1 片段至少 4 個字元,而且不會模稜兩可,也就是目前的版本庫中僅有一個提交是以此 SHA-1 片段作為開頭。 -For example, to see a specific commit, suppose you run a `git log` command and identify the commit where you added certain functionality: +例如,假設你要查看一個你增加某些功能的提交,你應該會先執行 `git log` 指令並找到這個提交: [source,console] ---- @@ -38,7 +38,7 @@ Date: Thu Dec 11 14:58:32 2008 -0800 added some blame and merge stuff ---- -In this case, choose `1c002dd...`. If you `git show` that commit, the following commands are equivalent (assuming the shorter versions are unambiguous): +在這個例子中,假設要檢視 `1c002dd...` 這個提交,下列 `git show` 的指令都能達到相同的功能(假設簡短版本是明確、不模稜兩可的): [source,console] ---- @@ -47,8 +47,8 @@ $ git show 1c002dd4b536e7479f $ git show 1c002d ---- -Git can figure out a short, unique abbreviation for your SHA-1 values. -If you pass `--abbrev-commit` to the `git log` command, the output will use shorter values but keep them unique; it defaults to using seven characters but makes them longer if necessary to keep the SHA-1 unambiguous: +Git 能夠為 SHA-1 值產生簡短且唯一的縮寫。 +如果你在 `git log` 後面加上參數 `--abbrev-commit`,就會輸出簡短但唯一的值。預設使用 7 個字元,但為了確保 SHA-1 的縮寫不會模稜兩可,也許會使用更多的字元: [source,console] ---- @@ -58,39 +58,39 @@ ca82a6d changed the version number a11bef0 first commit ---- -Generally, eight to ten characters are more than enough to be unique within a project. +一般來說,一個專案只要用 8 到 10 個字元就足夠了。 -As an example, the Linux kernel, which is a pretty large project with over 450k commits and 3.6 million objects, has no two objects whose SHA-1s overlap more than the first 11 characters. +舉例來說,Linux 核心專案有超過 450,000 個提交和 3.6 百萬個物件,是個相當大的專案,也只需要不超過 11 個字元 SHA-1 值就能達到不重複。 [NOTE] -.A SHORT NOTE ABOUT SHA-1 +.SHA-1 縮寫的說明 ==== -A lot of people become concerned at some point that they will, by random happenstance, have two objects in their repository that hash to the same SHA-1 value. -What then? +有許多人會擔心版本庫裡有兩個物件出現相同的 SHA-1 值, +然後呢? -If you do happen to commit an object that hashes to the same SHA-1 value as a previous object in your repository, Git will see the previous object already in your Git database and assume it was already written. -If you try to check out that object again at some point, you’ll always get the data of the first object. +如果你真的提交了一個物件雜湊出與先前物件相同的 SHA-1 值,Git 會發現先前物件已經在你的 Git 資料庫中,並假設它已經被寫入。 +之後如果你試圖再次檢出(checkout)這個物件,你只會取得先前已經寫入的第一個物件。 -However, you should be aware of how ridiculously unlikely this scenario is. -The SHA-1 digest is 20 bytes or 160 bits. -The number of randomly hashed objects needed to ensure a 50% probability of a single collision is about 2^80^ -(the formula for determining collision probability is `p = (n(n-1)/2) * (1/2^160))`. 2^80^ -is 1.2 x 10^24^ -or 1 million billion billion. -That’s 1,200 times the number of grains of sand on the earth. +然而,你應該知道這個情形發生的機率十分低。 +SHA-1 值占用 20 位元組的大小,也就是 160 位元。 +能夠確保每 2^80^ 個物件雜湊,會產生衝突的機率有 50% , +(計算衝突機率的算式 `p = (n(n-1)/2) * (1/2^160)` ), +是 1.2 x 10^24^, +也就是 1 百萬 乘上 10 億 再乘上 10 億, +這是地球上沙子總數的 1,200 倍。 -Here’s an example to give you an idea of what it would take to get a SHA-1 collision. -If all 6.5 billion humans on Earth were programming, and every second, each one was producing code that was the equivalent of the entire Linux kernel history (3.6 million Git objects) and pushing it into one enormous Git repository, it would take roughly 2 years until that repository contained enough objects to have a 50% probability of a single SHA-1 object collision. -A higher probability exists that every member of your programming team will be attacked and killed by wolves in unrelated incidents on the same night. +我們舉個例讓你了解 SHA-1 衝突什麼情況下會發生, +如果地球上 65 億人在進行開發,且每秒每個人都產生相當於整個 Linux 核心歷史(360 萬個 Git 物件)的程式碼,並提交到同一個超巨大的 Git 版本庫,必須持續大約 2 年的時間直到版本庫內有足夠的物件,才能滿足 50% 的機率產生一次的物件 SHA-1 衝突的條件。 +這個機率比起開發團隊內每一個成員在同一個晚上遭遇不同的意外,還要來得低。 ==== [[r_branch_references]] -==== Branch References +==== 分支參照 -The most straightforward way to specify a commit requires that it has a branch reference pointed at it. -Then, you can use a branch name in any Git command that expects a commit object or SHA-1 value. -For instance, if you want to show the last commit object on a branch, the following commands are equivalent, assuming that the `topic1` branch points to `ca82a6d`: +引用一個特定提交最直接的方式是,有一個分支參照指向這個提交, +然後將 Git 指令中提交物件或 SHA-1 值的位置,替換成分支名稱。 +例如,如果你想要知道分支最後一個提交物件,假設分支 `topic1` 下面的指令都能達到同樣的功能: [source,console] ---- @@ -98,10 +98,10 @@ $ git show ca82a6dff817ec66f44342007202690a93763949 $ git show topic1 ---- -If you want to see which specific SHA-1 a branch points to, or if you want to see what any of these examples boils down to in terms of SHA-1s, you can use a Git plumbing tool called `rev-parse`. -You can see <> for more information about plumbing tools; basically, `rev-parse` exists for lower-level operations and isn’t designed to be used in day-to-day operations. -However, it can be helpful sometimes when you need to see what’s really going on. -Here you can run `rev-parse` on your branch. +如果你想要只到分支指向哪一個特定 SHA-1 ,或想知道任何一個範例相關的 SHA-1 內容,你可以使用稱為 `rev-parse` 的 Git 底層工具, +你可以到 <> 了解更多關於底層工具的訊息,基本上 `rev-parse` 只會在底層操作時用到,並非用於日常使用。 +然而,當你有時想知道目前的狀況,會變得很有用, +就可以在你的分支執行 `rev-parse` 。 [source,console] ---- @@ -110,11 +110,11 @@ ca82a6dff817ec66f44342007202690a93763949 ---- [[r_git_reflog]] -==== RefLog Shortnames +==== 參照日誌(RefLog)簡稱 -One of the things Git does in the background while you’re working away is keep a ``reflog'' – a log of where your HEAD and branch references have been for the last few months. +Git 會在你工作時,默默地在背後保存一份 「參照日誌」,紀錄最近幾個月 HEAD 和分支參照的狀況, -You can see your reflog by using `git reflog`: +你可以執行 `git reflog` 查看參照日誌: [source,console] ---- @@ -128,27 +128,27 @@ d921970 HEAD@{1}: merge phedders/rdocs: Merge made by recursive. 7e05da5 HEAD@{6}: rebase -i (pick): updating HEAD ---- -Every time your branch tip is updated for any reason, Git stores that information for you in this temporary history. -And you can specify older commits with this data, as well. -If you want to see the fifth prior value of the HEAD of your repository, you can use the `@{n}` reference that you see in the reflog output: +不論如何,每次你的分支更新時,Git 會將資訊存到暫存歷史裡, +你可以利用這些資訊獲取之前的提交。 +假如你想要查看版本庫 HEAD 前五次的紀錄,你可以用 `@{n}` 作為參照日誌輸出的參照: [source,console] ---- $ git show HEAD@{5} ---- -You can also use this syntax to see where a branch was some specific amount of time ago. -For instance, to see where your `master` branch was yesterday, you can type +這個語法也可以用來查一個分支特定時間以前的參照紀錄, +例如,若要查看 `master` 昨天的紀錄,可以輸入 [source,console] ---- $ git show master@{yesterday} ---- -That shows you where the branch tip was yesterday. -This technique only works for data that’s still in your reflog, so you can’t use it to look for commits older than a few months. +就可以看到分支頂端昨天指向哪裡。 +這個技巧只在資料還保存在參照日誌中才有用,所以無法查看幾個月之前的提交。 -To see reflog information formatted like the `git log` output, you can run `git log -g`: +若想要參照日誌按照 `git log` 的輸出格式顯示,你可以執行 `git log -g`: [source,console] ---- @@ -170,15 +170,15 @@ Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit 'phedders/rdocs' ---- -It’s important to note that the reflog information is strictly local – it’s a log of what you’ve done in your repository. -The references won’t be the same on someone else’s copy of the repository; and right after you initially clone a repository, you'll have an empty reflog, as no activity has occurred yet in your repository. -Running `git show HEAD@{2.months.ago}` will work only if you cloned the project at least two months ago – if you cloned it five minutes ago, you’ll get no results. +有件重要的事要注意,參照日誌只限於本地端,紀錄你在版本庫裡做的所有事情, +即使是相同的版本庫,這份參照資料也不會相同,當你初次克隆(clone)一個版本庫時,將會產生一個空白的參照日誌,代表你的版本庫還沒有任何動作發生。 +如果你在至少兩個月前克隆版本庫,執行 `git show HEAD@{2.months.ago}` 才有用,若在五分鐘前才剛克隆,你將不會得到任何結果。 -==== Ancestry References +==== 祖代參照 -The other main way to specify a commit is via its ancestry. -If you place a `^` at the end of a reference, Git resolves it to mean the parent of that commit. -Suppose you look at the history of your project: +祖代參照是另一個指向一個提交的主要方法。 +如果你在參照後面加上 `^` 這個符號,Git 將解析為這個提交的親提交(the parent of that commit), +假設你的專案歷程如下: [source,console] ---- @@ -193,7 +193,7 @@ $ git log --pretty=format:'%h %s' --graph * 9b29157 add open3_detach to gemspec file list ---- -Then, you can see the previous commit by specifying `HEAD^`, which means ``the parent of HEAD'': +你可以透過指定 `HEAD^` ,也就是「HEAD 的親提交」來查看之前的提交: [source,console] ---- @@ -206,9 +206,9 @@ Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit 'phedders/rdocs' ---- -You can also specify a number after the `^` – for example, `d921970^2` means ``the second parent of d921970.'' -This syntax is only useful for merge commits, which have more than one parent. -The first parent is the branch you were on when you merged, and the second is the commit on the branch that you merged in: +你也可以在 `^` 指定一個數字,舉例來說,`d921970^2` 代表「d921970的第二個親提交」。 +這個語法只適用於有多個親代的合併提交, +第一個親代提交是合併時你所在分支,第二個親代提交則是你所合併的分支: [source,console] ---- @@ -227,11 +227,11 @@ Date: Wed Dec 10 22:22:03 2008 +0000 Some rdoc changes ---- -The other main ancestry specification is the `~`. -This also refers to the first parent, so `HEAD~` and `HEAD^` are equivalent. -The difference becomes apparent when you specify a number. -`HEAD~2` means ``the first parent of the first parent,'' or ``the grandparent'' – it traverses the first parents the number of times you specify. -For example, in the history listed earlier, `HEAD~3` would be +還有一種主要的祖代參照方式是使用 `~`。 +`HEAD~` 和 `HEAD^` 都是指向第一個親代, +若在符號後面指定數字時就不太一樣, +`HEAD~2` 意思是「親代的親代」或是「祖代」,它將依據指定次數遍歷所有的第一親代, +例如,依照先前提到的專案歷程,`HEAD~3` 會是: [source,console] ---- @@ -243,7 +243,7 @@ Date: Fri Nov 7 13:47:59 2008 -0500 ignore *.gem ---- -This can also be written `HEAD^^^`, which again is the first parent of the first parent of the first parent: +這也可以寫成 `HEAD^^^`,也就是第一親代的第一親代的第一親代: [source,console] ---- @@ -255,27 +255,27 @@ Date: Fri Nov 7 13:47:59 2008 -0500 ignore *.gem ---- -You can also combine these syntaxes – you can get the second parent of the previous reference (assuming it was a merge commit) by using `HEAD~3^2`, and so on. +兩種語法也能合併使用,像是 `HEAD~3^2` 可以查看之前提交的第二親代(假設提交是一個合併提交),以此類推。 [[r_commit_ranges]] -==== Commit Ranges +==== 提交區間 -Now that you can specify individual commits, let’s see how to specify ranges of commits. -This is particularly useful for managing your branches – if you have a lot of branches, you can use range specifications to answer questions such as, ``What work is on this branch that I haven’t yet merged into my main branch?'' +你已經知道怎麼指向單一的提交,現在來看看如何指向一連串的提交。 +對於管理你的分支特別好用,如果你有很多分支,你可以用來列出提交區間來解決像是「有哪些提交你尚未合併到主要的分支」的問題。 -===== Double Dot +===== 雙點 -The most common range specification is the double-dot syntax. -This basically asks Git to resolve a range of commits that are reachable from one commit but aren’t reachable from another. -For example, say you have a commit history that looks like <>. +雙點語法是區間指向最常用的語法, +這個語法常用來讓 Git 解析出哪些提交在這個分支有,但其他分支沒有。 +例如,假設你有個提交歷程如 <> 所示。 [[rdouble_dot]] .Example history for range selection. image::images/double-dot.png[Example history for range selection.] -You want to see what is in your experiment branch that hasn’t yet been merged into your master branch. -You can ask Git to show you a log of just those commits with `master..experiment` – that means ``all commits reachable by experiment that aren’t reachable by master.'' -For the sake of brevity and clarity in these examples, I’ll use the letters of the commit objects from the diagram in place of the actual log output in the order that they would display: +你想要知道分支 experiment 有哪些提交尚未合併到分支 master, +你可以在 `git log` 後面加上參數 `master..experiment`,也就是「所有分支 experiment 有但是分支 master 沒有的提交」。 +為了讓舉例可以更簡潔易懂,這邊使用圖片中英文字母代替實際日誌輸出,顯示的順序如下: [source,console] ---- @@ -284,8 +284,8 @@ D C ---- -If, on the other hand, you want to see the opposite – all commits in `master` that aren’t in `experiment` – you can reverse the branch names. -`experiment..master` shows you everything in `master` not reachable from `experiment`: +反之,你可以對調分支的名稱的位置,查看分支 `master` 參照到的提交但分支 `experiment` 沒有的。 +`experiment..master` 可以查看哪些提交是分支 `master` 有但分支 `experiment` 沒有的: [source,console] ---- @@ -294,24 +294,24 @@ F E ---- -This is useful if you want to keep the `experiment` branch up to date and preview what you’re about to merge in. -Another very frequent use of this syntax is to see what you’re about to push to a remote: +保持最新進度和預覽那些提交需要被合併變得很方便, +這個語法另一個常見的情況是查看你即將推送到遠端的提交: [source,console] ---- $ git log origin/master..HEAD ---- -This command shows you any commits in your current branch that aren’t in the `master` branch on your `origin` remote. -If you run a `git push` and your current branch is tracking `origin/master`, the commits listed by `git log origin/master..HEAD` are the commits that will be transferred to the server. -You can also leave off one side of the syntax to have Git assume HEAD. -For example, you can get the same results as in the previous example by typing `git log origin/master..` – Git substitutes HEAD if one side is missing. +這個指令會顯示你分支上任何不在遠端 `origin` 的提交, +當你執行 `git push` 且目前的分支正在追蹤(track) `origin/master`,指令 `git log origin/master..HEAD` 所列出來的提交將會傳到伺服器。 +當你在雙點語法一邊留空,Git 會預設為 HEAD。 +例如,輸入 `git log origin/master..`,將會得到和先前的例子相同的結果,因為 Git 將留空的位置視為 HEAD。 -===== Multiple Points +===== 多點 -The double-dot syntax is useful as a shorthand; but perhaps you want to specify more than two branches to indicate your revision, such as seeing what commits are in any of several branches that aren’t in the branch you’re currently on. -Git allows you to do this by using either the `^` character or `--not` before any reference from which you don’t want to see reachable commits. -Thus these three commands are equivalent: +雙點語法快速方便,但或許有時候你想要兩個以上的分支來指出你的修訂,像是查看哪些提交在多個分支上都有,但不在你現在的分支上, +Git 允許你在任何參照前加上字元 `^` 或是 `--not` 來指定你不想要提交被包含的分支。 +因此下列三個指令有相同的功能: [source,console] ---- @@ -320,8 +320,8 @@ $ git log ^refA refB $ git log refB --not refA ---- -This is nice because with this syntax you can specify more than two references in your query, which you cannot do with the double-dot syntax. -For instance, if you want to see all commits that are reachable from `refA` or `refB` but not from `refC`, you can type one of these: +這個語法最棒的就是你可以指定超過兩個參照,而雙點語法無法辦到。 +例如,你想要查看分支 `refA` 或 `refB` 所參照的提交,但分支 `refC` 沒有的,你可以選擇下列其中一個指令執行: [source,console] ---- @@ -329,14 +329,14 @@ $ git log refA refB ^refC $ git log refA refB --not refC ---- -This makes for a very powerful revision query system that should help you figure out what is in your branches. +這使得修訂查詢系統非常強大,對了解你的分支內有什麼很有幫助。 [[r_triple_dot]] -===== Triple Dot +===== 三點 -The last major range-selection syntax is the triple-dot syntax, which specifies all the commits that are reachable by either of two references but not by both of them. -Look back at the example commit history in <>. -If you want to see what is in `master` or `experiment` but not any common references, you can run +最後一個重要的區間選擇語法是三個點,這個語法可以列出只有一方參照、非雙方共同參照的提交, +請看一下之前 <> 提交歷史的範例, +如果你想要查看 `master` 或者 `experiment` 這兩個分支僅有一方擁有的提交,你可以執行: [source,console] ---- @@ -347,10 +347,10 @@ D C ---- -Again, this gives you normal `log` output but shows you only the commit information for those four commits, appearing in the traditional commit date ordering. +如同一般 `log` 輸出,這邊會顯示這四個提交的資訊,並按慣例照提交時間的順序顯示。 -A common switch to use with the `log` command in this case is `--left-right`, which shows you which side of the range each commit is in. -This helps make the data more useful: +這個情況下,通常會在 `log` 指令加上參數 `--left-right`,顯示每一個提交是屬於哪一邊的分支, +讓輸出的資料更加清楚: [source,console] ---- @@ -361,4 +361,4 @@ $ git log --left-right master...experiment > C ---- -With these tools, you can much more easily let Git know what commit or commits you want to inspect. +有了這些工具,你能更簡單地讓 Git 知道你想要檢查哪一個或哪一些提交。 diff --git a/status.json b/status.json index 3b336d2..e072a68 100644 --- a/status.json +++ b/status.json @@ -60,7 +60,7 @@ }, "07-git-tools": { "1-git-tools.asc": 100, - "sections/advanced-merging.asc": 0, + "sections/advanced-merging.asc": 100, "sections/bundling.asc": 0, "sections/credentials.asc": 0, "sections/debugging.asc": 0,