1. 程式人生 > >第七章 : Git 介紹 (下)[Learn Android Studio 漢化教程]

第七章 : Git 介紹 (下)[Learn Android Studio 漢化教程]

features 發布 double to do oda 日誌功能 測試 相關 rds

Learn Android Studio 漢化教程 Let’s reset even further to remove all traces of your work on the deprecated method calls. Choose VCS ? Git ? Reset Head. Then enter HEAD~2 in the pop-up dialog box, shown in Figure 7-28, and click Reset. Remember to click the revert changes button afterwards. This will become a habit each time you use Git Reset in Android Studio. Your history will then reflect that of Figure 7-22.
【翻譯】讓我們進一步重置,使用deprecated method calls清除你項目工作中的所有追蹤。選擇VCS ? Git ?Reset Head.進入彈出對話框中的HEAD~2 ,如圖7-28所示,然後點擊重置。接著,記得點擊重置更改按鈕,把這個養成習慣,日後每當你在Android Studio中使用Git重置時,記得點擊它。你的歷史會在圖7-22中反映出來。

REVERT VS. RESET

【翻譯】還原VS.重置

The difference between revert and reset is subtle but important. A revert adds a commit that inverts the changes from the last commit, whereas reset takes a commit away. A reset essentially backs your branch label up by a given number of commits. If you’ve accidentally committed something, you’ll often want to undo or delete a commit. It is reasonable to use reset in such cases, because it is the simplest option and does not add to your history. In some cases, however, you might want your history to reflect the work of unwinding a commit—for example, if you pull a feature from a project and want to document the removal of that feature to the user community. Another important use for revert comes with remote repositories, which we discuss later in this chapter. Because you can only add commits to remote repositories, the only way to remove or unwind a commit on a remote repository is to use a revert, which appends the inverted changes as a commit.
【翻譯】還原和重置之間的差別雖然很小,但很重要。盡管重置會撤銷上次提交中的更改,還原卻可以把它再添加回來。通過許多提交,還原可以備份你的分支標簽。如果你無意中作了一項提交,你經常需要撤銷或刪除它。在這樣的情況下使用重置是相當恰當的,因為它是最簡單的選項,而且不會被添加到項目歷史裏。然而在一些情況下,你可能想要你的項目歷史反映解除提交的工作。比如說,如果你從一個項目中pull一個功能並且想把這次功能清楚記錄到用戶社區上。還原的另一個功能是應用在遠程版本庫上,將在本章的後部分討論。因為你僅僅可以添加提交到遠程版本庫,所以在遠程版本庫上刪除或展開一項命令的唯一方式是使用還原功能,它能把inverted 更改添加為提交。

Merging

Merging is a means of combining work from two separate branches. Historically, merges have required extra effort because of conflicts between branches. Thanks to Git’s implementation of changes, merges have become less painful.
You’ll start by adding a new feature on the main branch for the extreme procrastinator. This new feature will set the default of all reminders to Important because we know you procrastinators will ignore anything other than the most important reminders. Click File ? VCS ? Git ? Branches to bring up a list of branches. Select the master branch and then select Checkout. Note that the underlying source has been changed, all of the changes to
support the new feature have been removed, and your project has been restored to its state before you began working on scheduled reminders. Create a new changelist entitled and set it to active. Remove the empty ScheduledReminders changelist when you are prompted to do so. Figures 7-30 and 7-31 demonstrate this flow.

【翻譯】合並

【翻譯】合並是一種把兩個不同分支上的工作聯系起來的方式。在以前,因為不同分支之間的沖突,合並需要承擔多余的工作,不便於使用。因為有Git更改的存在,合並現在容易多了。
你可以在master分支上為拖延者添加一個新功能。這個新功能會把所有的提醒事項設置為默認,因為我們知道拖延者會忽略一切東西,但他不會忽略最重要的提醒事項。點擊File ? VCS ? Git ?分支,查看分支列表。選擇master分支然後選擇檢驗按鈕。註意下面的源文件已經被更改了,並且所有的更改
都支持被清楚的新功能,在你開始設置scheduled reminders之前,你的項目已經被恢復到它的合適狀態上了。新建一個名為修改列表的列表並激活它。當你被提示刪除被清空的ScheduledReminders修改列表時,刪除它。圖7-30 和7-31 顯示了這個工作流。

Figure 7-30. New changelist dialog box
【翻譯】圖7-30 新的更改列表對話框

技術分享圖片

Figure 7-31. A confirmation dialog box appears when deleting the old changelist
【翻譯】圖7-31 當刪除舊的更改列表時出現的確認對話框
技術分享圖片

Look in the fireCustomDialog() method and find the line that retrieves the check box from the dialog box layout. Add a new line to call checkBox.setChecked(true), which will set the new default, as shown on line 200 in Figure 7-32.
【翻譯】查看fireCustomDialog()method,找到對話框設置圖中、可以檢索復選框的行。添加新的一行來調用checkBox.setChecked(true)文件 這個文件可以設置新的默認,如圖7-32中的200行所示。

Figure 7-32. Set the check box default to checked
【翻譯】圖7-32 把復選框設置為已被檢驗
技術分享圖片

Build and run the app to test the new feature and then commit using Ctrl+K | Cmd+K. Git will see the history documented in Figure 7-33, which represents your latest commit that follows your initial clone from the branch.
【翻譯】建立並運行這個應用程序來測試新功能,然後用Ctrl+K| Cmd+K提交。Git會查看如圖7-33所示的被記錄後的歷史,這項歷史紀錄代表了你最新的提交,它緊跟你在分支上的初始克隆之後。

Figure 7-33. Commit history after adding a feature to the master branch
【翻譯】圖7-33 在主分支上添加新功能後的提交歷史
技術分享圖片

Here you switched your HEAD to master and made a D commit. This latest commit follows a different historic path than the commits for the ScheduledReminders feature, as this commit is not on the same branch.
【翻譯】現在把你的HEAD切換到主分支,然後作提交D。較之於ScheduledReminders功能上的提交,這個最新提交有一個不同的歷史路徑,因為這個新提交是在另外一條分支上。
Note If you are following the history in Git log view, you will note there is another origin/master branch pointing to the A commit that we do not show.This is a remote branch that is discussed later.
【翻譯】註意如果你在Git日誌視圖中追蹤歷史,你會註意到一個沒有被顯示的、指向提交A的另一個源/主分支。我們將在後面探討探討這個遠程分支。

