How to Use Git and GitHub(二)

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)。

web110.png-108.7kB
web110.png-108.7kB

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。

web111.png-176.9kB
web111.png-176.9kB

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

web113.png-171.6kB
web113.png-171.6kB

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被推送。

web114.png-145.8kB
web114.png-145.8kB

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
web116.png-75.9kB
web116.png-75.9kB

我自己嘗試推送的時(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
web119.png-95.1kB
web119.png-95.1kB

命令行提示輸入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)信息。

web120.png-31.3kB
web120.png-31.3kB

我們?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)


web121.png-144.8kB
web121.png-144.8kB

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

web122.png-166.8kB
web122.png-166.8kB

在terminal端的操.git pull后還是要two argus, 一個(gè)是remote name, 一個(gè)是本地的branch name.

git pull origin master

pull之后,branch也會(huì)checkout到最新的commit狀態(tài)。

web123.png-65.2kB
web123.png-65.2kB

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.

web124.png-355.8kB
web124.png-355.8kB

3.7 Forking a Repository

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

git91.png-682.4kB
git91.png-682.4kB

quiz

git92.png-130.3kB
git92.png-130.3kB

左上,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.


git94.png-78.6kB
git94.png-78.6kB

其實(shí)我們想merge local and remote branches.

3.8.1 Change the Chili Recipe Quiz

最上面的commit是另一個(gè)人提交的。


git97.png-120kB
git97.png-120kB

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

git98.png-158.6kB
git98.png-158.6kB

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)


git100.png-84.9kB
git100.png-84.9kB

push后,全部更到最新。


git101.png-121.3kB
git101.png-121.3kB

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


git102.png-115.6kB
git102.png-115.6kB

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

git104.png-127.8kB
git104.png-127.8kB

也就是說(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做我的修改。

git105.png-128.9kB
git105.png-128.9kB

但如果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

git106.png-445.4kB
git106.png-445.4kB

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。

git110.png-64.1kB
git110.png-64.1kB

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

git111.png-32.8kB
git111.png-32.8kB

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

git112.png-18.8kB
git112.png-18.8kB

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


git113.png-29.1kB
git113.png-29.1kB

我要保留github 段做出的修改


git115.png-22.7kB
git115.png-22.7kB

修改完后,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)確方便。

git114.png-13.9kB
git114.png-13.9kB

通過(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)

git117.png-89.9kB
git117.png-89.9kB

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

git118.png-93kB
git118.png-93kB

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

git119.png-66kB
git119.png-66kB

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

git120.png-131kB
git120.png-131kB

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。

  1. 我先在本地修改了cask-recipe.txt里的配方,添加了一種更健康的oil.
  2. 創(chuàng)建一個(gè)branch,叫different oil.git branch different-oil+ git checkout different-oil 或者用一個(gè)命令git checkout -b different-oil.
  3. git add cask-recipe.txt + git commit + git push origin different-oil. 這樣就把branch different-oil 推送到了github端。接下在就能在github端查看了。
    git121.png-127.6kB
    git121.png-127.6kB
  4. 切換到branch different-oil,查看commit
    git122.png-141.5kB
    git122.png-141.5kB
  5. 我們向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
    git123.png-102.5kB
  6. 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)求。
  7. 現(xiàn)在在pull request里可以看到我們做出的所有commit,修改。其他的人可以在主頁(yè)面右側(cè)的list里有pull request,可以點(diǎn)擊查看。
    git124.png-82.5kB
    git124.png-82.5kB
  8. 好了,接下來(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.
  9. 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
    git126.png-155.6kB
  10. 如果檢查后一切正常,可以點(diǎn)擊merge pull request button. 這個(gè)button只有在沒(méi)有conflict的時(shí)候才會(huì)
    git127.png-130.3kB
    git127.png-130.3kB
  11. 在有conflict的情況下,先讓Caroline fix the conflict。讓Caroline合并master和different-oil,成功后說(shuō)明沒(méi)有什么問(wèn)題,之后再同一merge.

quiz

git129.png-550kB
git129.png-550kB

3.9.4 Updating a Pull Request

  1. 上一節(jié)里Sarah發(fā)現(xiàn)了pull request 里有spell error,所以寫(xiě)了個(gè)comment。接著Caroline收到了郵件,里面寫(xiě)著comment的內(nèi)容。
  2. Caroline在local檢查了下文件,發(fā)現(xiàn)全是寫(xiě)錯(cuò)了,于是fix,然后commit the fix。
    git130.png-67.3kB
    git130.png-67.3kB

    git131.png-179.7kB
    git131.png-179.7kB
  3. git push origin different-oil,這樣github端也能看到修改了。
    git132.png-62.5kB
    git132.png-62.5kB
  4. push branch自動(dòng)出現(xiàn)在pull request界面,在Sarah的comment下面,能看到Caroline的commit:Fix type in caola.
    git133.png-120kB
    git133.png-120kB
  5. 現(xiàn)在commit顯示為2,file changed顯示1,可以點(diǎn)擊file changed查看修改。
    git136.png-99kB
    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,


git137.png-119.3kB
git137.png-119.3kB

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.


git138.png-350.7kB
git138.png-350.7kB

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

git139.png-393.8kB
git139.png-393.8kB

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

git140.png-257kB
git140.png-257kB

回到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.

git141.png-88.4kB
git141.png-88.4kB

解決方法: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。

git142.png-493.4kB
git142.png-493.4kB

我們把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.

git143.png-476.6kB
git143.png-476.6kB

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更新本地到最新版本。

git144.png-561.1kB
git144.png-561.1kB

好了,現(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里,然后合并masterdifferent-oil, 再push different-oil,github那邊會(huì)自動(dòng)更新 pull request. 注意,別把different-oil合并到master,然后推送master,這會(huì)直接覆蓋,別人沒(méi)有機(jī)會(huì)在merge前review。

git145.png-600.1kB
git145.png-600.1kB

3.9.6 Updating Your Local Repository

上一節(jié)講了各種原理,這一節(jié)講在terminal端的具體命令操作。

git pull origin master更新local. 也可以用git fetch + git merge origin master.

git146.png-91.3kB
git146.png-91.3kB

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

git147.png-92.2kB
git147.png-92.2kB


下面是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.

git148.png-178.7kB
git148.png-178.7kB

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

git149.png-521kB
git149.png-521kB

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

git150.png-406.6kB
git150.png-406.6kB

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

git151.png-117kB
git151.png-117kB

quiz

git152.png-73.8kB
git152.png-73.8kB

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

git154.png-539.1kB
git154.png-539.1kB
git156.png-514.3kB
git156.png-514.3kB

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è)流程:

  1. github(original): fork repo create-your-own-adventure.在我的repo里得到github (my fork): create-your-own-adventure
  2. local(terminal): git clone github (my fork): create-your-own-adventure。在本地得到了整個(gè)repo
  3. 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
  4. 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
  5. 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ī)范
  6. 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))
  7. local(terminal):修改完了。 git add 兩個(gè)文件_分別add,'git commit'(注釋用自帶的,自己寫(xiě)的不好),git push origin little-prince.
  8. 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了。
  9. local(terminal): git checkout master, git merge little-prince, git push origin master.
  10. 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)


