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掉, 通过commit history记录下来。

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

github repo里没有working directory and staing area, 因为github repo 是在远程的,并不能直接连接,所以没有。github不会像其他service一样sync with cloud,比如CMD markdown就是,我现在敲击的每一句话都会立刻与云端同步。而且正因为能自动同步到云端,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里用过的git clone.但这个命令只能从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.
我们在之后的课程里再详细讲这个remote repository

假设我们现在已经有了remote repo指向github上的repo(见图中arrow), you can pull data and push data. 我们不是一个一个的commit推送,而是选定一个branch, git push后,就能把这个branch下的所有commit同步到remote repo。

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

但是想象一些,如果branch里有上百个commit,每次push都要把所有commit推送的话是件很低效的事。

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

git的做法很聪明,只提交“有用的”branch。比如下图中local有4个branch, github里只有一个branch. 现在我要推送local 里的a, 即e53,github会找到这个e53的所有parent和children。并只推送github中没有的branch. 而664因为unreachable,所以不会被推送。所以结果只有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可以在创建好的github repo里找到,初始化不带。

git remote add origin https://github.com/user_name/reflections.git
web116.png-75.9kB
web116.png-75.9kB

我自己尝试推送的时候得到了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).

发现这个reflections derectory根本没有初始化。

初始化以及准备工作: git init, git add xxx.txt,git commit -m "add xxx.txt.

好了,创建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官网上看到相应的文件了。
推送后,github默认会创建相同的branch name,即github上的branch也叫master。

3.4 Editing Files on GitHub

点击commit button,可查看commit history. 点击new fiel创建一个新文件。填写文件名,文件内容,commit message等相关信息。

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

我们在github直接创建一个文件,比如collebrate的时候别人也会上传一些commit,而我们的本地主机没有相关文件。下一节练习如何得到最新的version。

3.5 Pulling Changes

这是我们现在的状态


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

利用git pull来获得最新的commit

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

在terminal端的操.git pull后还是要two argus, 一个是remote name, 一个是本地的branch name.

git pull origin master

pull之后,branch也会checkout到最新的commit状态。

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,通过fork,会在自己的github账户中创建一个相同的repo。而Caroline和Sarah可以对右上的repo做出各种修改,制作自己喜欢的recipe,个人定制化。

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,点击github页面右上的fork,这样你的账户里就有一样的repo了。跳转页面到你账户里的repo,找到右下的https赋值。在本地git clone https//XXX就能得到local repo. 如果是通过这种方式,我们就不用自己添加remote了,git会自动添加remote. 不信的话运行git remote -v查看详情。

我想让Larry和我一起collaborate这个repo,在右下的setting里添加collaborator,输入对方的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,都会有confilict.


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

其实我们想merge local and remote branches.

3.8.1 Change the Chili Recipe Quiz

最上面的commit是另一个人提交的。


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

因为两个人都对同一个文件的同一行做出了改动,github会高亮标识,提示有confilct

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

3.9 Updating Local Copies of Remote Branches

我对一个Chili Recipe里做了改动后(包括add, commit),本地的master已经最新了,但是remote branch还没有更新。而remote branch的name就是origin/master,通过git push后,才能让branch master和origin/master同步。不信的话先别push,git diff origin/master master (git diff old_one new_one), 可以看到二者之间的差别。

图中本地的origin/master和github的master都是未更新状态,只有local的master有改动,是latest.(注:origin和origin/master是一个branch)


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

push后,全部更到最新。


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

如果现在local和github repo都改变了


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

我们可以通过git fetch只更新local, 即让origin/master和github repo(remote)同步,而让local的master被保留。

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

也就是说,local现在有两个branch,一个是master,一个是和remote github端同步了的origin/master. 比如说现在我要上飞机,但我本地已经有了最新的version,这个时候我可以merge这两个branch。但我也可以不着急merge二者,继续在master做我的修改。

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

但如果merge了的话,其实相当于用了git pull。因为pull的流程也是先更新(fetch)本地的remote branch origin/master,然后再把origin/master和local的master 合并(merge).
所以说,git pull = git fetch + git merge

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