You have done some work on the master branch, and made a few commits to add a new feature on your ScheduledReminders branch, so now you will bring these changes together into the main line, or master branch, where others can see them. Click File ? VCS ? Git ? Branches again to bring up a list of branches. Select the ScheduledReminders branch and click Merge. All of the changes and history from that branch will be incorporated into your master branch. Build and run the app to test both features. Clicking New Reminder from the options menu will open a New Reminder dialog box with the Important check box selected, while clicking any reminder in the list gives the option to schedule the reminder for a certain time. Figure 7-34 illustrates how Git has managed your changes.
【翻譯】你已經在你的主分支上完成了一些工作,你也通過作一些提交,為你的ScheduledReminders分支上添加了一個新功能,所以現在你可以把這些更改整合到主線或主分支中以便他人查看。再次點擊File? VCS ? Git ?分支,生成一個分支列表。選擇ScheduledReminders分支,然後點擊合並。這樣ScheduledReminders分支上所有的歷史和更改都會被合並到你的主分支上。創建並運行這個應用程序開始測試歷史和更改兩項功能。點擊選項菜單中的New Reminder,選擇重要復選框,打開New Reminder對話框。點擊列表中的任何reminder以讓這個選項在某些時刻設置提醒事項。圖7-34 顯示了Git會如何處理你的更改。

Figure 7-34. Commit history after merging the ScheduledReminders feature
【翻譯】圖7-34 合並ScheduledReminders功能後的提交歷史
技術分享圖片

A new E commit was automatically performed that includes changes from both C and D (E’s parents). Also note that HEAD is pointing to the head of the master branch which includes the latest commit.
【翻譯】一個新的提交E被自動執行,它包含了C以及D的更改(E的父級)你還要註意HEAD是指向指向包含最新提交的主分支上的head。

Git Reset Changes History

【翻譯】Git重置更改歷史

What if you wanted to treat your important reminders feature as a branch? You never created a branch for this feature. Instead you developed right on top of the master branch. You could force your master branch to back up and point to your D commit so let’s do this now. Click File? VCS ? Git and click Reset Head. The To Commit field will be set to HEAD. Set it to HEAD~1 and click the Reset button as shown in Figure 7-35 to reset your master branch again, which is more like a label. Remember to revert the changes saved from the Git reset. It will then point to the prior commit. Git will now see the repository as outlined in the prior diagram in Figure 7-33.
【翻譯】如果你想要把你的重要提醒功能設置為一個分支,你該如何做?你從未替這個功能創建過分支。你不需要在主分支的右上方來進行開發你可以
讓你的主分支備份並指向你的提交D,現在就讓做這個吧。點擊File
? VCS ?Git並且點擊 reset Head設置To Commit字段到HEAD中。把這個字段設置到HEAD~1 上,然後點擊如圖7-35所示的重置按鈕再次重置你看起來更像是標簽的一個主分支。記得還原那些被保留在Git重置中的更改。然後它會指向之前的提交。Git會查看在圖7-33上的圖表上大致描繪出的版本庫。

Figure 7-35. Git reset dialog box

【翻譯】圖7-35 Git重置對話框
技術分享圖片

Since the last commit included the merged changes, the reset makes it such that the merge never happened and you are now sitting on top of the commit, which introduced the ImportantReminders feature. This leaves you free to change history and make it look as if this new feature was developed on a branch. Click File ? VCS ? Git and then click Branches to open the branches dialog box. Click New Branch. Give the branch the name ImportantReminders and click OK to create it. You now have the history depicted in Figure 7-36.
【翻譯】因為上一次提交包含了合並後的更改,重置會抹去該次合並痕跡,現在你擁有了所有介紹重要提醒事項功能的提交。這會讓你自由地更改歷史,並且讓更改歷史看起來似乎是在分支上開發的新功能。點擊File ? VCS ? Git,然後點擊分支來打開分支對話框。點擊新的分支為這個分支命名為 ImportantReminders,點擊確定來新建它。看圖7-36,它描繪了整個項目歷史。
技術分享圖片

Figure 7-36. Git history showing the new branch
【翻譯】圖7-36 顯示新分支的Git歷史
Both master and ImportantReminders branches are pointing to the same commit. Check out the master branch using the Branches dialog box which can be invoked by clicking the branches section along the right corner of the status bar or by selecting File ? VCS ? Git? Branches. Reset this branch one more time to point it to where you initially cloned the project from Bitbucket and then check out the ImportantReminders branch. The history is now reflecting two experimental feature branches still in development while the working copy (what you see in the IDE) reflects the project as it existed when you first cloned it. You can see this in Figure 7-37.
【翻譯】主分支和重要提醒事項分支都指向同樣的命令。用分支對話框來檢驗主分支,你可以通過點擊狀態欄右角的分支部分或選中 File ? VCS ? Git? Branches來調用該對話框。再一次重置這個分支,把它指向從Bitbucket上最初克隆的那個項目,然後檢驗重要提醒事項分支。盡管這個工作副本(在IDE中)反映的是當這個項目存在時你第一次克隆它的時間,。這個歷史現在反映的是兩項正在開發的實驗型功能分支。你可以在圖7-37中看到這些。

Figure 7-37. Git history after resetting master to the beginning
【翻譯】圖7-37 重置master到begining後的Git歷史
技術分享圖片

