創建版本庫:
1.初始化一個Git倉庫,使用git init命令。
2.添加文件到Git倉庫,分兩步:
(1)使用命令git add <file>
添加文件到暫存區,注意,可反復多次使用,添加多個文件;
(2)使用命令git commit -m "message"
完成本地版本庫的提交。
時光穿梭:
?要隨時掌握工作區的狀態,使用git status命令。
?如果git status告訴你有文件被修改過,用git diff可以查看修改內容。
版本回退:
1.HEAD指向的版本就是當前版本,因此,Git允許我們在版本的歷史之間穿梭,使用命令:
git reset --hard commit_id或HEAD^或HEAD~Num
2.穿梭前,用git log可以查看提交歷史,以便確定要回退到哪個版本。
3.要重返未來,用git reflog查看命令歷史,以便確定要回到未來的哪個版本。
工作區、暫存區和分支
1.利用git status命令可以查看當前目錄(也就是工作區)的狀態(哪些文件被修改,新添加,有無提交等信息)。
2.利用git add <file>命令可以將file由工作區添加到暫存區Stage。
3.利用git commit命令可以將所有暫存區的文件一次性添加到分支master(缺省分支名)中去。
管理修改:
每次修改,如果不用git add到暫存區,那就不會加入到commit中。
場景1:當你改亂了工作區某個文件的內容,想直接丟棄工作區的修改時,用命令
git checkout --file。
場景2:當你不但改亂了工作區某個文件的內容,還添加到了暫存區時,想丟棄修改,分兩步:
第一步:用命令git reset HEAD <file>,就回到了場景1;
第二步:按場景1操作。
場景3:已經提交了不合適的修改到版本庫時,想要撤銷本次提交,git reset --hard HEAD^,不過前提是沒有推送到遠程庫。
刪除文件:
命令git rm用于刪除一個文件。
如果一個文件已經被提交到版本庫,那么你永遠不用擔心誤刪,但是要小心,你只能恢復文件到最新版本,你會丟失最近一次提交后你修改的內容。
遠程倉庫:
在連接遠程倉庫(自己公司創建的內部git服務器,或是github)上提交自己電腦終端的ssh公鑰
ssh-keygen -t rsa -C "youremail@163.com"
一、先有本地庫,后有遠程庫的時候,如何關聯遠程庫:
1)要關聯一個遠程庫,在本地git庫中使用以下命令與遠程庫repo-name相關聯;
git remote add origin git@server-name:path/repo-name.git
2)關聯后,使用以下命令第一次推送master分支的所有內容;
git push -u origin master
3)此后,每次本地提交后,只要有必要就可以使用以下命令推送最新修改:
git push origin master
分布式版本系統的最大好處之一是在本地工作完全不需要考慮遠程庫的存在,也就是有沒有聯網都可以正常工作,而SVN在沒有聯網的時候是拒絕干活的!當有網絡的時候,再把本地提交推送一下就完成了同步,真是太方便了!
二、先創建遠程庫,然后從遠程庫克隆
要克隆一個倉庫,首先必須知道倉庫的地址,然后使用git clone命令克隆。
ssh協議:
git clone git@github.com:username/reponame.git
https協議:
git clone https://github.com/username/reponame.git
克隆完了之后,本地和遠端倉庫便自動關聯了。Git支持多種協議,包括https,但通過ssh支持的原生git協議速度最快。
創建與合并分支:
一般來說,
master是本地默認的分支名,他指向當前最新提交;
HEAD指向一個分支,而且是當前的工作分支。
也即:HEAD --> master --> commit鏈
所謂創建分支就是創建一個指向commit鏈的指針變量
所謂切換當前分支就是對HEAD重新賦值,使之指向不同的分支指針變量.
查看分支:git branch
創建分支:git branch <name>
刪除分支:git branch -d <name>
切換分支:git checkout <name>
創建+切換分支:git checkout -b <name>
合并某分支到當前分支:git merge <name>
此時,默認為快速合并(fast forward),僅僅將master指針指向待合并的分支,不創建新的提交;當使用快速合并出現沖突時,就要采用
git merge --no-ff <name>
此時,將會建立一個新的提交,并將master指向該新提交
解決沖突:
當Git無法自動合并分支時,就必須首先解決沖突。解決沖突后,再提交,合并完成。 解決沖突就是把Git合并失敗的文件手動編輯為我們希望的內容,再提交。
用git status
查看沖突的文件;
用以下命令可以看到分支合并圖:
gitlog --graph --pretty=oneline --abbrev -commit
分支管理策略:
在實際開發中,我們應該按照幾個基本原則進行分支管理:
首先,master分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面干活; 那在哪干活呢?
干活都在dev分支上,也就是說,dev分支是不穩定的,到某個時候,比如1.0版本發布時,再把dev分支合并到master上,在master分支發布1.0版本;
你和你的小伙伴們每個人都在dev分支上干活,每個人都有自己的分支,時不時地往dev分支上合并就可以了。
合并分支時,加上--no-ff參數就可以用普通模式合并,合并后的歷史有分支,能看出來曾經做過合并,而fast forward合并就看不出來曾經做過合并。
Bug分支:
修復bug時,我們會通過創建新的bug分支進行修復,然后合并,最后刪除;
當手頭工作沒有完成時,先把工作現場git stash一下,然后去修復bug。
修復后,用git stash list 查看緩存的左右工作現場;
用git stash pop恢復到最近的工作現場,并同時刪除緩存文件;
或用
git stash apply stash@{num}
恢復到指定的工作現場,但需利用git stash drop
手動刪除緩存文件。
Feature分支:
開發一個新feature,最好新建一個分支;開發調試完畢后再合并到dev分支上去。
如果要丟棄一個沒有被合并過的分支,可以通過git branch -D <name>強行刪除。
多人協作:
當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,并且,遠程倉庫的默認名稱是origin。
?查看遠程庫信息,使用git remote -v
;
?本地新建的分支如果不推送到遠程,對其他人就是不可見的;
?從本地推送分支,使用
git push origin branch-name
如果推送失敗,先用git pull抓取遠程的新提交;
?在本地創建和遠程分支對應的分支,使用
git checkout -b branch-name origin/branch-name
本地和遠程分支的名稱最好一致;
?建立本地分支和遠程分支的關聯,使用
git branch --set-upstream branch-name origin/branch-name;
?從遠程抓取分支,使用git pull,如果有沖突,要先處理沖突。
多人協作的工作模式通常是這樣:
1.首先,可以試圖用git push origin <branch-name>推送自己的修改;
2.如果推送失敗,則因為遠程分支比你的本地更新,需要先用git pull試圖合并;
3.如果合并有沖突,則解決沖突,并在本地提交;
4.沒有沖突或者解決掉沖突后,再用
git push origin <branch-name>
推送就能成功!
如果git pull提示no tracking information,則說明本地分支和遠程分支的鏈接關系沒有創建,用命令
git branch --set-upstream-to <branch-name> origin/<branch-name>
。
Rebase:
?rebase操作可以把本地未push的分叉提交歷史整理成直線;
?rebase的目的是使得我們在查看歷史提交的變化時更容易,因為分叉的提交需要三方對比。
標簽的意義:
Git的標簽雖然是版本庫的快照,但其實它就是指向某個commit的指針(跟分支很像,但是分支可以移動,標簽不能移動)
所以,創建和刪除標簽都是瞬間完成的。tag就是一個容易讓人記住的和某特定提交綁定的版本庫快照。
創建標簽:
首先,切換到需要打標簽的分支上:
查看所有分支列表: git branch
切換到需要打tag的分支:git checkout <branch_name>
打一個新標簽:
git tag <name> [commit_id]
git tag -a <tag_name> -m "instruct strings" [commit_id]
其次,
利用命令git tag查看所有標簽;
git show <tag_name>
查看指定標簽詳細信息
注意:標簽總是和某個commit掛鉤。如果這個commit既出現在master分支,又出現在dev分支,那么在這兩個分支上都可以看到這個標簽。
操作標簽:
刪除本地標簽:git tag -d <tag_name>
推送某個本地標簽: git push origin <tag_name>
推送所有本地標簽: git push origin --tags
刪除遠程標簽:
1.先在本地刪除;
2.git push origin :refs/tags/<tag_name>
GitHub:
?在GitHub上,可以任意Fork開源倉庫;
?自己擁有Fork后的倉庫的讀寫權限;
?可以推送pull request給官方倉庫來貢獻代碼
gitee:
登錄gitee.com注冊后,添加本地終端的rsa公鑰,而后建立遠程版本庫;
回到本地終端,如果已有版本庫要和遠程端的版本庫相關聯,可以利用命令
git remote add <name> git@gitee.com:username/respotname.git
注意:如果你的項目同時在github和gitee上開發,需要注意關聯時的遠程版本庫名字不能相同;github默認為origin,gitee就不能再使用該名字了。
自定義Git:
除了配置user.name和user.email,實際上,Git還有很多可配置項。
比如,讓Git顯示顏色,會讓命令輸出看起來更醒目:
git config --global color.ui true
忽略特殊文件:在git的根目錄下的.gitignore文件中添加需要忽略的文件名即可。當然git已經幫我們預先設立了一些忽略規則
配置文件:配置Git的時候,加上--global是針對當前用戶起作用的,如果不加,那只針對當前的倉庫起作用。 每個倉庫的Git配置文件都放在.git/config文件中;當前用戶的Git配置文件放在用戶主目錄下的一個隱藏文件.gitconfig中。
搭建git服務器:
搭建Git服務器需要準備一臺運行Linux的機器,強烈推薦用Ubuntu或Debian,這樣,通過幾條簡單的apt命令就可以完成安裝。
第一步,安裝git:
$ sudo apt-get install git
第二步,創建一個git用戶,用來運行git服務:
$ sudo adduser git
第三步,創建證書登錄: 收集所有需要登錄的用戶的公鑰,就是他們自己的id_rsa.pub文件,把所有公鑰導入到/home/git/.ssh/authorized_keys
文件里,一行一個。
第四步,初始化Git倉庫:
先選定一個目錄作為Git倉庫,假定是/srv/sample.git
,在/srv目錄下輸入命令:
$ sudo git init --bare sample.git
Git就會創建一個裸倉庫,裸倉庫沒有工作區,因為服務器上的Git倉庫純粹是為了共享,所以不讓用戶直接登錄到服務器上去改工作區,并且服務器上的Git倉庫通常都以.git結尾。
然后,把owner改為git:
$ sudo chown -R git:git sample.git
第五步,禁用shell登錄:
出于安全考慮,第二步創建的git用戶不允許登錄shell,這可以通過編輯/etc/passwd文件完成。
找到類似下面的一行:git:x:1001:1001:,,,:/home/git:/bin/bash
改為:
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
這樣,git用戶可以正常通過ssh使用git,但無法登錄shell,因為我們為git用戶指定的git-shell每次一登錄就自動退出。
第六步,克隆遠程倉庫:
現在,可以通過git clone命令克隆遠程倉庫了,在各自的電腦上運行:
$ git clone git@server:/srv/sample.git
Cloning into 'sample'...
warning: You appear to have cloned an empty repository.
管理公鑰:
如果團隊很小,把每個人的公鑰收集起來放到服務器的/home/git/.ssh/authorized_keys
文件里就是可行的。
如果團隊有幾百號人,就沒法這么玩了,這時,可以用Gitosis來管理公鑰。 因為Git是為Linux源代碼托管而開發的,所以Git也繼承了開源社區的精神,不支持權限控制。
不過,因為Git支持鉤子(hook),所以,可以在服務器端編寫一系列腳本來控制提交等操作,達到權限控制的目的。
Gitolite就是這個工具。 這里我們也不介紹Gitolite了,不要把有限的生命浪費到權限斗爭中。
小結
- 搭建Git服務器非常簡單,通常10分鐘即可完成;
- 要方便管理公鑰,用Gitosis;
- 要像SVN那樣變態地控制權限,用Gitolite。
===========我是華麗的分割線===========
更多知識:
點擊關注專題:嵌入式Linux&ARM
或瀏覽器打開:http://www.lxweimin.com/c/42d33cadb1c1
或掃描二維碼: