diff --git a/src/levels/remote/fakeTeamwork.js b/src/levels/remote/fakeTeamwork.js index ddf1981c..3cd58f32 100644 --- a/src/levels/remote/fakeTeamwork.js +++ b/src/levels/remote/fakeTeamwork.js @@ -5,12 +5,14 @@ exports.level = { "name": { "en_US": "Faking Teamwork", "de_DE": "Teamarbeit simulieren", - "zh_CN": "Faking Teamwork" + "zh_CN": "Faking Teamwork", + "zh_TW": "模擬團隊合作" }, "hint": { "en_US": "remember you can specify the number of commits to fake", "de_DE": "Nicht vergessen, du kannst angeben wieviele Commits simuliert werden sollen.", - "zh_CN": "记住为fake指定数量" + "zh_CN": "记住为fake指定数量", + "zh_TW": "你要記得指定要送多少個 commit 出去" }, "startDialog": { "en_US": { @@ -67,6 +69,60 @@ exports.level = { } ] }, + "zh_TW": { + "childViews": [ + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "## 模擬合作", + "", + "接下來的課程有一個很難的事情,我們需要讓你學會如何 pull reomote 上的更新 。", + "", + "這就表示我們必須要 \"假裝\" remote 被你其中一個同事/ 朋友/ 合作的人在某個特定的 branch 上面送了一些特定的 commit。", + "", + "為了要做到這件事情,我們要介紹一個自己設計的指令 `git fakeTeamwork`! 從字面上就可以很容易地看出來它在幹嘛,讓我們來看一個範例‧‧‧" + ] + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "`fakeTeamwork` 的預設行為是在送一個 commit 給 master 分支" + ], + "afterMarkdowns": [ + "我就說吧 -- remote 已經藉由一個新的 commit 而更新了,而且因為我們還沒有用 `git fetch`,所以表示我們還沒有下載該更新。." + ], + "command": "git fakeTeamwork", + "beforeCommand": "git clone" + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "你可以在命令的後面指定你要送幾個 commit 或是要送給哪個 branch。" + ], + "afterMarkdowns": [ + "我們利用一個 command 將三個 commit 送給在 remote 上面的 `foo` branch。" + ], + "command": "git fakeTeamwork foo 3", + "beforeCommand": "git branch foo; git clone" + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "接下來的關卡會很困難,所以我們在這個關卡中會問你更多問題。", + "", + "現在先把 remote 下載下來 (利用 `git clone`),假裝送幾個 commit 給 remote 做更新,然後 pull 這些 commit 下來 。這就好像是幾個教學中的命令的總結!" + ] + } + } + ] + }, "zh_CN":{ "childViews": [ { diff --git a/src/levels/remote/fetchRebase.js b/src/levels/remote/fetchRebase.js index cabf9947..40ba02f1 100644 --- a/src/levels/remote/fetchRebase.js +++ b/src/levels/remote/fetchRebase.js @@ -5,11 +5,13 @@ exports.level = { "name": { "en_US": "Diverged History", "zh_CN": "分散的历史", + "zh_TW": "Diverged History", "de_DE": "Abweichende History" }, "hint": { "en_US": "check out the ordering from the goal visualization", "zh_CN": "检出可视化目标中的顺序", + "zh_TW": "確認目標中的順序", "de_DE": "Beachte die Reihenfolge in der Zieldarstellung" }, "startDialog": { @@ -156,6 +158,149 @@ exports.level = { } ] }, + "zh_TW": { + "childViews": [ + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "## Diverged Work", + "", + "到目前為止我們已經知道如何 `pull` 其他人所送的 commit,而且也知道如何 `push` 我們自己的 commit,感覺很簡單,但是為什麼有人看起來很困惑?", + "", + "當 repo 的歷史紀錄是 *diverge (branch 走向不同)* 的狀態時就會很棘手,在討論這個之前,讓我們先來看一個例子...", + "" + ] + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "想像一下你在星期一的時候 clone 了一個 repo,並且開始在設計一個功能,在星期五的時候你準備好要發佈你的新功能,但是非常不幸地,你的同事已經寫了一連串的程式碼並且已經將 commit 發佈到 remote,所以現在*你的*進度是在一個比較*舊*的版本的後面 (如果與 remote 比較的話啦!)。", + "", + "在這種情況底下,使用 `git push` 會有問題,如果你使用 `git push`,那麼 git 應該要把 remote 退回到星期一的狀態? 它應該要把你所寫好的程式碼一起更新進去,同時不會影響你的同事寫好的程式碼? 或者是他應該要因為版本比較舊而完全忽略你的程式碼?", + "", + "因為在這種情況下會很麻煩 (當 git 歷史紀錄被 diverge 了 ), 所以 git 不會允許你 `push` 你的 commit。在你上傳你的 commit 之前,它實際上會先強迫你先跟 remote 同步。" + ] + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "講太多了啦! 讓我們實際看一下這個情況。" + ], + "afterMarkdowns": [ + "看到了沒? 因為指令失敗了,所以沒有任何事情發生。 `git push` 失敗的原因是因為你最近的 commit `C3` 是在 `C1` 的後面,但是 remote 那邊是 `C2` 在 `C1` 的後面,所以 git 才會拒絕你的 push。" + ], + "command": "git push", + "beforeCommand": "git clone; git fakeTeamwork; git commit" + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "你要如何解決這種情況? 很簡單,你只需要把 `C3` 接在 remote 最新的版本 `C2` 的後面就可以了。", + "", + "有一些方法可以做到,但是最直接的方式是用 rebase,我們來做看看。" + ] + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "在我們 push 之前,先來做 rebase‧‧‧" + ], + "afterMarkdowns": [ + "看吧! 我們利用 `git fetch` 下載了 remote 上面的 commit,並且 rebase 我們的 commit 使得我們的 commit 可以接在 remote 上面最新的版本的後面,接著透過 `git push` 就可以上傳更新了。" + ], + "command": "git fetch; git rebase o/master; git push", + "beforeCommand": "git clone; git fakeTeamwork; git commit" + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "在 remote 已經率先更新之後,還有沒有其它方法可以上傳我們的 commit? 當然有阿! 我們這次利用 `merge` 來做看看!", + "", + "雖然 `git merge` 並不會去移動你的 commit (反而會產生一個 merge commit),這是一個告訴 git 你已經下載了 remote 上面的 commit 並且在 local repo 中已經做完 merge,而因為 remote branch 上的最新的 commit 現在已經是 merge commit 的一個 *ancestor*,這就表示你的 commit 已經包含了在 remote branch 上的所有 commit。", + "", + "讓我們來看一下這種情況..." + ] + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "現在假設我們不是用 rebase,而是用 merge..." + ], + "afterMarkdowns": [ + "看吧!我們藉由 `git fetch` 把 remote 上的 commit 下載下來,並且 *merged* 該 commit 到我們目前的 branch (這樣就表示我們產生的 merge commit 有包含了 remote 上的 commit),接著再透過 `git push` 上傳到 remote。" + ], + "command": "git fetch; git merge o/master; git push", + "beforeCommand": "git clone; git fakeTeamwork; git commit" + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "太棒了! 有沒有其它可以不用打這麼多指令的方法?", + "", + "當然有阿!你已經知道 `git pull` 就是表示一個 fetch 跟一個 merge。 有一個指令非常方便,那就是 `git pull --rebase`,它表示的是一個 fetch 以及一個 rebase。", + "", + "我們來看如何使用這個簡化後的指令。" + ] + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "首先 `--rebase`..." + ], + "afterMarkdowns": [ + "跟之前一樣!只是少了很多指令。" + ], + "command": "git pull --rebase; git push", + "beforeCommand": "git clone; git fakeTeamwork; git commit" + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "現在用一般的 `pull`" + ], + "afterMarkdowns": [ + "又來了,剛好跟之前的一樣!" + ], + "command": "git pull; git push", + "beforeCommand": "git clone; git fakeTeamwork; git commit" + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "fetch,rebase/merge,以及 push 的流程是幾乎一樣的。在之後的教學中我們會看到比這些流程更複雜的版本。但是現在讓我們先牛刀小試一下。", + "", + "為了要完成這一關,請按照下面的步驟:", + "", + "* clone 你的 repo", + "* 假裝送一個 commit 給 remote", + "* 送一個 commit 給 local repo", + "* 透過 *rebase* 送自己的 commit" + ] + } + } + ] + }, "zh_CN":{ "childViews": [ { diff --git a/src/levels/remote/mergeManyFeatures.js b/src/levels/remote/mergeManyFeatures.js index 42684e32..aab7e5c4 100644 --- a/src/levels/remote/mergeManyFeatures.js +++ b/src/levels/remote/mergeManyFeatures.js @@ -5,11 +5,13 @@ exports.level = { "name": { "en_US": "Merging with remotes", "zh_CN": "Merging with remotes", + "zh_TW": "Merging with remotes", "de_DE": "Änderungen vom Remote zusammenführen" }, "hint": { "en_US": "Pay attention to the goal tree!", "zh_CN": "注意目标树!", + "zh_TW": "注意最後要完成的目標!", "de_DE": "Beachte den Ziel-Baum!" }, "compareOnlyMaster": true, @@ -59,6 +61,51 @@ exports.level = { } ] }, + "zh_TW": { + "childViews": [ + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "## 為何不要 merge?", + "", + "為了要 push 新的 commit 給 remote,你只需要做的是先同步 remote 的更新,那就表示你可以使用 rebase *或者*是 merge remote branch (例如,`o/master`)。", + "", + "所以假如你已經學會使用其中一個方式了,那為什麼我們到目前為止還在強調 `rebase`? 為什麼當提到 remote 的時候,反而 `merge` 比較沒有受到關注?", + "" + ] + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "在程式發展的社群中,關於 `merge` 以及 `rebase` 的孰優孰劣有很多的爭論。這裡我們會提到關於 `rebase` 的優點及缺點:", + "", + "優點:", + "", + "* `rebase` 使得你的 commit tree 看起來更為簡潔,因為任何的 commit 都在一條直線上面。", + "", + "缺點:", + "", + "* `rebase` 修改了 commit tree 的歷史紀錄。", + "", + "舉例來說,我們可以 rebase commit `C1`,將 `C1` 接在*過去的* `C3` 上面,那麼就可以表現出 `C1` 是出現在 `C3` 的後面。", + "", + "有一些程式設計師喜歡保留歷史紀錄,因此他們會比較喜歡 `merge`; 其他人 (例如我自己) 比較喜歡一個簡潔的 commit tree,因此他們比較喜歡 `rebase`。這些都是擇你所愛。:D" + ] + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "在這個關卡中,我們面對的是之前關卡的題目,但是我們採用的是 `merge`,這可能會讓你感覺到有點困難,但是確實有講到重點。" + ] + } + } + ] + }, "de_DE": { "childViews": [ { diff --git a/src/levels/remote/push.js b/src/levels/remote/push.js index 662addf6..e7fb1082 100644 --- a/src/levels/remote/push.js +++ b/src/levels/remote/push.js @@ -5,11 +5,13 @@ exports.level = { "name": { "en_US": "Git Pushin'", "zh_CN": "Git Pushin'", + "zh_TW": "Git Pushin'", "de_DE": "Git Push" }, "hint": { "en_US": "Remember you have to clone before you can push!", "zh_CN": "push之前你需要先克隆.", + "zh_TW": "push 之前你需要先 clone.", "de_DE": "Denk dran, dass du einen Clone brauchst bevor du Pushen kannst!" }, "startDialog": { @@ -54,6 +56,47 @@ exports.level = { } ] }, + "zh_TW": { + "childViews": [ + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "## Git Push", + "", + "ok,現在我已經從 remote 那邊下載了一些更新,並且把它們 merge 到我的 local repository 上面的工作,這聽起來實在太讚了‧‧‧,但是我要如何分享_我_所做的更新給其它人呢?", + "", + "喔,其實上傳並且分享更新跟下載更新並且 merge 是相反的兩件事情,那什麼是 `git pull` 的相反呢? 那就是 `git push`!", + "", + "`git push` 負責上傳_你的_ commit 到特定 remote 上面並且做出相對應的更新,只要做完了 `git push`,所有你的朋友都可以從 remote 上面下載你所送出去的 commit。", + "", + "你可以把 `git push` 當作是一個 \"發佈\" 你的工作進度的指令,還有一些我們即將要講到的細節,但是先讓我們從一些簡單的步驟開始。" + ] + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "這裡我們有了一些 remote 所沒有的 commit。讓我們來上傳它們吧!" + ], + "afterMarkdowns": [ + "我說的沒錯吧! remote 收到了 commit `C2`,同時在 remote 上的 `master` branch 也一起更新並且指向 `C2`,同時我們*自己的* `o/master` 也一併更新了!" + ], + "command": "git push", + "beforeCommand": "git clone; git commit" + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "要完成這個關卡,只要上傳兩個新的 commit 給 remote,不要太得意忘形喔!因為這些課程將會愈來愈難!" + ] + } + } + ] + }, "zh_CN":{ "childViews": [ { diff --git a/src/levels/remote/pushArgs.js b/src/levels/remote/pushArgs.js index 80f27722..7578d6f4 100644 --- a/src/levels/remote/pushArgs.js +++ b/src/levels/remote/pushArgs.js @@ -8,10 +8,12 @@ exports.level = { "name": { "en_US": "Git push arguments", "zh_CN": "Git push 参数", + "zh_TW": "Git push 的參數", "de_DE": "Optionen für Git Push" }, "hint": { "en_US": "You can always look at the last slide of the dialog with \"objective\"", + "zh_TW": "你可以利用 \"objective\" 來閱讀對話視窗的最後一頁", "de_DE": "Du kannst dir die Zielsetzung des Levels immer wieder mit \"objective\" anzeigen lassen" }, "startDialog": { @@ -87,6 +89,78 @@ exports.level = { } ] }, + "zh_TW": { + "childViews": [ + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "## Push 的參數", + "", + "太好了! 現在你已經明白了 remote tracking,我們可以開始聊 git push,fetch,以及 pull 的一些有趣的地方,我們一次會講解一個 command,但是它們之間的概念是很類似的。", + "", + "首先我們來看一下 `git push`,你已經在 remote tracking 的課程中學習到 git 是根據目前 checkout 的 branch 所 track 的 remote branch 來做 push,這是在沒有任何的參數的情況下的預設動作,但是 git push 允許我們可以加上一些參數:", + "", + "`git push `", + "", + "" + ] + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "`` 這個參數表示什麼? 我們等一下會提到細節,但是先來看一個例子,執行以下的指令:", + "", + "`git push origin master`", + "", + "將這段解釋成中文:", + "", + "*先到我的 repo 中的 \"master\" branch,抓下所有的 commit,然後到叫作 \"origin\" 的 remote 的 \"master\" branch,檢查 remote 的 commit 有沒有跟我的 repo 一致,如果沒有,就更新。*", + "", + "將 `master` 當作 \"place\" 這個參數,我們告訴 git 這些 commit 是*從哪裡來的*,而且它們要*往哪裡去*。對於要同步兩個 repo, \"place\" 或者是 \"location\" 是非常重要的。", + "", + "要記住喔,因為我們告訴 git 它所要知道的 (有兩個參數),因此它才不會管你現在所 checkout 的 branch!" + ] + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "讓我們來看一個有加上參數的例子,在這個例子中,要特別注意到我們所 checkout 的位置。" + ], + "afterMarkdowns": [ + "我說的沒錯吧! 因為我們加上了參數,所以在 remote 上的 `master` branch 更新了" + ], + "command": "git checkout C0; git push origin master", + "beforeCommand": "git clone; git commit" + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "假如我們沒有特別指令參數會發生什麼事情?" + ], + "afterMarkdowns": [ + "指令會失敗 (就像你看到的),因為 `HEAD` 並沒有指向一個有 track remote branch 的 branch 上面阿。" + ], + "command": "git checkout C0; git push", + "beforeCommand": "git clone; git commit" + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "好的,在這個關卡中,我們要更新在 remote 上的 `foo` 以及 `master` branch,比較遺憾的是 `git checkout` 在這個關卡中是不被允許的喔!" + ] + } + } + ] + }, "zh_CN":{ "childViews": [ { diff --git a/src/levels/remote/pushArgs2.js b/src/levels/remote/pushArgs2.js index 179803dc..448680ba 100644 --- a/src/levels/remote/pushArgs2.js +++ b/src/levels/remote/pushArgs2.js @@ -5,11 +5,13 @@ exports.level = { "name": { "en_US": "Git push arguments -- Expanded!", "zh_CN": "Git push 参数2!", + "zh_TW": "Git push 的參數 -- 延伸討論!", "de_DE": "Optionen fü Git Push -- noch mehr!" }, "hint": { "en_US": "Remember you can admit defeat and type in \"show solution\" :P", "zh_CN": "如果你失败了, 可以通过 \"show solution\" 找到解决方案 :P", + "zh_TW": "如果你失敗了,可以利用 \"show solution\" 來找到解答 :P", "de_DE": "Vergiss nicht dass du aufgeben kannst, indem du \"show solution\" eingibst :P" }, "startDialog": { @@ -83,6 +85,76 @@ exports.level = { } ] }, + "zh_TW": { + "childViews": [ + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "## `` 這個參數的細節", + "", + "回想一下,我們在之前的課程中提到,當我們用 `git push` 並且把 `master` 當作 place 這個參數的時候,我們就相當於告訴 git 我們的所要更新的 commit 要*從哪裡來*(來源) 並且要 *往哪裡去*(目的地)。", + "", + "你可能會很好奇,當我們的來源以及目的地是不同的時候,應該怎麼做? 當你想要 push `foo` branch 上面的 commit 到 remote 的 `bar` branch 的時候,應該怎麼做?", + "", + "很遺憾地,對於 git 來說這是不可能的...開玩笑的啦! 當然是有可能的 :)... git 有非常非常大的彈性 (太超過了啦)。", + "", + "讓我們來看看下一頁..." + ] + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "為了要指定 `` 的來源以及目的地,只要利用一個分號將這兩個連在一起:", + "", + "`git push origin :`", + "", + "這通常被稱為一個 colon (分號) refspec. refspec 只是一個表示 location (位置) 的花俏的名稱,這個位置可以被 git 識別 ( 例如 `foo` branch 或是 `HEAD~1`)。", + "", + "一旦你單獨指定了來源以及目的地,你可以看到花俏且準確的指令。讓我來來看一個例子!" + ] + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "記住, `來源` 表示任意可以被 git 辨識的 location:" + ], + "afterMarkdowns": [ + "哇!這實在是一個很花俏的指令但是確很合理 -- git 把 `foo^` 解讀成一個 location,並且 push 該 location 的 commit 到目前 remote 的 master branch。 " + ], + "command": "git push origin foo^:master", + "beforeCommand": "git clone; go -b foo; git commit; git commit" + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "如果你想要 push 的目的地 (destination) 不存在怎麼辦? 沒有問題! 只要給一個 branch 的名稱, git 就會在 remote 幫你建立。" + ], + "afterMarkdowns": [ + "太讚了,實在非常地簡單 :D" + ], + "command": "git push origin master:newBranch", + "beforeCommand": "git clone; git commit" + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "對於這個關卡,想辦法達到這個視覺化的目標,而且要記得格式:", + "", + "`<來源>:<目的地>`" + ] + } + } + ] + }, "zh_CN":{ "childViews": [ { diff --git a/src/levels/remote/pushManyFeatures.js b/src/levels/remote/pushManyFeatures.js index 5d23d867..a094d9aa 100644 --- a/src/levels/remote/pushManyFeatures.js +++ b/src/levels/remote/pushManyFeatures.js @@ -5,11 +5,13 @@ exports.level = { "hint": { "en_US": "Remember you can always use the undo or reset commands", "zh_CN": "你随时都可以使用undo/reset命令.", + "zh_TW": "你隨時都可以使用 undo 或 reset 指令。", "de_DE": "Denk dran, du kannst immer undo oder reset benutzen, um deine Befehle zurück zu nehmen." }, "name": { "en_US": "Push Master!", "zh_CN": "Push Master!", + "zh_TW": "Push Master!", "de_DE": "Push Master!" }, "compareOnlyMasterHashAgnostic": true, @@ -67,6 +69,59 @@ exports.level = { } ] }, + "zh_TW": { + "childViews": [ + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "## Merging feature branches", + "", + "現在你已經很熟悉 fetch,pull,以及 push,讓我們來針對一個新的問題來應用這些技巧。", + "", + "在一個大型的專案裡面,程式設計師經常會在 feature branch (有別於 master branch) 上面做開發,之後等開發完之後,在一次 merge 回去。這跟之前的課程是很類似的 (其它的 branch 被 push 到 remote) 上,但是現在我們還要再多介紹一個步驟。", + "", + "某些程式設計師只針對 `master` branch 進行 push 或者是 pull。這樣子的話 `master` 一直都保持跟 remote (`o/master`) 同步。", + "", + "所以針對這個問題我們結合了兩件事情:", + "", + "* 將 feature branch 結合 (merge) 到`master` branch,並且", + "* push remote 以及 pull remote" + ] + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "讓我們馬上來實際看一下如何更新 `master` 並且 push 到 remote。" + ], + "afterMarkdowns": [ + "我們在這裡執行兩個指令:", + "", + "* rebase 我們的 branch 到 remote 的新的 commit 上面,並且", + "* 發佈到 remote 上面" + ], + "command": "git pull --rebase; git push", + "beforeCommand": "git clone; git commit; git fakeTeamwork" + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "這個關卡很複雜,這裡有一些提示:", + "", + "* 總共有三個 feature branch,分別是 `side1`,`side2` 以及 `side3`", + "* 我們想要將這三個 branch 分別 push 到 remote。", + "* 但是 remote 已經被事先更新過了,所以我們必須要先同步那些更新。", + "", + ":O 很好! 祝你好運,完成這個關卡是一個很重要的步驟。" + ] + } + } + ] + }, "de_DE": { "childViews": [ { diff --git a/src/levels/remote/tracking.js b/src/levels/remote/tracking.js index dd40466b..0c082804 100644 --- a/src/levels/remote/tracking.js +++ b/src/levels/remote/tracking.js @@ -5,11 +5,13 @@ exports.level = { "name": { "en_US": "Remote Tracking", "zh_CN": "Remote Tracking", + "zh_TW": "Remote Tracking", "de_DE": "Remote Tracking" }, "hint": { "en_US": "Remember there are two ways to set remote tracking!", "zh_CN": "有两种设置无端跟踪的方法!", + "zh_TW": " 記住喔,有兩個方式可以去設定 remote tracking", "de_DE": "Nicht vergessen, es gibt zwei Arten Remote Tracking einzurichten!" }, "startDialog": { @@ -131,6 +133,124 @@ exports.level = { } ] }, + "zh_TW": { + "childViews": [ + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "### Remote-Tracking branches", + "", + "在之前的課程中,有一件事情看起來很\"神奇\",那就是 git 知道 `master` branch 是對應到 `o/master` branch。當然這些 branch 有類似的名稱,所以可以大概猜到, local 的 `master` branch 可以 connect 到 remote 的 `master branch`,但是我們是在兩種情況下可以確定有這個 connection:", + "", + "* 在使用 `pull` 的時候,下載 commit 到 `o/master`,並且 `merge` 這些 commit 到 `master` branch,這就表示這個 merge 的目標是決定於這個 connection。", + "* 在使用 `push` 的時候,在 `master` branch 上面的 commit 被 push 到 remote 上面的 `master` branch (它在 local 端被表示成 `o/master`),這就表示 push 的目標是決定於 `master` 以及 `o/master` 之間的 connection。", + "" + ] + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "## Remote tracking", + "", + "長話短說,我們可以用 branch 上面的 \"remote tracking\" 特性來表示介於 `master` 以及 `o/master` 的 connection,`master` branch 被設定用來追蹤 (track) `o/master`,這就表示對於 `master` branch 來說的話,有一個 merge 的目標以及 push 的目標。", + "", + "你可能會覺得很奇怪,當你沒有下任何指令去設定的時候,關於 `master` branch 的 connection 是如何被設定的。喔,其實當你 clone 一個 repo 的時候,其實就已經自動幫你做設定了。 ", + "", + "在做 clone 的時候,git 會針對每一個在 remote 上面的 branch 建立一個 branch (例如 `o/master`),之後它會建立一個 local branch 來追蹤目前在 remote 上面的 active branch,在大部份的情況下,幾乎都是設定 `master` branch。", + "", + "一旦 git 完成這個動作,你就只會有一個 local branch ,但是你可以看到所有在 remote 上面的不同的 branch,對於 local 和 remote 來說的話,這樣子是最好的!", + "", + "這也解釋了為什麼當你 clone 的時候可能會看到以下被輸出的指令:", + "", + " local branch \"master\" set to track remote branch \"o/master\"" + ] + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "### 我可以自己設定嗎?", + "", + "是的你可以! 你可以設定任何的 branch 來 track `o/master`, 假如你真的這麼做的話,那麼該 branch 的 push 及 merge 的目標就會跟 `master` 一樣。這就表示說你可以在 `totallyNotMaster` branch 上面執行 `git push`,並且 push 你的 commit 到 remote 的 `master` branch!", + "", + "有兩個方式可以設定,第一個就是藉由參考一個 remote branch 來 checkout 一個新的 branch。執行", + "", + "`git checkout -b totallyNotMaster o/master`", + "", + "建立一個新的 `totallyNotMaster` branch 並且它會 track `o/master`." + ] + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "說的好多,我們現在來看一個例子! 我們會 checkout 一個新的 `foo` branch,而且該 branch 會被用來 track remote 上的 `master` branch。" + ], + "afterMarkdowns": [ + "就像你看到的,當 `o/master` 更新的時候,`foo` branch 也跟著一起被更新,要注意 master 並沒有被更新!" + ], + "command": "git checkout -b foo o/master; git pull", + "beforeCommand": "git clone; git fakeTeamwork" + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "同樣適用於 `git push`" + ], + "afterMarkdowns": [ + "哇,即使我們的 branch 名稱完全一點關係都沒有,但我們還是 push 了 commit 到 remote 的 `master` branch 上面。" + ], + "command": "git checkout -b foo o/master; git commit; git push", + "beforeCommand": "git clone" + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "### 方法 #2", + "", + "另外一個設定 remote tracking 的方法是使用 `git branch -u` 這一個指令,執行", + "", + "`git branch -u o/master foo`", + "", + "你就會看到 `foo` branch 被設定成 track `o/master`,如果你現在已經 checkout 到 foo 這個 branch 上面了,你就可以省略掉它:", + "", + "`git branch -u o/master`", + "" + ] + } + }, + { + "type": "GitDemonstrationView", + "options": { + "beforeMarkdowns": [ + "我們來看這個快速設定 remote tracking 的方法..." + ], + "afterMarkdowns": [ + "跟之前一樣,就只是一個更加明確的指令,讚啦!" + ], + "command": "git branch -u o/master foo; git commit; git push", + "beforeCommand": "git clone; git checkout -b foo" + } + }, + { + "type": "ModalAlert", + "options": { + "markdowns": [ + "好! 在這個關卡中,我們要 push 我們的 commit 到 remote 上面的 `master` branch,但是我們*不* checkout 到 local 的 `master` branch。因為這是一個進階的課程,所以我會讓你明白其它的東西。:P" + ] + } + } + ] + }, "zh_CN":{ "childViews": [ {