Now you want to further change history and reorder your feature commits so that they look like they were developed in series and no branches were used during development.
Before you do this, check out the master branch and merge it with the ImportantReminders
branch. The merge will result in a special Fast Forward operation: Git merely moves the master branch forward in history to the same commit shared by the ImportantReminders branch. This is different from the earlier merged branch example, because one branch is a descendant of the other. If you look close enough, you will notice that creating a commit that merges changes from the ImportantReminders branch onto the master would be identical
to the D commit already pointed to by this same branch. Consequently, Git optimizes the operation and just moves the master branch forward, which brings you back to the history similar to that illustrated in Figure 7-36. The difference is that you have master checked out instead of the ImportantReminders branch.
Now you’ll make your history more interesting. You will add an About dialog box to your app so your users know a little more about the developer. An About dialog box is also a good place to put attributions for technologies and artwork used. Yours will be relatively simple.
Delete the ImportantReminders changelist if you haven’t done so and work with a new changelist titled AboutScreen. Create a new resource XML file under app ? src ? main ? res ? layout named dialog_about.xml and fill it with the code in Listing 7-1.
【翻譯】現在你需要進一步更改記錄,重新排序功能提交,既讓它們看起來像是被連續開發的,又讓它們看起來似乎不使用分支來進行開發。在你做這個之前,檢查主分支並把它與重要提醒事項分支關聯。
關聯會產生一個特殊的Fast Forward操作:Git僅僅是把歷史上的主分支移動到與重要提醒事項分支共享的同一個提交上。這與之前的關聯分支例子不一樣,因為那裏的一個分支是另外一個分支的子分支。如果你觀察得足夠仔細,你會註意到創建一個從ImportantReminders分支到master分支的合並更改命令與指向master分支的提交D是一模一樣的。結果就是, Git優化運算,轉移分支,把你帶回與圖7-36所示的相似的歷史。不同點就是你需檢驗master分支而非ImportantReminders分支。
現在你可以讓你的歷史更加吸引人了。你需要添加一個About對話框到你的應用程序上,這樣你的用戶就可以對開發人員稍作了解。一個About對話框也是一個放置技術屬性與使用過的圖形的好位置。yours相對而言會簡單一點。
如果你還沒有刪除ImportantReminders更改列表,現在刪除它。然後開始使用名為 AboutScreen的新的更換列表。在app ? src ? main ? res ? layout named dialog_about.xml 下新建resource XML文件,用列表 7-1中的代碼填寫。

Listing 7-1. dialog_about.xml
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">

<TextView
android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="Reminders!"
android:id="@+id/textView2" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" />

<TextView
android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Version 1.0\nAll rights reserved\nDeveloped by yours truly!" android:id="@+id/textView3"
android:layout_marginTop="34dp" android:layout_below="@+id/imageView" android:layout_centerHorizontal="true" android:gravity="center" />

<ImageView
android:layout_width="wrap_content" android:layout_height="wrap_content"

android:id="@+id/imageView" android:layout_below="@+id/textView2" android:layout_centerHorizontal="true" android:src="@drawable/ic_launcher" />
</RelativeLayout>

This layout defines an About dialog box that contains a text view for the title, a text view for the body, and places your Reminders launch icon in between. You need a new menu item to trigger the dialog box. Open menu_reminders.xml and add the following XML snippet between the first and second item tags:
【翻譯】這個布局定義了一個包含名為文本視圖、正文為文本視圖的about對話框,現在把你的Reminders啟動圖標放在中間。你需要一個新的菜單選項來啟動這個對話框。打開menu_reminders.xml ,在第一和第二項標簽中添加下面的XML 片段:

<item android:id="@+id/action_about" android:title="About" android:orderInCategory="200" app:showAsAction="never" />

Change the orderInCategory for the Exit menu item from 200 to 300 so it can be ordered after the new About item.
Now open RemindersActivity.java and add a case for the new menu item that calls a new
fireAboutDialog method, as shown in Figure 7-38.
【翻譯】在退出菜單選項中把orderInCategory從200更改為300,這樣它就能被排在新建的About項之後。
現在打開 RemindersActivity.java ,為新建的稱為fireAboutDialog method的菜單選項添加一個事項,如圖 7-38所示。

Figure 7-38. Add an About screen
【翻譯】圖7-38 添加一個About界面

技術分享圖片

The fireAboutDialog() method builds a dialog box using your new layout and shows it. Build and run the new feature to test it. Finally, press Ctrl+K | Cmd+K and commit with the message Adds an About screen. The Git history now has one more commit after the important reminders feature that is now pointed to by a branch. Your latest E commit from Figure 7-39 includes the About dialog box feature.
【翻譯】fireAboutDialog()method可以通過新的布局創建了一個對話框並把它展示出來。創建並運行你的新功能來對它進行測試。最後,按住Ctrl+K | Cmd+K,用Adds an About screen字段進行提交。在重要提醒事項功能通過分支進行指向後,Git歷史現在會再有一次提交。圖7-39 中的最新的提交E,它包含了About對話框功能。

Figure 7-39. Git history after adding the About screen
【翻譯】圖7-39 添加About界面的Git歷史

技術分享圖片
Git Rebase
Rebasing is a means of making a branch based on another branch or series of commits. It is similar to a merge in that it combines changes between branches but it does so in a way that creates a commit history without multiple parents. It’s best to use the current history as an example. Click File ? VCS ? Git ? Rebase to open the Rebase Branch dialog box. Tell this dialog box that you want to rebase the master branch on to the ScheduledReminders branch by selecting it from the Onto drop-down menu, as shown in Figure 7-40. Keep the Interactive option selected so you can have more control on what gets combined.
【翻譯】Rebase是一種以另一個分支或者另一系列的提交為基礎而創建分支的方式。與合並類似,git rebase也把分支之間的更改合並起來。但是,它是以創建一個沒有多重父級的提交歷史的方式把它們聯系起來的。使用當前歷史作為示例是最恰當的。點擊File ? VCS ? Git ?Rebase,打開Rebase 分支對話框。命令你的對話框rebase 主分支到ScheduledReminders分支上,從Onto下拉菜單上選中它, 如圖7-40所示。一直選中交互選項,這樣你就可以在被關聯的選項中有更多的選擇。

Figure 7-40. The Git Rebase branch dialog box
【翻譯】圖7-40 Git Rebase分支對話框

技術分享圖片

