Lesson 3: Using GitHub to Collaborate
3.1 Creating a GitHub Account
Set up Password Caching
Every time you send changes to GitHub via the command line, you'll need to type your password to prove that you have permission to modify the repository. This can get annoying quickly, so many people like to set up password caching, which will let you type your password once and have it auto-filled on that computer in the future. To do this, follow the instructions here. If you're using Windows and you followed our Git installation instructions earlier, you're using msysgit, so you can follow the instructions for msysgit.
3.2 Keeping Repositories in Sync
在向github推送前,一定要先把working directory and staing area里的文件commit掉, 通過(guò)commit history記錄下來(lái)。

github repo里沒(méi)有working directory and staing area, 因?yàn)間ithub repo 是在遠(yuǎn)程的,并不能直接連接,所以沒(méi)有。github不會(huì)像其他service一樣sync with cloud,比如CMD markdown就是,我現(xiàn)在敲擊的每一句話都會(huì)立刻與云端同步。而且正因?yàn)槟茏詣?dòng)同步到云端,when you use Github, you need to choose when and how to get two version.
So, since syncing doesn't happen automatically, how do we sync between the local copy of a repository and the one hosted on GitHub?
你可能回答lesson oneli里用過(guò)的git clone.但這個(gè)命令只能從github server clone, 并不能把本地的repo clone 到github server上。
git has a concept of a remote repository. This lets you store the location of a repository that you will want to send and receive new commits to and from. Git users often refer to these remote repositories simply as remotes.
我們?cè)谥蟮恼n程里再詳細(xì)講這個(gè)remote repository。
假設(shè)我們現(xiàn)在已經(jīng)有了remote repo指向github上的repo(見(jiàn)圖中arrow), you can pull data and push data. 我們不是一個(gè)一個(gè)的commit推送,而是選定一個(gè)branch, git push后,就能把這個(gè)branch下的所有commit同步到remote repo。

但是想象一些,如果branch里有上百個(gè)commit,每次push都要把所有commit推送的話是件很低效的事。

git的做法很聰明,只提交“有用的”branch。比如下圖中l(wèi)ocal有4個(gè)branch, github里只有一個(gè)branch. 現(xiàn)在我要推送local 里的a, 即e53,github會(huì)找到這個(gè)e53的所有parent和children。并只推送github中沒(méi)有的branch. 而664因?yàn)閡nreachable,所以不會(huì)被推送。所以結(jié)果只有fd2 and e53被推送。

3.3 Adding a Remote
我們打算把local 的 reflection 推送到github. 先cd到reflection directory。
記住,remote repo的stardard name 是origin. 用git remote add origin url_address,url_address可以在創(chuàng)建好的github repo里找到,初始化不帶。
git remote add origin https://github.com/user_name/reflections.git

我自己嘗試推送的時(shí)候得到了error
[XX@XXXX] ~/Udacity/version-control/reflections
? git push
fatal: Not a git repository (or any parent up to mount point /home)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).
發(fā)現(xiàn)這個(gè)reflections derectory根本沒(méi)有初始化。
初始化以及準(zhǔn)備工作: git init, git add xxx.txt,git commit -m "add xxx.txt.
好了,創(chuàng)建remote: git remote add origin https://github.com/user_name/reflections.git。
git remote能查看remote branch. git remote -v能查看更多的信息。
git push takes two arguments, the remote I want to send changes to, and the name of local branch that I'd like to push. 所以把branch master push到 remote origin.
git push origin master

命令行提示輸入github的用戶名和密碼,輸入后推送完成,可以在github官網(wǎng)上看到相應(yīng)的文件了。
推送后,github默認(rèn)會(huì)創(chuàng)建相同的branch name,即github上的branch也叫master。
3.4 Editing Files on GitHub
點(diǎn)擊commit button,可查看commit history. 點(diǎn)擊new fiel創(chuàng)建一個(gè)新文件。填寫(xiě)文件名,文件內(nèi)容,commit message等相關(guān)信息。

我們?cè)趃ithub直接創(chuàng)建一個(gè)文件,比如collebrate的時(shí)候別人也會(huì)上傳一些commit,而我們的本地主機(jī)沒(méi)有相關(guān)文件。下一節(jié)練習(xí)如何得到最新的version。
3.5 Pulling Changes
這是我們現(xiàn)在的狀態(tài)

利用git pull來(lái)獲得最新的commit

在terminal端的操.git pull后還是要two argus, 一個(gè)是remote name, 一個(gè)是本地的branch name.
git pull origin master
pull之后,branch也會(huì)checkout到最新的commit狀態(tài)。

run git log就能看到在github端提交的commit了。
3.6 Concept Map: GitHub, Push, Pull, Remote
We’ve introduced a few new concepts since we last revisited our concept map.
- GitHub
- git push
- git pull
- remote
GitHub is a service that lets users interact with Git. But I chose to represent it as Git being a part of GitHub.
A remote in your local repository is basically a reference to another repository, so we can say that remote refers to repositories. Also when you clone a repository, a remote gets set up for you automatically, so we can say that clone operators on remotes.
When you push or pull, you have to specify what branch you want to push or pull. So, it definitely operates on branches. Pull takes a branch from a remote and brings it to your local repository. And push does the opposite, taking a branch and pushing it to a remote. So these do both operate on a remote as well.

3.7 Forking a Repository
左上是原始的repo,通過(guò)fork,會(huì)在自己的github賬戶中創(chuàng)建一個(gè)相同的repo。而Caroline和Sarah可以對(duì)右上的repo做出各種修改,制作自己喜歡的recipe,個(gè)人定制化。

quiz

左上,Branches happen on a single repository. Of course, you can push and pull branches, but when you create one, you're creating it on one single repository
右上,右下,Cloning involves taking an existing repository and making one just like it. The original repository could either be remote, like in this case, so here we cloned from GitHub to local. Or you could even clone a local repository into another spot on your computer. We haven't really talked about this, so this one was probably a little tricky.
左下,This one looks a lot like a clone too, but remember, we are cloning our repository from GitHub onto GitHub. You do that using GitHub's built-in fork feature. Forking is only used within the context of GitHub, taking an existing GitHub repository and making a copy of it, whereas clone works on any two repositories.
3.7.1 Fork the Recipes Repository
找到想要fork的repo,點(diǎn)擊github頁(yè)面右上的fork,這樣你的賬戶里就有一樣的repo了。跳轉(zhuǎn)頁(yè)面到你賬戶里的repo,找到右下的https賦值。在本地git clone https//XXX就能得到local repo. 如果是通過(guò)這種方式,我們就不用自己添加remote了,git會(huì)自動(dòng)添加remote. 不信的話運(yùn)行git remote -v查看詳情。
我想讓Larry和我一起collaborate這個(gè)repo,在右下的setting里添加collaborator,輸入對(duì)方的github name.
3.7.2 Push Changes to the Recipes Repository
Add a new recipe to the repository
On your own computer, add a new recipe for a food that you like and commit it on the master branch.
Push your changes
Push the master branch to your fork.
Where was your commit?
Before you ran git push, your change should have only existed locally via git log. Commits will not automatically be shared to remotes - you have to manually push your branch if you want to share changes.
After you ran git push, your change should have existed locally and on your fork. It should not have existed on Larry's repository, which is the repository you forked. The reason you forked in the first place is because you don't have permission to change Larry's repository!
3.8 Collaborations Cause Conflict
如果local和github上的repo都有了改變,那么不論是pull還是push,都會(huì)有confilict.

其實(shí)我們想merge local and remote branches.
3.8.1 Change the Chili Recipe Quiz
最上面的commit是另一個(gè)人提交的。

因?yàn)閮蓚€(gè)人都對(duì)同一個(gè)文件的同一行做出了改動(dòng),github會(huì)高亮標(biāo)識(shí),提示有confilct

3.9 Updating Local Copies of Remote Branches
我對(duì)一個(gè)Chili Recipe里做了改動(dòng)后(包括add, commit),本地的master已經(jīng)最新了,但是remote branch還沒(méi)有更新。而remote branch的name就是origin/master,通過(guò)git push后,才能讓branch master和origin/master同步。不信的話先別push,git diff origin/master master (git diff old_one new_one), 可以看到二者之間的差別。
圖中本地的origin/master和github的master都是未更新?tīng)顟B(tài),只有l(wèi)ocal的master有改動(dòng),是latest.(注:origin和origin/master是一個(gè)branch)

push后,全部更到最新。

如果現(xiàn)在local和github repo都改變了

我們可以通過(guò)git fetch只更新local, 即讓origin/master和github repo(remote)同步,而讓local的master被保留。

也就是說(shuō),local現(xiàn)在有兩個(gè)branch,一個(gè)是master,一個(gè)是和remote github端同步了的origin/master. 比如說(shuō)現(xiàn)在我要上飛機(jī),但我本地已經(jīng)有了最新的version,這個(gè)時(shí)候我可以merge這兩個(gè)branch。但我也可以不著急merge二者,繼續(xù)在master做我的修改。

但如果merge了的話,其實(shí)相當(dāng)于用了git pull。因?yàn)閜ull的流程也是先更新(fetch)本地的remote branch origin/master,然后再把origin/master和local的master 合并(merge).
所以說(shuō),git pull = git fetch + git merge

3.9.1 Merging the Changes Together
實(shí)操:command line
現(xiàn)在的狀態(tài)是github remote段寫(xiě)了兩個(gè)commit,local段寫(xiě)了一個(gè)commit.
可以用git branch -a看到remote branch. 用git fetch origin把本地的origin/master更到和github remote端一樣新。git log orgin可以查看origin/master的所有commit,現(xiàn)在這個(gè)branch的commit已經(jīng)完全和github端一樣了,git log查看的是local的master。

git status可以看到當(dāng)前的狀態(tài),提示說(shuō)origin/master和local的master有不同的commit進(jìn)度

git merge master origin/master,理所當(dāng)然得得到了conflict提示,因?yàn)閮蓚€(gè)branch的commit history不一樣

好了,打開(kāi)有問(wèn)題的文件,fix the conflict.
原文件

我要保留github 段做出的修改

修改完后,git add xxxx and git commit這一次沒(méi)有加message,但是竟然跳出了nano的編輯界面,自動(dòng)寫(xiě)好了message. Ctrl+X, 選yes, alt+D選擇DOS-format,即可保存message。果然還是自動(dòng)的填寫(xiě)的信息更準(zhǔn)確方便。

通過(guò)commit之后,這次merge也就算成功了。當(dāng)然,也可以直接git pull.
git push origin master,順序不能錯(cuò),必須是git push remote_branch local_branch. push后就能在github看到所有的commit了。
3.9.2 Fast-Forward Merges
既然git pull = git fetch + git merge,那為什么在上一節(jié)的例子里,直接用git pull的時(shí)候沒(méi)有g(shù)enerated merge commit like git fetch + git merge did.
因?yàn)閱?dòng)了fast-forward merges. This kind of merge occurs when you merge two commits, where one is ancestor of the other. (一個(gè)commit是另一個(gè)commit的祖先,這里的commit也可以理解為branch)

如果想把上圖中的a和b合并,其實(shí)沒(méi)有必要?jiǎng)?chuàng)建一個(gè)新的commit。想想也知道新的commit也會(huì)有二者共同的commit history, 那么創(chuàng)建一個(gè)新的commit就沒(méi)有必要了。

只需把commit label 更到最新即可。So instead of adding a new commit, all we would do is update the lable to point b(latest).

We're taking a label from the history of a branch somewhere in its ancestry, and moving that label forward to the tip of the branch.
quiz

3.9.3 Making a Pull Request
其實(shí)這里的pull并不是git pull里的意思,而是我打算在github段合并兩個(gè)branch,這個(gè)合并的申請(qǐng)叫做 pull request, github非要這么設(shè)定,只能順勢(shì)而為了。
現(xiàn)在做一個(gè)example,展示整個(gè)workflow。
- 我先在本地修改了
cask-recipe.txt里的配方,添加了一種更健康的oil. - 創(chuàng)建一個(gè)branch,叫different oil.
git branch different-oil+git checkout different-oil或者用一個(gè)命令git checkout -b different-oil. -
git add cask-recipe.txt+git commit+git push origin different-oil. 這樣就把branch different-oil 推送到了github端。接下在就能在github端查看了。
git121.png-127.6kB -
切換到branch different-oil,查看commit
git122.png-141.5kB -
我們向pull request, 點(diǎn)擊pull request button(如果綠色的那個(gè)button沒(méi)出現(xiàn)的話就在branch different-oil里點(diǎn)pull request button,如圖)
git123.png-102.5kB - github默認(rèn)會(huì)認(rèn)為你想要和原版的Larry的master合并,但是我們只是想把branch different-oil和master合并而已。點(diǎn)擊右側(cè)的edit,選擇要合并的branch。再點(diǎn)擊右下的create pull request. 這樣我們就發(fā)出了請(qǐng)求。
-
現(xiàn)在在pull request里可以看到我們做出的所有commit,修改。其他的人可以在主頁(yè)面右側(cè)的list里有pull request,可以點(diǎn)擊查看。
git124.png-82.5kB - 好了,接下來(lái)是另一個(gè)contributor的視角了,也就是Sarah.因?yàn)镾arah watching Caroline's fork of the recipes repository, 所有Sarah got an email notifying that Caroline made a pull request. 點(diǎn)擊郵件里的地址,查看pull request.
-
Caroline想讓sarah同意合并maser和different-oil。因?yàn)閙aster是最主要的branch,所以必須保證沒(méi)有錯(cuò)誤。Sarah查看了Caroline做出的修改,但是添加的那個(gè)oil有拼寫(xiě)錯(cuò)誤。所以Sarah在下面的寫(xiě)一個(gè)comment,提醒Caroline發(fā)現(xiàn)的問(wèn)題。也可以在上面出錯(cuò)的地方寫(xiě)一個(gè)inline comment
git126.png-155.6kB - 如果檢查后一切正常,可以點(diǎn)擊merge pull request button. 這個(gè)button只有在沒(méi)有conflict的時(shí)候才會(huì) git127.png-130.3kB
- 在有conflict的情況下,先讓Caroline fix the conflict。讓Caroline合并master和different-oil,成功后說(shuō)明沒(méi)有什么問(wèn)題,之后再同一merge.
quiz

3.9.4 Updating a Pull Request
- 上一節(jié)里Sarah發(fā)現(xiàn)了pull request 里有spell error,所以寫(xiě)了個(gè)comment。接著Caroline收到了郵件,里面寫(xiě)著comment的內(nèi)容。
-
Caroline在local檢查了下文件,發(fā)現(xiàn)全是寫(xiě)錯(cuò)了,于是fix,然后commit the fix。
git130.png-67.3kB
git131.png-179.7kB -
git push origin different-oil,這樣github端也能看到修改了。
git132.png-62.5kB - push branch自動(dòng)出現(xiàn)在pull request界面,在Sarah的comment下面,能看到Caroline的commit:Fix type in caola.
git133.png-120kB -
現(xiàn)在commit顯示為2,file changed顯示1,可以點(diǎn)擊file changed查看修改。
git136.png-99kB
3.9.5 Conflicting Changes
前一節(jié)我們學(xué)會(huì)了如何pull request,這一節(jié)我們take a look at what happens when someone else makes changes that confilct with your pull request.
Sarah也made a pull request,

It looks like she increased the amount of oil to put in the cake so that it would be more moist. Since our changes affect the same line, git will mark them as a merge so one of us will have to resolve the conflict.
二人修改的是同一行,所以git認(rèn)定是一個(gè)merge conflict,二人中的一個(gè)得負(fù)責(zé)fix it.

點(diǎn)擊左上的conversatoin button,先點(diǎn)擊綠色的merge pull request, 再點(diǎn)擊綠色的Confirm merge, 即先confirm Sarah的changes,然后再去resolve merging conflict。

Confirm后就可以刪除sarah創(chuàng)建的more-oil branch 了。

回到pull request 界面,發(fā)現(xiàn)無(wú)法merge的消息提醒。This is because performing a merge between the master branch and my branch would now cause merge conflicts. 之前的Sarah的修改已經(jīng)提前改變了master里的cake-recipes.txt里的oil那一行,而Caraline在自己的branch里也是修改的同一行,所以無(wú)法合并master,有confilit.

解決方法:Rather than having you resolve the merge conflicts from the browser GitHub requires you to merge the changes on your own computer and send update the pull request with the merged version.
也就是說(shuō)github不讓你通過(guò)browser更改,必須要在local fix conflict, merge suffessfullly, then git push to update the merged version.
圖解
初始狀態(tài):左圖是local version,master在中間,Craline做出的changes全在新的branch different-oil里。右圖是github version. 可以看到中間是master,但是從master開(kāi)始,向右有兩個(gè)branch就有差異了。一個(gè)右上角Sarah做出修改的branch more-oil,一個(gè)是右下角Craline做出的changes的branch different-oil。

我們把master和Sarah的more-oil branch合并。這其實(shí)本來(lái)是個(gè)fast forward merge, 也就是說(shuō)master的lable會(huì)移動(dòng)到more-oil上,并不會(huì)創(chuàng)建一個(gè)新的commit。但是github的merge機(jī)制不一樣,只要是github頁(yè)面上的merge button,點(diǎn)擊后merge后就一定會(huì)有一個(gè)commit。(it turns out that even if you could of had a fast forward merge, merging with the button on GitHub will always make a commit anyway even if no extra information is given by making that merge commit.) 合并后master label 到了新的commit上?,F(xiàn)在就可以刪除more-oil這個(gè)branch了,因?yàn)橐坏┖喜⑺氖姑簿屯瓿闪?。所以在圖中把右上角的more-oil這個(gè)branch name 移去。現(xiàn)在Craaline想要把自己的branch和master合并,但因?yàn)閮蓚€(gè)人都對(duì)同一line做除了改動(dòng),所以有conlict. 現(xiàn)在Caraline必須在local fix this conflict.

Now if Caroline wants to update her pull request to include my changes. If merging these two branches wouldn't cause a conflict, I could actually just pull in her request now. But since we changed the same lines, she's going to have to pull these changes over into her local version. So she'll need to pull master.
要想在local修改,就要用git pull更新本地到最新版本。

好了,現(xiàn)在Caraline可以直接fix conflict,merge master and different-oil, git push, 這樣github段的master就能更新了。但是!!!這么做的話其他人沒(méi)有機(jī)會(huì)看到Caraline做出的修改,也沒(méi)有機(jī)會(huì)提醒修改是否合理。尤其是在collaboration的環(huán)境下,必須要讓別人review,所以要通過(guò)github的pull request功能來(lái)提交,這樣其他人就能得到通知,來(lái)查看修改是否正確了。
具體的做法: Caroline will need to make the fix to her branch. Fix the typo for canola, and then merge in master into her different oil branch. And then push her branch up to GitHub which will update the pull request so that I can look at that before merging it back into master.
也就是說(shuō)把所有改動(dòng)放在different-oil里,然后合并master到different-oil, 再push different-oil,github那邊會(huì)自動(dòng)更新 pull request. 注意,別把different-oil合并到master,然后推送master,這會(huì)直接覆蓋,別人沒(méi)有機(jī)會(huì)在merge前review。

3.9.6 Updating Your Local Repository
上一節(jié)講了各種原理,這一節(jié)講在terminal端的具體命令操作。
用git pull origin master更新local. 也可以用git fetch + git merge origin master.

先checkout到different-oil,再git merge master different-oil.這樣才能把master merge到branch。如我們所料,得到了merge conflict提示。

下面是stackoverflow上的回答:
How to merge the master branch into the feature branch? Easy:
git checkout feature1
git merge master
I'll resolve the conflict keeping both of our changes, so now there's three quarters of the cup of canola oil, and then I'll commit the merge.
修改了cake-recipes.txt后,commit.

Now I'll run git log, and I can see that this branch contains both of our changes.
這下兩個(gè)人的修改commit就都能看到.

之后run git push origin different-oil。As you saw before, pushing the branch updates the pull request.
push后就能更新github端的pull request了

在點(diǎn)擊綠色的Merge pull request前,先寫(xiě)個(gè)comment通知Sarah讓她來(lái)review.因?yàn)閡pdata the pull request的消息是不會(huì)email給Sarah的。

quiz

After running git log -n 1, you should have seen output something like this:
commit bc368511c6406028c77e2631f77c4d22a5da16d0
Merge: 79fff84 23d1775
Author: cbuckey
Date: Tue Sep 30 18:50:28 2014 -0400
Merge pull request #1 from cbuckey-uda/different-oil
Change vegetable oil to canola oil
Notice that the commit message:
- Indicates that a pull request was merged
- Gives the number of the pull request (#1 here)
- Gives the branch the pull request was merged from (cbuckey-uda/different-oil here).
- Contains the title of the pull request.
GitHub automatically creates a commit message like this whenever a pull request is merged to make it easy to see pull requests in the commit history. Even when the merge is a fast-forward merge, GitHub still creates this commit.
3.10 CM: Fork, Fetch, Pull Request


Forking is like cloning but with some extra steps and you can only do it on GitHub itself. It also takes a repository and makes another repository, so it does operate on repositories.
We know that fetching is a part of pull, but does it operate on remotes and branches? It clearly operates on remotes, because you're fetching data from the remote repository. The connection to branch is a little less clear. You can definitely, fetch a particular branch. When you fetch, the branch doesn't necessarily get updated. But remember that, we have references to the remote versions of our branches, and those are the things that get updated. So, it does operate on branches, as well.
you would think fast-forward merge would be related to merges.But the way that I think, about fast-forward merges is basically, that they change where a branch points. So, it's take a branch label from one commit to another commit. So in my mind, it just operates on a branch.
When you make a pull request, you're asking to have a particular branch be merged in, with the main branch or some other branch. It doesn't necessarily, have to be a master. And pull requests are purely GitHub idea. They don't exist in git proper. So, mergers are part of pull requests. Pull requests, work on branches. You merge two branches together. And it's something that's part of GitHub, so it all fits.
3.11 Reflect: When to use a separate branch
You just saw that the workflow when making changes in a separate branch is more complicated than working directly in master, especially when you need to stay up-to-date with changes others are making. Rather than simply pulling and pushing, you need to pull changes into your local master branch, merge the local master into your branch (different-oil, in our case), then push your branch to the remote before finally merging your branch into master, either locally or on GitHub.
Given that, please add the following question and your thoughts on it to your reflections file:
When would you want to make changes in a separate branch rather than directly in master? What benefits does each approach have?
因?yàn)橥ㄟ^(guò)創(chuàng)建不同的branch來(lái)添加新的feature更易于和別人合作,每個(gè)人都更易于理解project的branch結(jié)構(gòu),user friendly. 通過(guò)pull request來(lái)merge,也能讓別人review。
3.12 Modifying the Adventure Repository (實(shí)操練習(xí))
以下是指南部分,主要是fork這個(gè)repo,來(lái)進(jìn)行練習(xí)。
Fork the repository and clone your fork
Now that you've learned how to fork a repository, push changes to your fork, and make a pull request, you’re ready to contribute to the create-your-own-adventure story that you saw at the beginning of the lesson. To do this, first you should fork this repository. Then clone your fork, and make a branch to make your changes in.
Note: You could make your changes directly to the master branch in your fork, but when contributing to a public repository, it’s standard practice to make the changes in a non-master branch within the fork. This way, you can easily keep your master branch up-to-date with master of the original repository, and merge changes from master into your branch when you are ready.
Make a change to the story
Next, you should actually make a change to the story. For instructions on how to do so, please read the README in the create-your-own-adventure repository.
Make a pull request
Next, you should make a pull request containing your changes to the original repository. To do this, click the "pull request" button from your branch like you did before, but this time, leave the original repository as the base.
Ask for your pull request to be merged
You don't have permission to modify this repository, so you'll need someone at Udacity to merge your pull request. Our helpful bot Casey may be able to merge your pull request automatically. To have your pull request automatically merged, you'll need to follow the guidelines in the README of the repository, and in addition you won't be able to delete or modify lines. That restriction on deletions is because Casey doesn't want to merge a request that accidentally deletes part of the story, and she can't tell the difference between an accidental deletion and an intentional modification. To request auto-merging, leave a comment on the pull request containing "@casey-collab". For example "Please review this, @casey-collab". Make sure to leave the comment on the "Conversation" tab of the pull request, not the "Files changed" tab.
There are some valid pull requests that Casey won't be able to merge. For example, she won't accept a pull request that fixes a typo, since that modifies a line. If you'd like to make a pull request Casey can't merge, feel free to do so, and someone from Udacity will merge the pull request if we have time. However, we can't guarantee a response to these pull requests.
If needed, update your pull request
If someone merges your pull request or leaves a comment, GitHub will email you and let you know. If you're asked to make some changes, push those changes to your fork to update the pull request. Make sure you let the reviewer know that they should take another look!
If your pull request would result in a merge conflict, and you're not sure how to resolve it, see the next video for instructions.
根據(jù)上面的指南,完成了整個(gè)練習(xí)。review一下整個(gè)流程:
- github(original): fork repo create-your-own-adventure.在我的repo里得到github (my fork): create-your-own-adventure
- local(terminal): git clone github (my fork): create-your-own-adventure。在本地得到了整個(gè)repo
- local(terminal): 在
/create-your-own-adventure/chinese/里添加了folder little_prince,在floder里添加了file:this_is_a_story_about_a_boy.md.這個(gè)path:create-your-own-adventure/Chinese/little_prince/this_is_a_story_about_a_boy.md.git checkout -b little-prince,創(chuàng)建新的branch.git add xxx+git commit -m "xxxxx", 最后git push origin little-prince - github(my fork): 有了新的branch,點(diǎn)擊comment&pull request綠色button.這一次合并請(qǐng)求的對(duì)象是github(original)里的那個(gè)master, 被合并的是github(my fork)下little-prince這個(gè)branch. 點(diǎn)擊綠色的commit pull request后
- github(original):打開(kāi)Pull request(有80+ge), 移動(dòng)到Conversation這個(gè)label下,只有在這里留言才能提醒original repo的owner去處理我的合并請(qǐng)求。在comment里留言
@casey-collab.這個(gè)是一個(gè)bot,查看你的提交是否符合規(guī)范 - local(terminal):好了,看來(lái)不符合。@casey-collab 給我反饋說(shuō)md文件里的一行太長(zhǎng),超120個(gè)字符,讓我用回車隔開(kāi)。還有一個(gè)問(wèn)題是在
chinese/language.md里應(yīng)該添加一行鏈接到我的文件,不然如果別人直接看language.md的話,是看不到的我的文件的。所以我在大話西游.md里添加了一行[little_prince](little_prince/this_is_a_story_about_a_boy.md)。(我想吐槽一句,能不能別用大話西游.md表示language.md,看了好久沒(méi)反應(yīng)過(guò)來(lái)) - local(terminal):修改完了。
git add 兩個(gè)文件_分別add,'git commit'(注釋用自帶的,自己寫(xiě)的不好),git push origin little-prince. - github(original):Pull request, 移動(dòng)到Conversation這個(gè)label下,再給
@casey-collab寫(xiě)個(gè)comment告訴他我改好了。@casey-collab告訴我好了,沒(méi)問(wèn)題了。會(huì)自動(dòng)merge pull request. 這個(gè)時(shí)候有提示,可以刪除little-prince這個(gè)branch了。 - local(terminal):
git checkout master,git merge little-prince,git push origin master. - github(original):好了,這樣在主目錄里就能看到自己添加的文件了。而github(my fork)里也會(huì)有最新的commit和文件。Over
3.13 Keeping a Fork Up-To-Date(Merge Conflicts in Pull Request)
有時(shí)候pull request會(huì)因?yàn)閙erge confilcts無(wú)法通過(guò)。比如,你fork了一個(gè)repo,你在fork repo上做了changes,但是此時(shí)original repo也有別人做了修改,所以pull request會(huì)有merge conflicts, 而且你是沒(méi)有權(quán)限修改origianl repo的。在github端使無(wú)法解決這個(gè)conflict,必須得在local解決。下面說(shuō)得更具體些:
初始狀態(tài)

