次短路
【一】基礎知識
1、版本控制系統發展史
版本控制工具的歷史可以分為三代
第一代版本控制系統被稱為本地版本控制系統。通過加鎖將併發執行轉換成順序執行。 一次只能有一個人處理檔案。如RCS、SCCS(1972年釋出)和 DSEE(被認為是 Atria ClearCase 的前身)
第二代版本控制系統被稱為集中式版本控制系統(Centralized Version Control Systems,CVCS),其對同步修改更加寬容,但有一個明顯的限制,使用者必須在允許提交之前將當前修訂合併到他們的工作中。第二代版本控制系統主要有 SVN/CVS(CVS有設計的問題,會造成提交檔案不完整,版本庫莫名其妙損壞的情況,SVN修正了CVS的一些穩定性問題,是目前用得最多的集中式版本庫控制系統)、SourceSafe、Subversion、Team Foundation Server、SVK.
第三代版本控制系統被稱為分散式式版本控制系統(Distributed Version Control Systems,DVCS),其允許合併和提交分開。在每個使用者電腦上就有一個完整的資料倉庫,沒有網路依然可以使用
第三代版本控制系統主要有 Bazaar、Git、Mercurial、BitKeeper、Monotone.
2、git簡介
在 Linux 開源的初期,linux社群使用的是BitMover授權免費使用的BitKeeper,但免費使用有很多限制,後因一大佬破解了BitKeeper,被 BitMover 公司發現,收回了免費使用權。迫不得已,Linus與2005年4月3日,用C開始開發一個分散式版本控制工具Git以替代 BitKeeper。在 2005 年7月26日,Linus 功成身退,將 Git 的維護交給另外一個 Git 的主要貢獻者 Junio C Hamano。Git迅速成為最流行的分散式版本控制系統,尤其是2008年,GitHub網站上線了,它為開源專案免費提供Git儲存
所有的版本控制系統,其實只能跟蹤文字檔案的改動,Git也不例外。而圖片、word、視訊這些二進位制檔案,是沒法跟蹤檔案的變化的,只能把二進位制檔案每次改動串起來,也就是隻知道圖片從100KB改成了120KB,但到底改了啥,版本控制系統不知道,也沒法知道。如果要真正使用版本控制系統,就要以純文字方式編寫檔案。因為文字是有編碼的,強烈建議使用標準的UTF-8編碼,所有語言使用同一種編碼,既沒有衝突,又被所有平臺所支援。
3、集中式與分散式區別
集中式版本控制系統版本庫是集中存放在中央伺服器的,多人協作時,要先從中央伺服器取得最新的版本,再把自己的程式碼推送給中央伺服器。缺點是中間伺服器宕機會影響到所有開發者,而且必須聯網的中央伺服器才能工作,如果在區域網內還好,頻寬夠大,速度夠快,可如果在網際網路上,遇到網速慢的話會嚴重影響彼此協作。
分散式版本控制系統根本沒有“中央伺服器”,每個人的電腦上都是一個完整的版本庫,本地工作完全不需要考慮遠端庫的存在,也就是有沒有聯網都可以正常工作,多人協作時只需把各自的修改推送給對方,就可以互相看到對方的修改了。除此之外Git還有極其強大的分支管理功能。
【二】git環境搭建
1、安裝git與配置
Ubuntu安裝命令:
sudo apt-get install git
安裝完後要進行全域性配置
git config --global user.name "你的github或gitlab等git儲存的使用者名稱"
git config --global user.email "你的github或gitlab等git儲存的郵箱地址"
2、自建程式碼託管平臺gitlab
GitLab是一個利用 Ruby on Rails 開發的開源應用程式,實現一個自託管的Git專案倉庫,可通過Web介面進行訪問公開的或者私人專案。
它擁有與Github類似的功能,能夠瀏覽原始碼,管理缺陷和註釋。可以管理團隊對倉庫的訪問,它非常易於瀏覽提交過的版本並提供一個檔案歷史庫。它還提供一個程式碼片段收集功能可以輕鬆實現程式碼複用,便於日後有需要的時候進行查詢
詳見:
https://www.cnblogs.com/chendf/p/13040447.html
3、git協議
Git支援多種協議,預設的git://
使用ssh,但也可以使用https
等其他協議。
使用https
除了速度慢以外,還有個最大的麻煩是每次推送都必須輸入口令,但是在某些只開放http埠的公司內部就無法使用ssh
協議而只能用https
。
【三】命令講解
1、建立版本庫
版本庫又名倉庫,英文名repository,你可以簡單理解成一個目錄,這個目錄裡面的所有檔案都可以被Git管理起來,每個檔案的修改、刪除,Git都能跟蹤,以便任何時刻都可以追蹤歷史,或者在將來某個時刻可以“還原”。
通過git init命令把這個目錄變成Git可以管理的倉庫
$ mkdir learngit
$ cd learngit
$ git init
建立好後,當前目錄下多了一個.git的目錄,這個目錄是Git來跟蹤管理版本庫的。以後對程式碼所做的很多git操作都會導致.git目錄裡檔案的實時變化,以便實現追蹤。
2、新增到暫存區
gitadd將工作區檔案的修改新增到暫存區
git add -u .(-u == --update),將已跟蹤檔案中的修改(modified)和刪除(deleted)的檔案新增到暫存區,不包括新檔案(new)。
git add . ,將修改(modified)操作的檔案和未跟蹤新新增的檔案(new)新增到git系統的暫存區,不包括被刪除(deleted)檔案
git add -A(-A == --all),是上面2個功能的合集,提交所有變化
3、提交到本地版本庫
gitcommit 將暫存區裡的改動給提交到本地版本庫
git commit -m “massage”,添加註釋git commit -a -m “massage” ,-a引數可以將所有已跟蹤檔案中的修改或刪除操作的檔案都提交到本地倉庫,即使它們沒有經過git add新增到暫存區,注意,新加的檔案是不能被提交到本地倉庫的
git commit --amend ,追加提交,它可以在不增加一個新的commit-id的情況下將新修改的程式碼追加到前一次的commit-id中,但該操作會改變你原來的commit id
4、檢視修改變動
gitdiff將檢視工作區和暫存區版本的區別
gitdiff --檔名
5、丟棄修改
分幾種情況:
未提交到暫存區:
使用git checkout --檔名(--很重要,沒有
--
,就變成了“切換到另一個分支”的命令),把工作區的修改全部撤銷
git checkout
其實是用版本庫裡的版本替換工作區的版本
提交到暫存區:
gitreset HEAD <file>,把暫存區的修改撤銷掉(unstage),重新放回工作區
git reset HEAD Marketing/User.php或git reset HEAD .(把所有檔案從暫存區撤回工作區)
git checkout -- .或git checkout .(把工作區的修改全部撤銷)
提交到本地版本庫:
git reset --hard HEAD #git reset --hard HEAD~1或git reset --hard 上一次commitId
6、關聯遠端庫
如果先有本地庫,後有遠端庫
如初始專案時,使用git init命令把本地目錄變成Git倉庫,需要使用git remote add origin 遠端庫地址url(如[email protected]:cdf/learn.git),來把已有的本地倉庫關聯到遠端庫。
這樣遠端庫既可以作為備份,又可以讓其他人通過該倉庫來協作了。
7、推送本地庫到遠端庫
gitpush,把本地庫的內容推送到遠端。
git push -u origin master,如果遠端庫是空的(在先有本地庫,後有遠端庫的情況),第一次推送master
分支時,要加上-u
引數,Git不但會把本地的master
分支內容推送的遠端新的master
分支,還會把本地的master
分支和遠端的master
分支關聯起來,在以後的推送或者拉取時就可以簡化命令。
以後直接誒使用gitpush(或git pushoriginmaster)即可把本地倉庫推送到遠端倉庫
8、從遠端庫克隆
如果先有本地庫,後有遠端庫的時候,則需要使用git remote add origin遠端庫url關聯遠端庫。
若是先建立遠端庫,則使用使用gitclone把遠端庫url克隆到本地庫。
要克隆一個倉庫,首先必須知道倉庫的地址,然後使用git clone命令克隆。Git支援多種協議,包括https,但ssh協議速度最快。
當你從遠端倉庫克隆時,實際上Git自動把本地的master
分支和遠端的master
分支對應起來了,並且,遠端倉庫的預設名稱是origin
git clone [email protected]:cdf/hello.git
9、分支操作
因為建立、合併和刪除分支非常快,所以Git鼓勵你使用分支完成某個任務。
git branchbranch_name,建立分支
git checkoutbranch_name,切換到某分支
git branch -bbranch_name,加-b引數代表建立並切換到某分支(相當於上面2個命令)
因為切換分支使用git checkout <branch>,撤銷修改則是git checkout -- <file>,同一個命令,有兩種作用容易讓人迷惑,因此,最新版本的Git提供了新的git switch
命令來切換分支
git switchbranch_name,切換分支(推薦使用gitswitch)
git switch -c branch_name,建立並切換分支(--change)
gitbranch查本地分支
gitmergeother_branch_name,把其它分支程式碼合併到當前分支
gitbranch -dother_branch_name,刪除其它分支(-D,d大寫代表強制刪除)
分支合併策略
使用gitmerge合併分支時,Git預設使用Fast forward模式,但這種模式下,刪除被合併分支後,會丟掉分支資訊。
如果加上引數--no-ff
禁用Fast forward模式,就可以用普通模式合併,Git就會在merge時生成一個新的commitId,這樣,從分支歷史上就可以看出分支資訊。
git merge --no-ff -m "merge with no-ff" dev
加-m進行註釋是因為合併會生成新的commitId,就行執行gitcommit會生成commitId需要註釋一樣
10、衝突解決
常見衝突情況,2個或多個人修改了同一行的程式碼,然後分支合併產生衝突,gitmerge other_branch_name,會提示衝突的檔名。
Git用<<<<<<<
,=======
,>>>>>>>
標記出不同分支的內容,我們必須解決衝突後再提交。
可手動找到相應檔案解決,或使用工具()
解決後使用git add/git commit提交
11、檢視分支合併圖
用git log --graph
命令可以看到分支合併圖,如
git log --graph --pretty=oneline --abbrev-commit -n 6
可看見
12、暫存修改(儲存現場)
在開發專案的時候,突然來一個變更需要修改,我們除了將當前專案提交(commit)後切換(checkout) 到其他分支外,我們還可以先將當前的修改暫存(stash)起來,然後再切換(checkout)到其他分支,而不需要提交(commit),這樣就可以減少一個 commit (雖然可以使用 gitcommit --amend 來修改最後一次提交 )
暫存修改分2種情況
檔案已被git跟蹤:使用gitstash,如果需要加註釋使用gitstashsave 'message'
檔案未被跟蹤,如新增檔案,使用gitstash -a或需要註釋gitstashsave -a 'messge',或先 git add . 然後再使用 git stash 或 git stashsave "註釋" 來暫存修改
其它命令:
git stash list ,檢視暫存列表
可以看到stash@{id}裡面的id預設從0開始,最近的暫存為0,使用此特性可對暫存區進行一些操作
git show stash@{n},通過此命令可以檢視stash的詳情,如git show stash@{0}可看到最近一次暫存內容的修改情況
git stash apply stash@{id},回到曾今的工作現場(在當前分支應運指定id暫存內容),恢復後,stash內容並不刪除。需使用git stash drop stash@{id}來刪除
git stash pop stash@{id},恢復最新的暫存內容到工作區,不指定stash@{id}(git stash pop即git stash popstash@{0}),會在 stash list 裡面將最近一次的修改暫存記錄刪除掉,等同於git stash apply stash@{0}和git stashdrop stash@{0}。
git stash clear,清空所有修改暫存
git stash drop stash@{id},刪除指定暫存
12、git cherry-pick
複製特定的提交到當前分支,可用於“重放”別的分支的bug修復過程等。
如,master分支有bug,當前分支是早期從master分支分出來的,在master分支上修復了bug後,我們只想把master分支提交所做的修改“複製”到當前分支,而不是把整個master分支merge過來,這時可使用gitcherry-pick.
git cherry-pick <commit>,如git cherry-pick 4c805e2
13、gitremote遠端分支操作
遠端倉庫的預設名稱是origin。使用git remote可檢視遠端倉庫名
git remote -v,可檢視詳細資訊
gitpushoriginlocal_branch_name,把本地指定分支上的所有本地提交推送到遠端庫。
如gitpushorigin dev、gitpushoriginmaster
推送時,通過指定本地分支,這樣,Git就會把該分支推送到遠端庫對應的遠端分支上
必須先指定本地分支與遠端分支的連結,才能使用gitpushorigin local_branch_name。
可使用git branch --set-upstream-to=origin/remote_branch_name local_branch_name來指定連結.如git branch --set-upstream-to=origin/dev dev
14、gitrebase變基
負責把分叉的提交歷史“整理”成一條直線,再推送到遠端。
使用場景:同一分支,別人在我之前做了修改,並且提交到了遠端庫,那麼我提交時必須先git pull獲取一下最新程式碼,再git push到遠端庫。
這樣有個問題:提交歷史分叉了
我們可以在git pull之後,gitpush提交之前,執行
git rebase
這樣再git push到遠端庫,提交歷史就不再分叉,變的好看一些
15、gittag標籤
標籤是是指向某個commit的指標,是版本庫的快照。
使用場景:
git commit提交多次,需要把上週的某一次打包釋出,要找到對應的commit號,很麻煩,這事可以打個標籤,按標籤查詢就行了。
還有一種場景,使用composer search、composerrequire等操作庫檔案,由於庫檔案是儲存在github等git倉庫中,它的不同版本也是通過標籤向外釋出供引入。
gittagtag_name [commitId],不指定commitId表示在最新節點打標籤。如git tag v1.0.
可通過git log --pretty=oneline --abbrev-commit檢視各commit號,指定節點打標籤。如git tag v1.2 guwy543we4
引數解釋
-a,指定標籤名,
-m ,註釋
如:git tag -a v0.1 -m "version 0.1 released" 1wewe12
git tag,檢視當前所有標籤
git show tag_name,檢視指定標籤資訊
git tag -dtag_name,刪除標籤
gitpushorigintag_name,因為建立的標籤都只儲存在本地,不會自動推送到遠端,有時需把指定標籤推送到遠端分支。
gitpush origin --tags,一次性把所有標籤推送到遠端分支。
如果標籤推送到了遠端庫,要刪除標籤怎麼辦?
先使用git tag -dtag_name刪除本地分支,再使用git push origin :refs/tags/tag_name,如(git push origin :refs/tags/v1.2)從遠端刪除
注意:標籤總是和某個commit掛鉤。如果這個commit既出現在master分支,又出現在dev分支,那麼在這兩個分支上都可以看到這個標籤
16、配置別名gitalias
分對當前使用者其作用還是整個倉庫起作用
當前使用者起作用,可使用git config --global alias.自定義別名git名,如給git status配置別名,可使用命令git config --global alias.st status。
可對git log配置別名:git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
發現美觀了不少,也不用敲入那麼長命令浪費時間了。
當前使用者的Git配置檔案放在使用者主目錄下的一個隱藏檔案.gitconfig
中,可找到這個目錄,直接修改來配置
對當前倉庫起作用,git config alias.自定義別名git名,不加--global。配置檔案放在.git/config中,可對其直接修改來配置
17、忽略檔案
有些檔案,如:
作業系統自動生成的檔案,比如縮圖等;
編譯生成的中間檔案、可執行檔案等,也就是如果一個檔案是通過另一個檔案自動生成的,那自動生成的檔案就沒必要放進版本庫;
你自己的帶有敏感資訊的配置檔案,比如存放口令的配置檔案。
需要進行忽略操作,可編寫.gitignore,.gitignore檔案本身要放到版本庫裡,並且可以對.gitignore做版本管理!
如果本地忽略已提交到遠端,再次ignore忽略失敗,解決方案,刪除快取:
git rm -r --cached core/library/wew/cer/.
git commit -m '忽略版本控制證書'
git push
18、清理版本庫不存在的本地分支
有時由於切換的本地分支很多,導致分支管理越來越麻煩,可以清理掉已經不用的分支,如刪除本地有但在遠端庫已經不存在的分支
git remote prune origin
19、更改遠端倉庫地址
場景:某員工建立了專案,後離職了,那以前的倉庫url需要進行使用者名稱改變(http://gitlab.mkeduit.com:8888/使用者名稱/learn.git),操作如下
刪除遠端倉庫git remote rm origin
新增倉庫
git remote add originhttp://gitlab.cdf.com:8888/xiaona/learn.git
檢視倉庫是否新增成功
git remote -v
配置全域性使用者名稱郵箱
git config --global user.name "cdf"
git config --global user.email [email protected]
git commit --amend --reset-author
拉取下最新的分支 git fetch
git pull
關聯本地分支到遠端分支
git branch --set-upstream-to=origin/master master
測試推送程式碼是否正常
git push
git pull