This takes you into interactive rebase mode presenting the dialog box in Figure 7-41. Interactive rebasing is one of Git’s more powerful features. From here, you can remove and change individual commits in your commit history. The Rebasing Commits dialog box lists all of the commits that occur in the selected branch’s history, up to the first common ancestor of the branch you are basing “onto”. One of the first things to note are options under the Action column for each commit. The dialog box gives the option to pick, edit, skip, or squash. However, Android Studio defaults each commit to pick.
【翻譯】它會讓你進入如圖7-41所示的、演示對話框的交互rebase模式,交互rebase是git最強大的功能之一。在這兒,你可以在你的提交歷史中刪除並更改個人提交。Rebase提交對話框列出了發生在你選擇提交歷史上的所有提交,它甚至多到包含了正在base的分支上的第一個common ancestor。你首先應該註意到的就是在每一項提交的Action欄下方的選項。對話框可以讓選項進行挑選、編輯、跳過或者粉碎等操作。不過, Android Studio把每一次提交默認為挑選。

Figure 7-41. The Git Rebase commits dialog box

【翻譯】圖7-41 Git Rebase提交對話框

技術分享圖片

Let’ say you no longer want the ImportantReminders feature from this branch but you are still interested in your About screen. Chose the Skip action to remove this commit from the list, and none of those changes will be present when you finish your rebase and combine the branches. Click the Start Rebasing option to complete the operation. Your Git history will now look like Figure 7-42.
【翻譯】讓我猜猜,你現在可能不需要這個分支上的ImportantReminders功能了,但是你仍然對About界面感興趣。選擇Skip操作清除列表上的提交,當你完成對分支的rebase和關聯後,這些更改都不會被顯示。點擊開始Rebase選項,完成操作。你的Git歷史會看起來像圖7-42中所示的一樣。

Figure 7-42. After rebasing and skipping the ImportantReminders branch
【翻譯】圖7-42 在rebase和跳過重要提醒事項分支之後

技術分享圖片

Detached Head

Let’s pretend that you had another developer working on an Alarm feature when you initially cloned the project. Let’s further say that you want to eventually merge in this work. To simulate this, you need to move back in history to the A commit and start the new feature. Until this point, you have been working and committing against a specific branch. This has been either a custom-named branch or the master branch that was created upon the initial import.
We will now demonstrate an alternate way of working in Git, which is known as Detached HEAD mode. If you check out a particular commit rather than a branch, the HEAD is detached from whichever branch you are working under and exposed. First you need
to check out the parent commit to the ImportantReminders branch. To do this, open the Branches dialog box and click Checkout Tag or Revision, as shown in Figure 7-43.

【翻譯】Detacheded Head

【翻譯】讓我們假設當你最初克隆這個項目時候,你是和另一位開發人員共通過開發alarm功能的。進一步說,你最終需要對這項任務進行合並merge合並。為了模擬這一步,你需要返回到項目歷史中的提交A,並開始這項新功能。直到現在為止,你一直都在一個專門的分支上工作或提交。它要麽是常規命名的分支,要麽是在最初的import中被創建的主分支。
現在我們向你演示在Git上工作的另一種方法,它被稱為Detached HEAD模式如果你檢驗的不是一個分支,而是一項特殊的提交,HEAD會脫離你正在操作的任意一項提交,並且把這個顯示出來。首先你需要檢查ImportantReminders分支上的父級提交。為了完成這一步,打開分支對話框、點擊Checkout標記或Revision, 如圖7-43所示。

Figure 7-43. Checking out the change prior to the last change in the ImportantReminders branch
【翻譯】圖7-43 檢驗ImportantReminders分支上的上一次更改之前的更改

技術分享圖片

技術分享圖片

Enter ImportantReminders~1 in the Checkout prompt. You will now be in detached mode, and your HEAD branch as well as your project state will reflect the last commit made when you initially cloned the project, as shown in Figure 7-44.
【翻譯】進入檢驗提示窗口的ImportantReminders~1 現在你處於detached模式中,你的HEAD分支以及項目狀態會反映你最初克隆這個項目時作的最後一次提交,如圖7-44所示。

Figure 7-44. git_diagram8
【翻譯】圖7-44 git圖8

技術分享圖片

Note that Git now exposes a new HEAD, which is detached from any branch that was created as part of your development. The HEAD had formally followed whichever branch you had checked out. As you made commits, the checked-out branch would move along with the HEAD to the latest commit. The ImportantReminders~1 text you entered was a relative reference to where you wanted your checkout to start. You can give a relative reference to most operations that expect a branch or commit hash. Relative references use one of the following two formats:
【翻譯】註意Git現在會顯示一個新的HEAD,它與任何分支都是分開的,被創建作為你程序開發中的一部分。HEAD會正式地跟蹤你之前檢驗過的任意一個分支。當你作出提交時,檢查分支會與head一起轉移到最新的提交上。你鍵入的ImportantReminders~1 text文本是你開始進行檢驗的區域內的相對參照。對於大部分需要分支或提交哈希代碼的操作,你都可以運用相對參照。相對參照選用下面兩種格式之一:

BranchOrCommitHash^ BranchOrCommitHash~NumberOfStepsBack

The single-caret form takes a single step back in history from the branch or commit specified to the left, while the tilde form takes a number of steps back in history that is equal to the number given to the right of the tilde.
【翻譯】single-caret形式從分支上僅需一步就可以從分支中進入歷史或專門向左欄提交,然而tilde形式需花與向右欄進行提交的相同的步驟才能進入歷史。

Relative References

Relative references are Git expressions that are used to refer to a specific point in Git history.
They use a starting point, or point of reference, and a target that is given as the number of steps from the point of reference. While the reference is frequently given as HEAD, it can also be either the name of a branch or the hash code (or abbreviated hash code) of a specific commit. You can use relative references for tasks such as moving a branch anywhere in your Git history, selecting a particular commit, or moving your HEAD to a
specific point in history. A relative reference can be given as a parameter anywhere a branch name or commit hash can be given. While we’ve seen a couple of examples of using them in the IDE, they are best used with Git on the command line.

Create a new branch to begin your next feature and call it SetAlarm. Create a changelist to go with the new branch and delete any old empty changelists. Add a new class in the com.apress.gerber.reminders package called RemindersAlarmReceiver and fill it with the following code:

【翻譯】相對參照