然后在local做了些changes,并把這些push到了fork repo.

與此同時(shí)有人更新了original repo。所有現(xiàn)在問(wèn)題出現(xiàn)了,你想把自己的fork repo和original repo 合并,但因?yàn)楝F(xiàn)在兩個(gè)repo都有了變化,所以pull request會(huì)有merge confilct。(If there are merge conflicts between their change and your change, then your pull request will not be able to be automatically merged.)

Since there's no way to resolve merge conflicts on the GitHub site, you'll need to resolve the conflicts within the clone on your computer.
因?yàn)椴荒茉趃ithub端解決conflict, 所以必須要把conflict clone到local來(lái)解決。也就是說(shuō),一個(gè)是local的已經(jīng)有了changes的branch,這個(gè)branch和fork repo是一致的,另一個(gè)是已經(jīng)更新過(guò)的latest origial repo,我們想把后者clone到local,在local合并并解決conflict后再push就能解決問(wèn)題了。那么如果把original repo clone到local呢? 我們可以通過(guò)adding remote(這里的remote就是original repo)的方式來(lái)做到這點(diǎn)。(To do that, you'll need to get the conflicting changes from the original repository into your local repository, which you can do by adding a remote.)
但是別忘了我們已經(jīng)添加了一個(gè)remote叫origin,這個(gè)origin指向fork repo,我們需要另一個(gè)remote指向original repo。通常,這個(gè)指向original repo的remote起名為upstream。(Recall that you already have a remote set up called origin that points to your fork. But you'll still need to add a remote that points to the original repository. And many people namethis remote upstream.)
在本地fetch創(chuàng)建新的branch后,這個(gè)新的remote 的正式表示是 upstream/master。這樣就可以在本地把upstream/master和local branch合并了。(Adding and fetching the upstream remote will add branches like upstream/master into your local repository, so that you can merge the upstream branch with your local branch.)

現(xiàn)在我們舉例來(lái)說(shuō)。original repo里添加了名為Sprikler的branch,而我在本地做出的changes也全放到了名為stop drop roll的branch里。

在local,因?yàn)槲覀儼裞hanges都放在新的branch stop drop roll里了,所以我們想把master更新到original repo的最新版。git merge upstream/master master.(Since I created my change in a separate branch, I want to make my master branch the same as the master in the original repository. So, I'll run git pull upstream/master to update my master branch to the latest commit from the original repository.)


然后我們把master和stop drop roll branch(也就是我們?cè)诒镜豤hange過(guò)的branch)合并成change branch。

然后把master和change branch都推送到fork repo。(Then I'll merge the master branch into my changed branch, and I'll push both the changed branch and the master branch to my fork. I didn't need to push the master branch, but I thought it might be nice.)

quiz

實(shí)操
-
復(fù)制original repo 的https, 作為remote添加到local。
git167.png-51.2kB - 切換到master,然后用
git pull upstream master更新master
git168.png-39.8kB - 此時(shí)用
git log就能看到最新的commit了
git169.png-244.3kB - 切換到stop-drop-roll branch,也就是我們?cè)趌ocal做出了changes的branch。然后和master合并,這樣就得到了merge conflict.(記住,想要把A合并到B里,就先checkout到B,在進(jìn)行merge)
git170.png-41.8kB -
得到conflict后打開(kāi)文件,fix the conflict
git173.png-191.3kB -
git add xxxx,git commit,git push origin stop-drop-roll,記住最后是把stop-drop-roll push 到 origin,也就是fork repo,而不是original repo. 因?yàn)槟銢](méi)有權(quán)限直接推送給主倉(cāng)庫(kù)。
git175.png-57.8kB -
然后checkout到master,把master也推送到fork repo
git178.png-50.8kB -
好了,解決了conflict,回到全球同性交友網(wǎng)站,發(fā)現(xiàn)可愛(ài)的綠色button,說(shuō)明我們能merge pull request了。
git179.png-133.2kB