3.9.1 Merging the Changes Together

实操:command line
现在的状态是github remote段写了两个commit,local段写了一个commit.

可以用git branch -a看到remote branch. 用git fetch origin把本地的origin/master更到和github remote端一样新。git log orgin可以查看origin/master的所有commit,现在这个branch的commit已经完全和github端一样了,git log查看的是local的master。

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

git status可以看到当前的状态,提示说origin/master和local的master有不同的commit进度

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

git merge master origin/master,理所当然得得到了conflict提示,因为两个branch的commit history不一样

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

好了,打开有问题的文件,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这一次没有加message,但是竟然跳出了nano的编辑界面,自动写好了message. Ctrl+X, 选yes, alt+D选择DOS-format,即可保存message。果然还是自动的填写的信息更准确方便。

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

通过commit之后,这次merge也就算成功了。当然,也可以直接git pull.
git push origin master,顺序不能错,必须是git push remote_branch local_branch. push后就能在github看到所有的commit了。

3.9.2 Fast-Forward Merges

既然git pull = git fetch + git merge,那为什么在上一节的例子里,直接用git pull的时候没有generated merge commit like git fetch + git merge did.

因为启动了fast-forward merges. This kind of merge occurs when you merge two commits, where one is ancestor of the other. (一个commit是另一个commit的祖先,这里的commit也可以理解为branch)

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

如果想把上图中的a和b合并,其实没有必要创建一个新的commit。想想也知道新的commit也会有二者共同的commit history, 那么创建一个新的commit就没有必要了。

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

其实这里的pull并不是git pull里的意思,而是我打算在github段合并两个branch,这个合并的申请叫做 pull request, github非要这么设定,只能顺势而为了。

现在做一个example,展示整个workflow。

  1. 我先在本地修改了cask-recipe.txt里的配方,添加了一种更健康的oil.
  2. 创建一个branch,叫different oil.git branch different-oil+ git checkout different-oil 或者用一个命令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, 点击pull request button(如果绿色的那个button没出现的话就在branch different-oil里点pull request button,如图)
    git123.png-102.5kB
    git123.png-102.5kB
  6. github默认会认为你想要和原版的Larry的master合并,但是我们只是想把branch different-oil和master合并而已。点击右侧的edit,选择要合并的branch。再点击右下的create pull request. 这样我们就发出了请求。
  7. 现在在pull request里可以看到我们做出的所有commit,修改。其他的人可以在主页面右侧的list里有pull request,可以点击查看。
    git124.png-82.5kB
    git124.png-82.5kB
  8. 好了,接下来是另一个contributor的视角了,也就是Sarah.因为Sarah watching Caroline's fork of the recipes repository, 所有Sarah got an email notifying that Caroline made a pull request. 点击邮件里的地址,查看pull request.
  9. Caroline想让sarah同意合并maser和different-oil。因为master是最主要的branch,所以必须保证没有错误。Sarah查看了Caroline做出的修改,但是添加的那个oil有拼写错误。所以Sarah在下面的写一个comment,提醒Caroline发现的问题。也可以在上面出错的地方写一个inline comment
    git126.png-155.6kB
    git126.png-155.6kB
  10. 如果检查后一切正常,可以点击merge pull request button. 这个button只有在没有conflict的时候才会
    git127.png-130.3kB
    git127.png-130.3kB
  11. 在有conflict的情况下,先让Caroline fix the conflict。让Caroline合并master和different-oil,成功后说明没有什么问题,之后再同一merge.

quiz

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

3.9.4 Updating a Pull Request

  1. 上一节里Sarah发现了pull request 里有spell error,所以写了个comment。接着Caroline收到了邮件,里面写着comment的内容。
  2. Caroline在local检查了下文件,发现全是写错了,于是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自动出现在pull request界面,在Sarah的comment下面,能看到Caroline的commit:Fix type in caola.
    git133.png-120kB
    git133.png-120kB
  5. 现在commit显示为2,file changed显示1,可以点击file changed查看修改。
    git136.png-99kB
    git136.png-99kB