【翻譯】相對參照是一種Git表達方式,被用於指代git歷史中的專門時刻。
相對參照使用來自參照點上的幾個步驟來進行工作,如一個開始點、參照點或目標點。盡管參照經常被稱為HEAD,它也可以作為一個特殊提交上的分支名或哈希代碼(或哈希代碼縮寫)。你可以使用相對參照來完成任務,比如說你可以在git歷史上把分支移動到任何地方,選中一個特殊的提交或把你的head移動到歷史上的特殊點。
s相對參照可以在任何命名分支名或提交哈希代碼的區域內作參數使用。盡管在IDE中使用它們比較常見,在命令行中用Git使用它們其實才是最合適的。
創建一個新的分支來開始你的下一個功能,把它稱作 SetAlarm.新建一個更改列表來與新建的分支匹配,刪除空的舊列表。在被稱作RemindersAlarmReceiver的數據包 com.apress.gerber.reminders 中添加一個新的class,並且在它裏面填入下列代碼:

public class ReminderAlarmReceiver extends BroadcastReceiver{ public static final String REMINDER_TEXT = "REMINDER TEXT";

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onReceive(Context context, Intent intent) {
String reminderText = intent.getStringExtra(REMINDER_TEXT);
Intent intentAction = new Intent(context, RemindersActivity.class); PendingIntent pi = PendingIntent.getActivity(context, 0, intentAction, 0); Notification notification = new Notification.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setTicker("Reminder!")
.setWhen(new Date().getTime())
.setContentText(reminderText)
.setContentIntent(pi)
.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, notification);
}

}

Here we have a BroadcastReceiver that expects REMINDER_TEXT given as an intent extra. It uses the text and creates an action intent, which it uses to build a notification to post in the notification tray. Next add the following entry in AndroidManifest.xml after the activity tag, just before the closing application tag, to define the BroadcastReceiver:
【翻譯】現在我們就擁有了一個需要REMINDER_TEXT作為附加內容的BroadcastReceiver REMINDER_TEXT作為附加內容。它使用這個文本並且新建了一個操作內容來創建一個通知表中顯示的通知。接下來,在activity標簽後,在AndroidManifest.xml中添加下列項目。 在關閉應用標簽前,定義BroadcastReceiver為:

<receiver android:name="com.apress.gerber.reminders.ReminderAlarmReceiver"/>

Press Ctrl+K | Cmd+K and commit the SetAlarm changelist with the message Adds BroadcastReceiver for alarms. Your Git history will resemble Figure 7-45 with a third commit hanging off your initial starting point at A.
【翻譯】按住Ctrl+K | Cmd+K,用Adds BroadcastReceiver for alarms字段提交SetAlarm更改列表。你的git歷史會類似於圖7-45 所示,在A初始點會有第三個提交。

Figure 7-45. Git history after committing to the SetAlarm branch
【翻譯】圖7-45 提交到SetAlarm分支之後的git歷史

技術分享圖片

This feature by itself will not do much of anything on its own. It needs to be merged with the ScheduledReminders feature, which lives on its own branch. To wrap up your work, you need to combine these two features and push them to your remote Bitbucket host, but you want to do this in a way that makes it look like it was done by one person or one team on the main branch and clean up all of your other branches. Earlier you saw how a Git merge creates a commit with two parent commits from both branches involved in the merge. You also learned that a Git rebase combines two branches in a linear way with a single parent commit, which is exactly what you need. Open the Branches dialog box and check out the master branch. Click File ? VCS ? Git ? Rebase. Choose SetAlarm as the branch you are basing onto and deselect the Interactive check box since you now want to include all of your changes from the trunk. Click Start Rebasing. You should get the error pop-up shown in Figure 7-46.
【翻譯】提交到SetAlarm分支之後的歷史本身並不能實現很多功能。它需要與獨立存在於各自分支上的ScheduledReminders功能合並才能發揮作用。為了完成你的工作,你需要合並這兩項功能並把它們push到你遠程的Bitbucket主頁上。但是你需要使得它看起來是由一個人或一個團隊在主要分支上完成的,你還需要清除所有其他的分支。之前你看到了一個Git合並是如何利用合並內的兩個分支上的兩個父級提交來新建一個提交,你也學習了你最需要學習的知識點,如用一個以線性方式使用一個父級提交來合並兩個分支的Git rebase。打開分支對話框並檢驗主分支。點擊File ? VCS ? Git ?Rebase.選擇SetAlarm作為你base的分支,取消選定交互復選框,因為你現在需要把主幹中所有的更改都包含進去。點擊Start Rebasing.你會看到一個如圖7-46所示的錯誤彈出框。

Figure 7-46. Rebase conflict pop-up
【翻譯】圖7-46 Rebase 沖突彈出框

技術分享圖片

Resolving Conflicts While Rebasing
The pop-up should not alarm you, as it points out that Git has found some conflicts. Git marks files that it cannot automatically merge with a conflict status. It is up to you to resolve these conflicts before the rebase can continue. Traditionally, conflict resolution has been the bane of many collaborative efforts. It is natural to feel uncomfortable when you encounter an error or conflict, especially during a merge. However, familiarizing yourself with the not-so-happy path of collaboration and making merges and conflict resolution a habit,increases your ability to coordinate changes across teams and individuals. Also, Android Studio makes resolving such conflicts much less painful. Remember that you started the BroadcastReceiver in your master branch as part of the ScheduledReminders feature. This conflict comes as a result of code in two branches containing similar or identical changes. Find the conflict in the Changes view by looking for the files highlighted in red, as shown in Figure 7-47.
【翻譯】在rebase時解決沖突
彈出框會指出git發現的一些沖突,但它不會向你預警。Git會標記那些不能與沖突狀態自動合並的文件。在繼續rebase之前,你需要解決這些沖突。傳統上,沖突解決辦法一直是許多協作工作中的大麻煩。當你遭遇一個錯誤或沖突時,覺得不愉快是非常自然的。但如果你在合並時中遇到它們,那感覺會更糟糕。
然而,深諳這些不太愉快的合作方式並把合並和解決沖突當成習慣,這會增強你在個體間甚至團隊中的應變能力。而且,通過使用Android Studio,你會更容易解決這些沖突。記得你啟動過主分支上的BroadcastReceiver作為ScheduledReminders 功能的一部分。這個沖突是緣於兩個分支內的代碼,它包含類似或相同的更改。尋找標紅的文件,找到更改視圖中的沖突,如圖7-47所示。