git157.png-113.2kB
git157.png-113.2kB

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


git157.png-113.2kB
git157.png-113.2kB

與此同時(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.)


git159.png-110.4kB
git159.png-110.4kB

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.)


git160.png-331.6kB
git160.png-331.6kB

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

git161.png-136.3kB
git161.png-136.3kB

在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.)

git161.png-136.3kB
git161.png-136.3kB

git162.png-43.8kB
git162.png-43.8kB

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

git163.png-45.5kB
git163.png-45.5kB

然后把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.)


git164.png-163.5kB
git164.png-163.5kB

quiz

git165.png-101kB
git165.png-101kB

實(shí)操

  1. 復(fù)制original repo 的https, 作為remote添加到local。
    git167.png-51.2kB
    git167.png-51.2kB
  2. 切換到master,然后用git pull upstream master更新master
    git168.png-39.8kB
    git168.png-39.8kB
  3. 此時(shí)用git log就能看到最新的commit了
    git169.png-244.3kB
    git169.png-244.3kB
  4. 切換到stop-drop-roll branch,也就是我們?cè)趌ocal做出了changes的branch。然后和master合并,這樣就得到了merge conflict.(記住,想要把A合并到B里,就先checkout到B,在進(jìn)行merge)
    git170.png-41.8kB
    git170.png-41.8kB
  5. 得到conflict后打開(kāi)文件,fix the conflict
    git173.png-191.3kB
    git173.png-191.3kB
  6. 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
    git175.png-57.8kB
  7. 然后checkout到master,把master也推送到fork repo
    git178.png-50.8kB
    git178.png-50.8kB
  8. 好了,解決了conflict,回到全球同性交友網(wǎng)站,發(fā)現(xiàn)可愛(ài)的綠色button,說(shuō)明我們能merge pull request了。
    git179.png-133.2kB
    git179.png-133.2kB
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 因?yàn)樵奶L(zhǎng)超出字?jǐn)?shù),Lesson 3 就放在另一篇文章里 How to Use Git and GitHub 標(biāo)...
    赤樂(lè)君閱讀 5,507評(píng)論 1 5
  • origin websiteComparing WorkflowsCentralized Workflow Fea...
    伍帆閱讀 576評(píng)論 0 0
  • 我從來(lái)都沒(méi)有感覺(jué)自己有愛(ài)你, 你準(zhǔn)備離開(kāi)的當(dāng)天天。 平時(shí)賣火腿腸的老奶奶問(wèn):那個(gè)男孩子呢。 我開(kāi)心說(shuō):奶奶你好久都...
    馬櫻佳閱讀 528評(píng)論 0 1
  • 喜歡寫(xiě)字,從十幾歲開(kāi)始。那時(shí),第一次離開(kāi)家,去很遠(yuǎn)的城市。陌生的環(huán)境,陌生的人,內(nèi)心的孤獨(dú),讓性情安靜的我更孤僻。...
    微笑的小魚(yú)閱讀 375評(píng)論 0 0
  • 推薦一個(gè)正則表達(dá)式的開(kāi)源測(cè)試工具 接下來(lái)的demo都會(huì)使用這個(gè)工具進(jìn)行測(cè)試: https://github.co...
    螞蟻牙齒不黑閱讀 742評(píng)論 0 0

友情鏈接更多精彩內(nèi)容