3.9.5 Conflicting Changes

前一节我们学会了如何pull request,这一节我们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认定是一个merge conflict,二人中的一个得负责fix it.


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

点击左上的conversatoin button,先点击绿色的merge pull request, 再点击绿色的Confirm merge, 即先confirm Sarah的changes,然后再去resolve merging conflict。

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

Confirm后就可以删除sarah创建的more-oil branch 了。

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

回到pull request 界面,发现无法merge的消息提醒。This is because performing a merge between the master branch and my branch would now cause merge conflicts. 之前的Sarah的修改已经提前改变了master里的cake-recipes.txt里的oil那一行,而Caraline在自己的branch里也是修改的同一行,所以无法合并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.
也就是说github不让你通过browser更改,必须要在local fix conflict, merge suffessfullly, then git push to update the merged version.

图解

初始状态:左图是local version,master在中间,Craline做出的changes全在新的branch different-oil里。右图是github version. 可以看到中间是master,但是从master开始,向右有两个branch就有差异了。一个右上角Sarah做出修改的branch more-oil,一个是右下角Craline做出的changes的branch different-oil。

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

我们把master和Sarah的more-oil branch合并。这其实本来是个fast forward merge, 也就是说master的lable会移动到more-oil上,并不会创建一个新的commit。但是github的merge机制不一样,只要是github页面上的merge button,点击后merge后就一定会有一个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上。现在就可以删除more-oil这个branch了,因为一旦合并它的使命也就完成了。所以在图中把右上角的more-oil这个branch name 移去。现在Craaline想要把自己的branch和master合并,但因为两个人都对同一line做除了改动,所以有conlict. 现在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

好了,现在Caraline可以直接fix conflict,merge master and different-oil, git push, 这样github段的master就能更新了。但是!!!这么做的话其他人没有机会看到Caraline做出的修改,也没有机会提醒修改是否合理。尤其是在collaboration的环境下,必须要让别人review,所以要通过github的pull request功能来提交,这样其他人就能得到通知,来查看修改是否正确了。

具体的做法: 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.
也就是说把所有改动放在different-oil里,然后合并masterdifferent-oil, 再push different-oil,github那边会自动更新 pull request. 注意,别把different-oil合并到master,然后推送master,这会直接覆盖,别人没有机会在merge前review。

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

3.9.6 Updating Your Local Repository

上一节讲了各种原理,这一节讲在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.
这下两个人的修改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

在点击绿色的Merge pull request前,先写个comment通知Sarah让她来review.因为updata the pull request的消息是不会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?

因为通过创建不同的branch来添加新的feature更易于和别人合作,每个人都更易于理解project的branch结构,user friendly. 通过pull request来merge,也能让别人review。

3.12 Modifying the Adventure Repository (实操练习)

以下是指南部分,主要是fork这个repo,来进行练习。
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.


根据上面的指南,完成了整个练习。review一下整个流程:

  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。在本地得到了整个repo
  3. local(terminal): 在/create-your-own-adventure/chinese/里添加了folder little_prince,在floder里添加了file:this_is_a_story_about_a_boy.md.这个path: create-your-own-adventure/Chinese/little_prince/this_is_a_story_about_a_boy.md. git checkout -b little-prince,创建新的branch. git add xxx+git commit -m "xxxxx", 最后git push origin little-prince
  4. github(my fork): 有了新的branch,点击comment&pull request绿色button.这一次合并请求的对象是github(original)里的那个master, 被合并的是github(my fork)下little-prince这个branch. 点击绿色的commit pull request
  5. github(original):打开Pull request(有80+ge), 移动到Conversation这个label下,只有在这里留言才能提醒original repo的owner去处理我的合并请求。在comment里留言@casey-collab.这个是一个bot,查看你的提交是否符合规范
  6. local(terminal):好了,看来不符合。@casey-collab 给我反馈说md文件里的一行太长,超120个字符,让我用回车隔开。还有一个问题是在chinese/language.md里应该添加一行链接到我的文件,不然如果别人直接看language.md的话,是看不到的我的文件的。所以我在大话西游.md里添加了一行[little_prince](little_prince/this_is_a_story_about_a_boy.md)。(我想吐槽一句,能不能别用大话西游.md表示language.md,看了好久没反应过来)
  7. local(terminal):修改完了。 git add 两个文件_分别add,'git commit'(注释用自带的,自己写的不好),git push origin little-prince.
  8. github(original):Pull request, 移动到Conversation这个label下,再给@casey-collab写个comment告诉他我改好了。@casey-collab告诉我好了,没问题了。会自动merge pull request. 这个时候有提示,可以删除little-prince这个branch了。
  9. local(terminal): git checkout master, git merge little-prince, git push origin master.
  10. github(original):好了,这样在主目录里就能看到自己添加的文件了。而github(my fork)里也会有最新的commit和文件。Over