Figure 7-47. Merge conflicts in the Changes view

【翻譯】圖7-47 在更改視圖中Merge沖突

技術分享圖片

Right-click and choose Git ? Resolve Conflicts from the context menu, as shown in
Figure 7-48. This will launch the Files Merged with Conflicts dialog box. Resolving confllicts traditionally consists of two parties offering two sources of input; your local changes or yours, and their incoming changes or theirs.
【翻譯】右擊並選中內容菜單中的Git ? Resolve Conflicts。
如圖7-48所示。這會你可以啟動Files Merged with Conflict對話框。解決沖突一般需要雙方提供兩種輸入來源,你當地的更改以及yours,他們即將發布的更改以及theirs。

Figure 7-48. Select the Resolve Conflicts option
【翻譯】圖7-48 選中解決沖突選項

技術分享圖片

The Android Studio Files Merged with Conflicts dialog box shown in Figure 7-49 is a powerful merge tool for performing three-way file merges and resolving text conflicts. It borrows yours vs. theirs terminology from the traditional merge scenario as it guides you through the merge. The merge tool considers the SetAlarm branch you are rebasing onto as theirs, or the incoming server changes. The master branch you are rebasing from is considered yours, or the local working copy. The Files Merged with Conflicts dialog box starts with a dialog box that allows you to Accept Yours, Accept Theirs, or Merge. The Accept Yours option totally ignores the incoming server file update from the branch you are rebasing onto in favor of the changes from the local working copy branch you are rebasing from and marks the file as resolved. The Accept Theirs option completely replaces your current branch’s local working copy with the incoming server file updates from the branch you are rebasing onto while marking the file as resolved. The Merge option takes you into the three-way merge editor, where you can pull in individual line changes from the incoming server and working copies into the base merge copy while custom merging only the things you need. The base merge copy is the output, or result, of the merge.
【翻譯】如圖7-49所示的Android Studio Files Merged with Conflicts對話框是一個強大的合並工具,能夠完成三方文件歸並,解決文本沖突。它會從傳統的合並方案中借用yours vs. theirs術語來指導你進行合並。合並工具會把你正在rebese的SetAlarm分支作為theirs或者incoming server changes,把你正在base的主分支當成yours或當地工作副本。Files Merged with Conflicts對話框以一個對話框的形式開啟,它能允許你進行Accept Yours, Accept Theirs或合並等操作。Accept Yours選項完全忽視你正在rebase的分支上的incoming server file updata,而是支持你當地工作副本分支上的更改並把這個文件標記為已解決。Accept Theirs選項用你正在rebase的分支上的incoming server file update來完全取代你當前分支上的當地工作副本,並把該文件標記為已解決。合並選項引導你使用三方歸並編輯器,當你專門合並你需要的項目時,你可以在這個編輯器上從incoming server和工作副本中把individual line changes 拉入base 合並副本中,其中base合並副本是合並的輸出或結果。

Figure 7-49. Merge the ReminderAlarmReceiver
【翻譯】圖7-49 合並ReminderAlarmReceiver

技術分享圖片

Click the Merge button to see how this works. The merge editor shown in Figure 7-50 opens.
【翻譯】點擊合並按鈕,看看它如何運行。合並編輯器如圖7-50 所示。

Figure 7-50. The Merge editor
【翻譯】圖7-50 合並編輯器

技術分享圖片

The Merge editor lines up your working copy and the incoming copy on either side of the Merge Result, which is the editable part of the screen. It is syntax and import aware, which means you can use auto-complete and quick-fix and other keyboard shortcuts as you
edit the local copy. This gives you certain advantages not present in external VCS merge tools. The editor shows both the local working copy and the incoming update, which is marked Changes from Server. These are the changes from the SetAlarm branch that you are rebasing onto. Along the sidebars, you’ll see little double chevrons and Xs next to the changed lines. Clicking a double chevron from either side will include that particular change in your merge result. Clicking the X will omit that particular change. The changes are also color coded, red for a conflict, green for additional lines, and blue for changed lines. In this case, the majority of the file is conflicting.
Since you have only a stub of the class in your local copy on the left, it makes more sense to accept the entirety of the complete implementation from the right incoming changes. Click Cancel and answer Yes to the prompt asking if you want to exit without applying changes.
Click Accept Theirs in the Files Merged with Conflicts dialog box to take the entire incoming server changes. The dialog box lines up the mainfest file next. If you click Merge, you will see that the local working copy has the exact same modification as the incoming server copy, so you can choose either Yours or Theirs. Click the double chevron from the local working copy to accept your change and the X in the incoming copy pane to deny theirs.
Click Save and Finish from the prompt that pops up to complete your merge. Both files will be marked as conflict resolved for Git. If you look in the Changes tool window, you will see files you merged in the Default changelist. Git has paused in the middle of replaying the series of changes onto the ScheduleAlarm branch and is waiting for you to continue.
Go to the main menu and find the VCS ? Git ? Continue Rebasing option, as shown in Figure 7-51. Note you also have the option of either aborting the rebase or skipping this commit while rebasing. If you were in the middle of a complicated merge and realized something was catastrophically wrong, you could click Abort Rebasing and return everything to the state it was in prior to starting the rebase. If you accidentally included a commit
with several conflicts, you also have the option of skipping. Click Continue Rebasing to finish the rebase.
【翻譯】合並編輯器會把你的工作副本以及可在界面中編輯的任意一邊的合並結果中的incoming副本排成一行。它是syntax和import aware, 這意味著當你編輯本地副本時,你可以使用自動完成、快速修改以及其他鍵盤快捷方式來進行相關操作。
編輯本地副本合並編輯器也還有一些其他的VCS合並工具中沒有的優勢。這個編輯器既顯示了當地工作副本,也顯示了服務器上被標記為更改的incoming update。這些是你正在rebase的來自SetAlarm分支的更改。沿著邊欄,你會看到小標簽double chevrons和修訂行旁邊的Xs。從任意一邊點擊double chevron,這樣會讓你的合並結果中顯示特殊的更改。點擊X可以刪除這一特殊更改,這些更改也是被彩色編碼的。其中紅色表示沖突,綠色代指添加行,藍色指修改行。在這樣情況下,大部分文件都是沖突的。
因為你在左側的當地副本中僅有一小段class, 所以完全接受右側的incoming changes中的complete implementation將更有意義。點擊取消按鈕,在詢問你“是否在不應用更改的情況下退出”的提示窗口中回答是。
在Files Merged with Conflicts對話框中點擊Accept Theirs,進行完整的incoming server更改。接著對話框會把顯示文件排列成行。如果你點擊合並按鈕, 你會看到當地工作副本與incoming server副本擁有完全一致的更改,所以你既可以選擇Yours選項,也可以選擇Theirs選項。點擊當地工作副本上的double chevron,接受your 更改以及incoming copy窗格中的X更改,取消theirs.
從跳出的即時窗口點擊保存和完成按鈕,完成此次合並。這兩個文件在git上都會被標記為“已解決”。如果你查看更改工具窗,你會看到你在默認更改列表中合並過的文件。這時Git已經在ScheduleAlarm分支上的replaying更改序列中暫停運行並等待你的下一步操作。
去主菜單找到VCS ? Git ? Continue Rebasing選項, 如圖 7-51所示。註意你既可以中止rebase, 也可以在rebase時跳過這項提交。如果你身陷一項被災難性錯誤包圍的復雜合並中,,點擊AbortRebasing選項,把一切還原到你進行rebase前的狀態。如果你在提交時不小心地包含進了幾項
沖突,選擇跳過選項。點擊ContinueRebasing來結束此次rebase.

