我们知道 Git 储存库并没有什麽「权限控管」的概念,因为他是分散式的版本控管系统,当你执行 git clone
之后就会把整份拥有完整版本历史的储存库下载回来,接著你就可以在本地离线的进行开发与建立版本,最后再将变更推送到远端储存库。不过,如果我们只有一份远端储存库的话,这代表大家都有权限将变更推送到远端储存库。因此,GitHub 採用了 forks 与 pull request 的流程,让你可以做到基本的权限控管。
在 GitHub 的个人帐户下,并没有甚麽权限控管的机制,所以只要你授权特定人为协同开发人员 (Collaborators),他就能自由的 Push 与 Pull 专案原始码。
我以我之前在 GitHub 上建立的某个专案为例,专案网址:https://github.com/doggy8088/DataDictionaryCreator
进入该网址后,点选右侧选单的 Settings 链接进入:
然后就可以加入授权的协同开发人员,这裡要输入的是对方在 GitHub 上的帐号:
设定成功的图示如下:
但由于你没办法设定更细的 Git 远端储存库权限,所以只要被指派的人,就能够存取完整的 Git 远端储存库,大家都能对任意分支进行推送 (Push)、拉取 (Pull) 或删除分支等动作,要是团队遇上天兵,那可能会是场灾难。
在 GitHub 的组织帐户下,就可以设定人员群组(Teams),你就可以在群组上设定更细的权限,其中包括三种权限:
设定群组的方法如下:
然后选择团队:
你也可以点选进入组织设定页面,进一步的来挑选团队成员:
英文的 Fork 字面翻译是「叉子」的意思,就好像你刀叉去把食物「叉」起来一样,直接把菜挪放到你自己的盘子裡,我比喻的「菜」就是你要複製的 GitHub 专案,而「盘子」就是你的 GitHub 帐号。
注:老外用刀叉比较多,如果 GitHub 是台湾发展的,这个单字可能会是 Chopsticks (筷子),哈! XD
现在我们以 https://github.com/doggy8088/DataDictionaryCreator 为例,这个专案,你当然没有「写入」权限,只有「唯读」而已。
我现在登入另外一个 GitHub 帐号 ( LearnGitForks
),然后将该专案「叉」到这个帐户自己 GitHub 帐号下:
按下去之后,他骨子裡其实就是使用 git clone
来複製该专案到你的 GitHub 帐号下,估计只要十几秒钟就会複製完成,看你複製的专案大小:
完成后,在你自己的帐号下,就会有个完全一样的 Git 专案被建立,但会在名称下显示一段 forked from
提示你该专案是来从哪裡複製过来的。
因为该专案已经在你自己的帐号下,所以此时你已经可以把该专案当成「自己的远端储存库」在用,完全没有读写权限的问题。
因为 Git 是个分散式版本控管系统,只要你有 fetch 的权限,基本上就可以抓到该版本库的完整版本变更历程。
在版本控管方面,使用上几乎跟用自己的 Git 远端储存库没什麽两样,而且你也有完整的历史纪录。请记得这份资料是从 https://github.com/doggy8088/DataDictionaryCreator 複製过来的就好。
我们先取得远端储存库回来:
C:\>git clone git@github.com:LearnGitForks/DataDictionaryCreator.git
Cloning into 'DataDictionaryCreator'...
remote: Counting objects: 57, done.
remote: Compressing objects: 100% (45/45), done.
Receiving objects: 71% (41/57), 36.00 KiB | 42.00 KiB/s
Receiving objects: 100% (57/57), 94.08 KiB | 42.00 KiB/s, done.
Resolving deltas: 100% (12/12), done.
C:\>cd DataDictionaryCreator
C:\DataDictionaryCreator>
然后我们建立起一个版本,然后把变更推送回去:
C:\DataDictionaryCreator>echo TEST > test.md
C:\DataDictionaryCreator>git add .
C:\DataDictionaryCreator>git commit -m "Add a test.md for test purpose"
[master b2004b0] Add a test.md for test purpose
1 file changed, 1 insertion(+)
create mode 100644 test.md
C:\DataDictionaryCreator>git push
Counting objects: 4, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 285 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To git@github.com:LearnGitForks/DataDictionaryCreator.git
c29aaab..b2004b0 master -> master
C:\DataDictionaryCreator>
刚刚我们用 LearnGitForks
身分,把专案从 doggy8088
这边 Fork 回来,然后用 LearnGitForks
的身分 git clone
回本地端,建立版本后再用 git push
推回 GitHub 的 LearnGitForks
下。
现在我们要把储存在 LearnGitForks
帐号下的 DataDictionaryCreator
专案「合併」回 doggy8088
帐号下的 DataDictionaryCreator
专案,这时因为是跨帐号的,所以必须利用 pull request
才能把变更「合併」回去。
注:这裡的 pull request 照字面翻译是「拉取要求」的意思,代表要以 LearnGitForks
的身分,请 doggy8088
把我的变更给拉回去 (git pull
),但你不能强迫对方拉(pull
),所以必须拜託(request
)对方拉,所以才叫做 pull request。
这时,你要用 LearnGitForks
的身分,连到 https://github.com/doggy8088/DataDictionaryCreator
这一页,然后点选 Pull Requests 页籤:
然后点选 New pull request
按钮,准备建立一个新的 pull request 项目:
接下来你要选择两个版本 (两个 commit 物件),GitHub 才能建立 patch 档案,也才能知道要合併那些东西回去。但你选不到自己 fork 过的版本,因此你要点选 compare across forks
然后你就可以选择到自己 fork 过的专案与分支了!不过,这一步要特别注意不要选错,你的版本因为比较新,所以应该要把右边的版本选择成你的,GitHub 才知道从 doggy8088/DataDictionaryCreator
的 master
分支,到 LearnGitForks/DataDictionaryCreator
的 master
分支,到底发生了那些版本变化。
最后你会看到有哪些档案以及哪些地方变更了,然后你就可以按下 Click to create a pull request for this comparison 建立起一个 pull request:
最后,我们先看一下右上角有个 Able to merge 的地方,会预先告诉你合併的结果,显示你的版本跟目前的 doggy8088:master
的版本是否有衝突发生。如果都没问题,再输入一些说明文字给原作者 ( doggy8088
) ,并按下 Send pull request
即可建立完成。
注 Github for Mac;Github for Windows 已增加pull request功能
最后一个步骤,则是让原作者 ( doggy8088
) 去看有谁传送了一个 pull request 给自己。
现在我重新以 doggy8088
登入 GitHub,并到该专案发现有一个 Pull Requests 进来了:
点击进去:
最后按下 Merge pull request 即可完成合併工作。
做到这裡,你应该大致能够了解为什麽会有 fork 与 pull request 的存在,最主要的就是「权限」以及「版本库隔离」的需求。一个上千人的专案 (Linux Kernel
),如果所有人都能存取主要的远端储存库,那不是很恐怖吗!
不过在一般企业裡,你不一定要这样做,毕竟操作的步骤确实繁琐了些。实际要怎麽用,就要靠你自己判断了。