3.13 Keeping a Fork Up-To-Date(Merge Conflicts in Pull Request)

有时候pull request会因为merge confilcts无法通过。比如,你fork了一个repo,你在fork repo上做了changes,但是此时original repo也有别人做了修改,所以pull request会有merge conflicts, 而且你是没有权限修改origianl repo的。在github端使无法解决这个conflict,必须得在local解决。下面说得更具体些:

初始状态


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

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


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

与此同时有人更新了original repo。所有现在问题出现了,你想把自己的fork repo和original repo 合并,但因为现在两个repo都有了变化,所以pull request会有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.
因为不能在github端解决conflict, 所以必须要把conflict clone到local来解决。也就是说,一个是local的已经有了changes的branch,这个branch和fork repo是一致的,另一个是已经更新过的latest origial repo,我们想把后者clone到local,在local合并并解决conflict后再push就能解决问题了。那么如果把original repo clone到local呢? 我们可以通过adding remote(这里的remote就是original repo)的方式来做到这点。(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.)

但是别忘了我们已经添加了一个remote叫origin,这个origin指向fork repo,我们需要另一个remote指向original repo。通常,这个指向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创建新的branch后,这个新的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

现在我们举例来说。original repo里添加了名为Sprikler的branch,而我在本地做出的changes也全放到了名为stop drop roll的branch里。

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

在local,因为我们把changes都放在新的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(也就是我们在本地change过的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

实操

  1. 复制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. 此时用git log就能看到最新的commit了
    git169.png-244.3kB
    git169.png-244.3kB
  4. 切换到stop-drop-roll branch,也就是我们在local做出了changes的branch。然后和master合并,这样就得到了merge conflict.(记住,想要把A合并到B里,就先checkout到B,在进行merge)
    git170.png-41.8kB
    git170.png-41.8kB
  5. 得到conflict后打开文件,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. 因为你没有权限直接推送给主仓库。
    git175.png-57.8kB
    git175.png-57.8kB
  7. 然后checkout到master,把master也推送到fork repo
    git178.png-50.8kB
    git178.png-50.8kB
  8. 好了,解决了conflict,回到全球同性交友网站,发现可爱的绿色button,说明我们能merge pull request了。
    git179.png-133.2kB
    git179.png-133.2kB

推荐阅读更多精彩内容

  • 因为原文太长超出字数,Lesson 3 就放在另一篇文章里 How to Use Git and GitHub 标...
    赤乐君阅读 2,778评论 0 4
  • origin websiteComparing WorkflowsCentralized Workflow Fea...
    伍帆阅读 163评论 0 0
  • 今天第一天开始上班,没有任务,于是开始学习Git这一程序猿必须掌握之技能,希望今天的积累过后,对与Git或者...
    CoderTung阅读 5,500评论 2 92
  • 我从来都没有感觉自己有爱你, 你准备离开的当天天。 平时卖火腿肠的老奶奶问:那个男孩子呢。 我开心说:奶奶你好久都...
    马樱佳阅读 54评论 0 1
  • 喜欢写字,从十几岁开始。那时,第一次离开家,去很远的城市。陌生的环境,陌生的人,内心的孤独,让性情安静的我更孤僻。...
    微笑的小鱼阅读 30评论 0 0