Figure 7-51. Click the Continue Rebasing menu option

【翻譯】圖7-51 點擊Continue Rebasing菜單選項

技術分享圖片

The rebase will complete, and a new commit is performed. The Git history will reflect a copy of all the changes from the master following the SetAlarm commit in the timeline. This is shown in Figure 7-52.

【翻譯】rebase就這樣結束了,一項新提交被完成了。Git歷史會在時間軸中顯示一個副本,它列出了SetAlarm在提交後的來自母版的所有更改。如圖7-52所示。

Figure 7-52. Git history after rebasing and fixing conflicts
【翻譯】圖7-52 rebase和修改沖突後的Git歷史

技術分享圖片

The master contains commits B and C, supporting ScheduledReminders; commit E, which added the About screen; and commit F from the SetAlarm branch. You also decided you no longer want the ImportantReminders feature with your earlier rebase.
The task of setting the alarm and implementing the actual BroadcastReceiver was done on a separate branch but it now looks like a tag, or milestone, in your timeline. To complete your feature, you need to tie your work from the ScheduleReminders branch to the actual BroadcastReceiver in the SetAlarm branch. Make the following change to connect the listener that invokes the BroadcastReceiver to the TimePickerDialog. You will insert the following code snippet at the end of the else block just before the dialog that we use for Edit Reminder.
【翻譯】母版包含了支持ScheduledReminders的提交B和提交C、被添加在About界面上的提交E和SetAlarm分支上的提交F.你也決定你不需要用你之前的rebase方式來設置重要提醒功能。
分別在不同的分支上設置aralm和完成實際的BroadcastReceiver等任務結束了, 但現在它在你的時間軸裏看起來就像是一個標簽或一個裏程碑。為了完善你的功能,你需要把你ScheduleReminders分支上的工作轉換到到SetAlarm分支上的 BroadcastReceiver中。作出下列更改,把調用BroadcastReceiver 的Listener關聯到TimePickerDialog上。在我們使用編輯提醒器對話之前,把下列代碼片段插入到每一個block的結尾部分。

new TimePickerDialog(RemindersActivity.this,listener,today.getHours(),today. getMinutes(),false).show();

Run your project on a device and verify that the feature works. You should now get device notifications when you schedule reminders, as shown in Figure 7-53.
【翻譯】在一個設備上運行你的項目並確保這個功能能正常運行。當你設置提醒事項時,你會看到一個設備通知, 如圖7-53所示。

Figure 7-53. Notification from a reminder
【翻譯】圖7-53 來自提醒事項上的通知

技術分享圖片

You can now push your master branch to the remote Bitbucket host. From the File menu, choose VCS ? Git ? Push. The dialog box in Figure 7-54 opens, giving you the ability to push changes from your local master branch to the remote master branch of your Bitbucket repository. Click the Push button to perform the push.
【翻譯】你也可以把你的主分支推送到遠程的Bitbucket主機上.從這個文件菜單中, 選擇VCS ? Git ?Push.接著圖 7-54所示的對話框會打開,它能讓你從當地的主分支上推送更改到你Bitbucket版本庫上的遠程主分支。點擊推送標簽執行此次推送。

Figure 7-54. Push your changes to Bitbucket
【翻譯】圖7-54 把你的更改推送到Bitbucket上

技術分享圖片

Since you are done with the ScheduledReminders and ImportantReminders branches, they can be deleted. Open the Branches dialog box and select both of these branches in turn; click Delete to remove them.

【翻譯】刪除你已經完成了的ScheduledReminders和ImportantReminders分支。打開分支對話框,輪流選中上面兩項分支,點擊刪除。

Git Remotes

Git remotes are merely copies of a Git repository stored on a remote server and accessible over a network. While you can use them similarly to a traditional client/server-modeled VCS like Subversion, it is better to think of them as publicly accessible copies of your work. You don’t commit to a shared central server in the Git workflow; instead you share your work via pull requests.
The pull request is a request from one developer to pull in changes from a public repository under that developer’s profile. Others are free to include individual commits or your entire work at their discretion. You will usually find a main branch, with one or more lead developers responsible for keeping that branch up-to-date with the latest and most valuable features and commits. The leads pull in changes from various contributors by using the entire feature set of Git, which allows the selection, removal, reordering, merging, squashing, and amending of individual commits.
However, pull requests are for advanced Git users. The most common way people begin with Git is by cloning a project from a Git hosting server—downloading an entire copy of the Git repository to work with locally. You continue to make changes and commit them locally, and then finally push these changes back to the remote repository. You can also fetch and merge changes that were pushed by others up to the remote.
Another option is to start with an empty repository locally and build a project. You then push the project to a Git hosting service such as Bitbucket or GitHub and advertise it to be shared with others, or you can make it private and invite others at your discretion. Development continues as in the common approach, with local commits that you push to the remote.
Eventually, contributors fork and add to their remote copies of the project over time as you work, and you will fetch and merge these changes.

【翻譯】遠程Git

【翻譯】遠程Git僅僅是儲存在遠程服務器內、可通過網絡連接上的git版本庫副本。你會傾向於把它們當作像傳統的subversion一樣的用戶/服務器版本控制系統來使用,但是最好把遠程Git當作是你的可被公開訪問的工作副本。你並不是在Git工作流中向一個共享的中心服務器提交; 反而你是通過pull申請來共享你的工作。
pull申請是一項來自一個開發人員的請求,它請求在那個開發人員頭像下的的公共版本庫內pull更改,其他人可以在他們的審核下,自由地把個人提交或你的
整項工作列入進來。你通常會發現一個主要分支,它由一個或多個核心開發人員負責用最新的、最有價值的功能和提交來更新。這會導致不同貢獻者依靠使用整套的Git的功能設置來把更改拖進Git中, 因為它允許選中、刪除、重新排序、合並、粉碎和修補個人提交。
然而, pull請求僅針對Git的高級用戶。人們打開git的最常見方式是:先從Git主服務器上克隆一個項目來打開git,然後再下載git版本庫上的整個副本來在當地工作。你可以繼續作出更改並在當地把它們提交出去,然後讓這些更改最終被push回遠程版本庫中。你也可以提取和合並被其他用戶push進遠程版本庫內的更改。
你的另一個選擇是是在一個空的版本庫上新建一個項目。然後你可以把這個項目push進git主服務器Bitbucket或GitHub中,並把它廣而告之以便他人貢獻共享。或者你也可以把它設置成個人私有模式,邀請他人在你的審查下進入。隨著你把當地提交push到遠程版本庫,開發會以常用的方式持續進行下去。
最終,貢獻者可以在你工作時為你的項目作分支和添加工作,以便你最終可以提取和合並這些更改。

Pull vs. Push Model

Traditional VCS systems rely on a push model whereby features are worked on by several developers and eventually pushed up to a central server. While this model has worked for years, it is subject to the limitations of a single copy of the master branch becoming corrupt as contributors attempt to merge their changes by using diffs and patch files. Patch files are textual representations of the individual actions taken to change source files; for example, indicating to add these lines, remove those lines, or change this line. Most VCS systems that follow this model manage changes as a series of diffs applied over time.
Git follows a distributed pull model treating a project as a shared entity. Because Git allows distributed copies of the master branch, any individual is allowed to commit and update a local copy at any time, which reduces the complexity involved with merging work between contributors. Git also elevates the significance of individual commits, treating them as snapshots of your repository over time. This leaves the tool better adept at managing changes. It also adds the flexibility of managing multiple changes to an individual source file separately. Merges are much more precise and manageable, and the complexity of
combining work is dramatically reduced. For example, a project lead could pull a feature that you’ve implemented in 10 or so commits spread between multiple branches, squash them all into one, amend the message, and organize it in that lead’s personal history before other commits in the master branch, and finally push and publicize it on the remote associated with the project.

【翻譯】Pull vs. Push模式

【翻譯】傳統的版本控制系統依賴於 push模式,通過這種模式,幾個開發者使用共同的功能並把它們最終push回一個中心服務器。盡管人們數年來都習慣這種模式,它仍然受限於主分支上的單一副本,因為它在貢獻者通過使用diffs和patch文件來嘗試合並他們的更改時會奔潰。修補文件是個人操作的文本形式,被用來改變源文件。比如說,它可以被用來表示添加這些行,刪除那些行或者更改這行。采用這一模式的大多數版本控制系統在一系列diffs被運用的時候進行更改管理。
Git把一個項目作為共同體,遵循分布式的pull模式。因為Git承認主分支上的分布式副本,所以任何人在任何時候都被允許提交和更新當地副本,這一模式降低為貢獻者們降低了合並工作的復雜性。Git也會增強個人提交的重要性,並把這些個人提交視為你當地版本庫的快照。這會讓它更善於管理更改。而且,它還為管理個人源文件上的多重更改增加了靈活性。並合並更加精確且可控,
極大減少了合並工作的復雜程度。比如說,一個項目負責人可能會pull你完成的散布在多個分支上的十多個提交,一次性全部粉碎這些提交並修改信息並在主分支上的其他提交之前在這個負責人的個人歷史中規劃這項信息。最終,在與這個項目有關的遠程版本庫中push並公開它。

Summary

This covers the basics of using Git with Android Studio. In this chapter, you’ve seen how to install Git and use it to track changes. We demonstrated how to add your source to Git
and used the Git log feature to see a summary of your commit history. You’ve seen in-depth examples of how branches work like labels pointing to individual commits. The branches can be moved between commits by using relative references or even deleted entirely. We’ve demonstrated how Git history can modify changes that were committed in parallel and line them up serially. We demonstrated a few collaborative scenarios involving multiple branches maturing simultaneously.

【翻譯】總結

【翻譯】這章囊括了在Android Studio上使用Git的基本方法。通過在這一章,你了解了如何安裝Git以及如何用它來追蹤更改,如何把你的資源添加到Git上
並使用Git的日誌功能去一覽你的提交歷史。你也見到了許多關於分支如何像指向個人提交的標簽那樣運行的詳實例子。這些分支可以通過使用相對參照和徹底刪除之間的提交來進行移動。我們向你展示了git歷史是如何修改以平行或序列線形方式提交的更改。最後,我們還向你展示了一些包含多重分支共同成熟完善的合作場景。

第七章 : Git 介紹 (下)[Learn Android Studio 漢化教程]