Git相關知識點
本文主要介紹了git使用SSH金鑰、入門知識、分支管理以及常用命令,掌握了一下內容,你就可以輕鬆的在工作送使用Git了。
SSH金鑰
git使用https協議,每次pull, push都要輸入密碼,相當的煩。
使用git協議,然後使用ssh金鑰。這樣可以省去每次都輸密碼。
需要三個步驟:
一、本地生成金鑰對;
二、設定github上的公鑰;
三、修改git的remote url為git協議。
1、生成金鑰
大多數 Git 伺服器都會選擇使用 SSH 公鑰來進行授權。系統中的每個使用者都必須提供一個公鑰用於授權,沒有的話就要生成一個。生成公鑰的過程在所有作業系統上都差不多。首先先確認一下是否已經有一個公鑰了。SSH 公鑰預設儲存在賬戶的主目錄下的 ~/.ssh 目錄。進去看看:
$ cd ~/.ssh $ ls authorized_keys2 id_dsa known_hosts config id_dsa.pub
關鍵是看有沒有用 something 和 something.pub 來命名的一對檔案,這個 something 通常就是 id_dsa 或 id_rsa。有 .pub 字尾的檔案就是公鑰,另一個檔案則是金鑰。假如沒有這些檔案,或者乾脆連 .ssh 目錄都沒有,可以用 ssh-keygen 來建立。該程式在 Linux/Mac 系統上由 SSH 包提供,而在 Windows 上則包含在 MSysGit 包裡:
$ ssh-keygen -t rsa -C "your_email@youremail.com" # Creates a new ssh key using the provided email # Generating public/private rsa key pair. # Enter file in which to save the key (/home/you/.ssh/id_rsa):
直接Enter就行。然後,會提示你輸入密碼,如下(建議輸一個,安全一點,當然不輸也行):
Enter passphrase (empty for no passphrase): [Type a passphrase] # Enter same passphrase again: [Type passphrase again]
完了之後,大概是這樣。
Your identification has been saved in /home/you/.ssh/id_rsa. # Your public key has been saved in /home/you/.ssh/id_rsa.pub. # The key fingerprint is: # 01:0f:f4:3b:ca:85:d6:17:a1:7d:f0:68:9d:f0:a2:db your_email@youremail.com
這樣。你本地生成金鑰對的工作就做好了。
2、新增公鑰到你的github帳戶
2-1、檢視你生成的公鑰:大概如下:
$ cat ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlE LEVf4h9lFX5QVkbPppSwg0cda3 Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA t3FaoJoAsncM1Q9x5+3V 0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx NrRFi9wrf+M7Q== schacon@agadorlaptop.local
2-2、登陸你的github帳戶。然後 Account Settings -> 左欄點選 SSH Keys -> 點選 Add SSH key
2-3、然後你複製上面的公鑰內容,貼上進“Key”文字域內。 title域,你隨便填一個都行。
2-4、完了,點選 Add key。
這樣,就OK了。然後,驗證下這個key是不是正常工作。
$ ssh -T git@github.com # Attempts to ssh to github
如果,看到:
Hi username! You've successfully authenticated, but GitHub does not # provide shell access.
就表示你的設定已經成功了。
3、修改你本地的ssh remote url. 不用https協議,改用git 協議
確保:
你已經init了一個空倉庫。
你已經把遠端git的url新增到了本地git倉庫的配置檔案
================================================
可以用git remote -v 檢視你當前的remote url
$ git remote -v origin (fetch) origin (push)
可以看到是使用https協議進行訪問的。
你可以使用瀏覽器登陸你的github,在上面可以看到你的ssh協議相應的url。類似如下:
git@github.com:someaccount/someproject.git
這時,你可以使用 git remote set-url 來調整你的url。
git remote set-url origin git@github.com:someaccount/someproject.git
完了之後,你便可以再用 git remote -v 檢視一下。
$ git remote -v origin (fetch) origin (push)
OK。
至此,你就可以省去輸入密碼的麻煩,也可以很安全的進行push,pull,fetch,checkout等操作了。
你可以用git fetch, git pull , git push。
「注意:」
第一次使用git push之前,需要對git push進行配置:
1.simple方式:
git config --global push.default.simple
2.matching方式:
git config --global push.default.matching matching means git push will push all your local branches to the ones with the same name on the remote. This makes it easy to accidentally push a branch you didn't intend to.
matching與simple方式的push的區別是:matching會把你所有本地的分支push到遠端倉庫中對應匹配的分支。
simple means git push will push only the current branch to the one that git pull would pull from, and also checks that their names match. This is a more intuitive behavior, which is why the default is getting changed to this.
simple方式,只會push你已經從遠端倉庫pull過的分支,意思是你曾經pull了分支dev,那麼當你使用預設git push時,當前分支為dev,遠端分支dev就會收到你的commit。
3.或者使用git push [遠端倉庫] [本地分支]
入門知識
Git簡介
Git是目前世界上最先進的分散式版本控制系統。
-
版本控制
典型代表Word檔案的編輯,你的資料夾中是不是有這樣的情況:
word20160301.doc word備份的.doc word(小王).doc word-03.doc word.doc
而某一天,你可能需要以前修改過的版本(因為,經常會遇到這種抽風的上司或者客戶)
而由版本控制給你帶來的是:
版本 使用者 說明 日期 1 張三 刪除了軟體服務條款5 7/12 10:38 2 張三 增加了License人數限制 7/12 18:09 3 李四 財務部門調整了合同金額 7/13 9:51 4 張三 延長了免費升級週期 7/14 15:17
而且,你想退回到哪裡,就可以退回到哪裡!
記住第一個關鍵詞:(無盡的)後悔藥
-
分散式 VS 集中式
集中式,典型的代表就是SVN,版本庫是集中存放在中央伺服器的,而幹活的時候,用的都是自己的電腦,所以要先從中央伺服器取得最新的版本,然後開始幹活,幹完活了,再把自己的活推送給中央伺服器。
分散式,分散式版本控制系統根本沒有“中央伺服器”,每個人的電腦上都是一個完整的版本庫,分散式版本控制系統的安全性要高很多,因為每個人電腦裡都有完整的版本庫,某一個人的電腦壞掉了不要緊,隨便從其他人那裡複製一個就可以了。而集中式版本控制系統的中央伺服器要是出了問題,所有人都沒法幹活了。
Git不單是不必聯網這麼簡單,Git更強大的是分支管理。後面講到~~~~~
關於更多SVN&Git的區別可以參見:
記住第二個關鍵詞:分散式
Git環境搭建
安裝Git
在Linux(Debian)上安裝Git:
apt-get install gitMac OS X上安裝Git:
第一種方法是安裝homebrew,然後透過homebrew安裝Git,具體方法請參考homebrew的文件:。
第二種方法更簡單,也是推薦的方法,就是直接從AppStore安裝Xcode,Xcode整合了Git,不過預設沒有安裝,你需要執行Xcode,選擇選單“Xcode”->“Preferences”,在彈出視窗中找到“Downloads”,選擇“Command Line Tools”,點“Install”就可以完成安裝了。在Windows上安裝Git
從這裡下載,雙擊安裝
安裝完成後,可以在右鍵選單/開始選單中找到“Git”->“Git Bash”,蹦出一個類似命令列視窗的東西,就說明Git安裝成功!
全域性變數設定
就像Java需要設定Path一樣,Git需要設定一些全域性變數。
“Git”->“Git Bash” $ git config --global user.name "Your Name" $ git config --global user.email "email@example.com"
設定使用者與Email,相當於自報家門,讓版本庫有一個記錄。注意:git config
命令的--global
是全域性設定的意思。
任何一個命令或者參考:
git [命令] --help
來檢視幫助,或者登陸官方來學習命令
參考資料:
建立版本庫
-
windows下,需要建立的版本庫的地方,右鍵git bash->
$ git init
瞬間Git就把倉庫建好了,而且告訴你是一個空的倉庫(empty Git repository),細心的讀者可以發現當前目錄下多了一個.git的目錄,這個目錄是Git來跟蹤管理版本庫的,沒事千萬不要手動修改這個目錄裡面的檔案,不然改亂了,就把Git倉庫給破壞了。
PS:如果你沒有看到.git目錄,那是因為這個目錄預設是隱藏的
Linux中:
如果,需要在learngit目錄下建立一個Git倉庫,可以如下操作
$ mkdir learngit $ cd learngit $ git init
你也可以這樣:
$ git init learngit
試一試吧!
基本操作
Git工作區和暫存區:
我們看到目錄為工作區(/learngit);需要進行提交到版本庫的檔案放在暫存區(看不到,需要使用git status
來檢視)。
git status
命令:可以讓我們時刻掌握倉庫當前的狀態。
git diff
命令:讓我們檢視檔案與版本庫中的區別。
獲取遠端倉庫程式碼(前提是init
之後)
-
克隆倉庫:
$ git clone [user@]example.com:path/to/repo.git/
-
或者新增遠端倉庫:
使用
git remote add
命令,新增一個遠端倉庫的連結,命令格式:git remote add [遠端倉庫別名] [遠端倉庫地址]
$ git remote add origin git@github.com:michaelliao/learngit.git
-
拉取程式碼。
如果已經被git管理的專案,則使用
git pull
和git fetch
來管理程式碼的拉取與更新:使用
git pull
拉取遠端程式碼的HEAD
頭標記,即最新的程式碼。命令格式:
$ git pull <遠端主機名> <遠端分支名>:<本地分支名>
$ git pull
提交程式碼
把所有的檔案更改提交到暫存區:
$ git add -a
為所有暫存區的程式碼寫入日誌並提交到本地倉庫:
$ git commit -m "(something)"
把所有本地倉庫的提交,更新到遠端倉庫:
$ git push
Git時光機
-
git log
命令:檢視每次修改的日誌檔案。,記得幾點:git log是順著當前分支往前去查詢提交記錄,而git reflog並不像git log去遍歷提交歷史,它都不是倉庫的一部分,它不包含推送、更新或者克隆,而是作為本地提交記錄的清單。簡單理解:本地後悔藥。
-
git reset
命令:回退命令。首先,Git必須知道當前版本是哪個版本,在Git中,用
HEAD
表示當前版本,上一個版本就是HEAD^
,上上一個版本就是HEAD^^
,當然往上100個版本寫100個^
比較容易數不過來,所以寫成HEAD~100
。$ git reset --hard HEAD^ HEAD is now at ea34578 add distributed
回退add命令提交到快取區的檔案,並不會把檔案恢復快取區,需要區別(3)
git checkout
命令:$ git reset HEAD
git checkout --
命令:丟棄快取區檔案的修改,把檔案恢復到git add
之前的狀態。git diff HEAD --
命令可以檢視工作區和版本庫裡面最新版本的區別git rm
刪除檔案。
標籤管理
釋出一個版本時,我們通常先在版本庫中打一個標籤,這樣,就唯一確定了打標籤時刻的版本。將來無論什麼時候,取某個標籤的版本,就是把那個打標籤的時刻的歷史版本取出來。所以,標籤也是版本庫的一個快照。
Git的標籤雖然是版本庫的快照,但其實它就是指向某個commit的指標(跟分支很像對不對?但是分支可以移動,標籤不能移動),所以,建立和刪除標籤都是瞬間完成的。
-
建立標籤(快照)
在Git中打標籤非常簡單,首先,切換到需要打標籤的分支上:
$ git branch * dev master $ git checkout master Switched to branch 'master'
然後,敲命令
git tag
就可以打一個新標籤:$ git tag v1.0
可以用命令
git tag
檢視所有標籤:$ git tag v1.0
預設標籤是打在最新提交的commit上的。有時候,如果忘了打標籤,比如,現在已經是週五了,但應該在週一打的標籤沒有打,怎麼辦?
方法是找到歷史提交的commit id,然後打上就可以了:
$ git log --pretty=oneline --abbrev-commit 6a5819e merged bug fix 101 cc17032 fix bug 101 7825a50 merge with no-ff 6224937 add merge 59bc1cb conflict fixed 400b400 & simple 75a857c AND simple fec145a branch test d17efd8 remove test.txt
比方說要對add merge這次提交打標籤,它對應的commit id是
6224937
,敲入命令:$ git tag v0.9 6224937
再用命令
git tag
檢視標籤:$ git tag v0.9 v1.0
注意,標籤不是按時間順序列出,而是按字母排序的。
可以用
git show
檢視標籤資訊:$ git show v0.9 commit 622493706ab447b6bb37e4e2a2f276a20fed2ab4 Author: Brian Date: Thu Aug 22 11:22:08 2013 +0800 add merge ...
可以看到,v0.9確實打在add merge這次提交上。
還可以建立帶有說明的標籤,用-a
指定標籤名,-m
指定說明文字:
$ git tag -a v0.1 -m "version 0.1 released" 3628164
用命令git show
可以看到說明文字:
$ git show v0.1 tag v0.1 Tagger: Brian Date: Mon Aug 26 07:28:11 2013 +0800 version 0.1 released commit 3628164fb26d48395383f8f31179f24e0882e1e0 Author: Brian Date: Tue Aug 20 15:11:49 2013 +0800 append GPL
還可以透過-s
用私鑰簽名一個標籤:
$ git tag -s v0.2 -m "signed version 0.2 released" fec145a
參考資料:
-
標籤操作(刪除,推送)
命令
git push origin
可以推送一個本地標籤;命令
git push origin --tags
可以推送全部未推送過的本地標籤;命令
git tag -d
可以刪除一個本地標籤;命令
git push origin :refs/tags/
可以刪除一個遠端標籤。如果標籤已經推送到遠端,要刪除遠端標籤就麻煩一點,先從本地刪除:
$ git tag -d v0.9 Deleted tag 'v0.9' (was 6224937)
然後,從遠端刪除。刪除命令也是push,但是格式如下:
$ git push origin :refs/tags/v0.9 To git@github.com:michaelliao/learngit.git - [deleted] v0.9
使用.gitignore忽略檔案
有些時候,你必須把某些檔案放到Git工作目錄中,但又不能提交它們,比如儲存了資料庫密碼的配置檔案啦,等等,每次git status都會顯示Untracked files …,有強迫症的童鞋心裡肯定不爽。
好在Git考慮到了大家的感受,這個問題解決起來也很簡單,在Git工作區的根目錄下建立一個特殊的.gitignore檔案,然後把要忽略的檔名填進去,Git就會自動忽略這些檔案。
不需要從頭寫.gitignore
檔案,GitHub已經為我們準備了各種配置檔案,只需要組合一下就可以使用了。所有配置檔案可以直接線上瀏覽:
忽略檔案的原則是:
忽略作業系統自動生成的檔案,比如縮圖等;
忽略編譯生成的中間檔案、可執行檔案等,也就是如果一個檔案是透過另一個檔案自動生成的,那自動生成的檔案就沒必要放進版本庫,比如Java編譯產生的.class檔案;
忽略你自己的帶有敏感資訊的配置檔案,比如存放口令的配置檔案。
舉個例子:
假設你在Windows下進行Python開發,Windows會自動在有圖片的目錄下生成隱藏的縮圖檔案,如果有自定義目錄,目錄下就會有Desktop.ini檔案,因此你需要忽略Windows自動生成的垃圾檔案:
# Windows: Thumbs.db ehthumbs.db Desktop.ini
然後,繼續忽略Python編譯產生的.pyc
、.pyo
、dist
等檔案或目錄:
# Python: *.py[cod] *.so *.egg *.egg-info dist build
加上你自己定義的檔案,最終得到一個完整的.gitignore
檔案,內容如下:
# Windows: Thumbs.db ehthumbs.db Desktop.ini # Python: *.py[cod] *.so *.egg *.egg-info dist build # My configurations: db.ini deploy_key_rsa
最後一步就是把.gitignore也提交到Git,就完成了!當然檢驗.gitignore
的標準是git status
命令是不是說working directory clean。
使用Windows的童鞋注意了,如果你在資源管理器裡新建一個.gitignore
檔案,它會非常弱智地提示你必須輸入檔名,但是在文字編輯器裡“儲存”或者“另存為”就可以把檔案儲存為.gitignore
了。
或者可以使用以下方法,在git bash中輸入以下命令:
$ touch .gitignore $ vi .gitignore
Git忽略規則及.gitignore規則不生效的解決辦法:
git rm -r --cached . git add . git commit -m 'update .gitignore'
PS:注意–cached後面有一個”.”,add後面也有一個“.”
完成上述操作後,再重新修改.gitnore檔案,並
git add .
新增檔案到快取區
配置命令別名
有沒有經常敲錯命令?比如git status
?status這個單詞真心不好記。
如果敲git st
就表示git status
那就簡單多了,當然這種偷懶的辦法我們是極力贊成的。
我們只需要敲一行命令,告訴Git
,以後st
就表示status
:
$ git config --global alias.st status
好了,現在敲git st
看看效果。
當然還有別的命令可以簡寫,很多人都用co
表示checkout
,ci
表示commit
,br
表示branch
:
$ git config --global alias.co checkout $ git config --global alias.ci commit $ git config --global alias.br branch
以後提交就可以簡寫成:
$ git ci -m "bala bala bala..."
--global
引數是全域性引數,也就是這些命令在這臺電腦的所有Git倉庫下都有用。
在撤銷修改一節中,我們知道,命令git reset HEAD file
可以把暫存區的修改撤銷掉(unstage),重新放回工作區。既然是一個unstage
操作,就可以配置一個unstage
別名:
$ git config --global alias.unstage 'reset HEAD'
當你敲入命令:
$ git unstage test.py
實際上Git執行的是:
$ git reset HEAD test.py
配置一個git last
,讓其顯示最後一次提交資訊:
$ git config --global alias.last 'log -1'
這樣,用git last
就能顯示最近一次的提交:
$ git last commit adca45d317e6d8a4b23f9811c3d7b7f0f180bfe2 Merge: bd6ae48 291bea8 Author: Michael Liao Date: Thu Aug 22 22:49:22 2013 +0800 merge & fix hello.py
甚至還有人喪心病狂地把lg
配置成了:
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 lg的效果:
為什麼不早點告訴我?別激動,我們不是為了多記幾個英文單詞嘛!
配置檔案
配置Git的時候,加上--global
是針對當前使用者起作用的,如果不加,那隻針對當前的倉庫起作用。
配置檔案放哪了?每個倉庫的Git配置檔案都放在.git/config
檔案中:
$ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [remote "origin"] url = git@github.com:michaelliao/learngit.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master [alias] last = log -1
別名就在[alias]
後面,要刪除別名,直接把對應的行刪掉即可。
而當前使用者的Git配置檔案放在使用者主目錄下的一個隱藏檔案.gitconfig
中:
$ cat .gitconfig [alias] co = checkout ci = commit br = branch st = status [user] name = Your Name email = your@email.com
Git恢復流程
當中心倉庫由於不可抗拒因素而垮了之後:
專案Git恢復流程:
方法一:恢復指定分支
1.註冊賬號→輸入SSH keys→新建專案。
2.在原專案資料夾下,使用git remote -v
命令檢視
$ git remote -v origin git@192.168.1.222:kanlidy/HelloGit.git (fetch) origin git@192.168.1.222:kanlidy/HelloGit.git (push)
使用git remote remove origin
刪除原有倉庫地址。
3.使用新的倉庫地址:
git remote add origin [ssh倉庫地址]
如:
git remote add origin ssh://git@github.com/kanlidy/HelloGit.git
4.新增檔案,並Commit提交,最後push上遠端指定分支
git add . git commit -m "add my repo" #這條命令會把當前分支,推送到遠端的master分支 git push origin master #如果需要把dev分支,推送到遠端的dev分支 git push origin dev:dev
方法二:恢復專案所有分支:
git remote remove origin git remote add origin [新的SSH倉庫地址] git push --mirror ssh://git@github.com/kanlidy/LearnPython.git
本地多個SSH金鑰檔案
有的時候,不僅github使用ssh key,工作專案或者其他雲平臺可能也需要使用ssh key來認證,如果每次都覆蓋了原來的id_rsa檔案,那麼之前的認證就會失效。這個問題我們可以透過在~/.ssh目錄下增加config檔案來解決。
-
第一步依然是配置git使用者名稱和郵箱
git config user.name "使用者名稱" git config user.email "郵箱"
-
生成ssh key時同時指定儲存的檔名
ssh-keygen -t rsa -f ~/.ssh/id_rsa.company -C "email"
上面的
id_rsa.company
就是我們指定的檔名,這時~/.ssh目錄下會多出id_rsa.company
和id_rsa.company.pub
兩個檔案,id_rsa.company.pub
裡儲存的就是我們要使用的key。 -
新增並配置config檔案
新增config檔案
如果config檔案不存在,先新增;存在則直接修改
touch ~/.ssh/config
在config檔案裡新增如下內容(User表示你的使用者名稱)
Host 域名或者IP IdentityFile ~/.ssh/id_rsa.company User test
如:
Host 192.168.1.222 IdentityFile ~/.ssh/id_rsa.company User kanlidy
上傳key到雲平臺後臺(省略)
-
測試ssh key是否配置成功
ssh -T git@域名或者IP
如:
ssh -T git@192.168.1.222 -p 8082
成功的話會顯示:
Welcome to GitLab, kanlidy!
至此,本地便成功配置多個ssh key。日後如需新增,則安裝上述配置生成key,並修改config檔案即可。
Git分支管理
還記得《星際穿越》中的平行空間嗎?兩個獨立的空間互不干擾,當你正在電腦前努力學習Git的時候,另一個你正在另一個平行宇宙裡努力學習SVN。在某一個時間點,兩個平行的時空合併了,結果,你既學會了Git又學會了SVN!
**分支在實際中有什麼用呢?**假設你準備開發一個新功能,但是需要兩週才能完成,第一週你寫了50%的程式碼,如果立刻提交,由於程式碼還沒寫完,不完整的程式碼庫會導致別人不能幹活了。如果等程式碼全部寫完再一次提交,又存在丟失每天進度的巨大風險。
**分支的獨立性:**現在有了分支,就不用怕了。你建立了一個屬於你自己的分支,別人看不到,還繼續在原來的分支上正常工作,而你在自己的分支上幹活,想提交就提交,直到開發完畢後,再一次性合併到原來的分支上,這樣,既安全,又不影響別人工作。
**git分支的高效:**其他版本控制系統如SVN等都有分支管理,但是用過之後你會發現,這些版本控制系統建立和切換分支比蝸牛還慢,簡直讓人無法忍受,結果分支功能成了擺設,大家都不去用。
但Git的分支是與眾不同的,無論建立、切換和刪除分支,Git在1秒鐘之內就能完成!無論你的版本庫是1個檔案還是1萬個檔案。
理解HEAD
頭指標
一開始的時候,HEAD
頭指標指向的是主分支,即master
分支。而HEAD
指向的是當前分支,master
指向的是提交。
如果,在master
分支上新建了一個分支dev
,此時HEAD
指向了dev
,Git建立分支的過程很快,因為除了增加一個dev
指標,改改HEAD
的指向,工作區的檔案都沒有任何變化!
不過,從現在開始,對工作區的修改和提交就是針對dev
分支了,比如新提交一次後,dev
指標往前移動一步,而master
指標不變。
建立dev
分支
建立分支使用git branch
命令,命令格式:git branch [分支別名]
$ git branch dev
可以使用$ git branch
來檢視所有本地分支,$ git branch -a
檢視所有分支(包括遠端分支)。
使用git checkout [分支名]
切換到對應的分支,如:
$ git checkout dev
此時,HEAD
頭指標會指向dev,如果在dev
上提交,dev
指標會往前移,而其他分支不變。(master
分支及指標不變)
當使用git checkout master
時,HEAD
頭指標會重新指向master
,此時再提交,master
指標會往前移。
這個過程,需要自己親身的試驗才能體會到它們的作用和變化。
$gitk
使用Git自帶的圖形介面,可以很好的來管理分支。
衝突解決
衝突產生:當兩個分支中修改的相同的檔案並提交(add->commit),合併(merge)這兩個分支的時候,會產生衝突。
如下例:
$ git checkout -b feature1
-
在新的
feature1
分支下修改了readme.txt:vi readme.txt //修改,新增Creating a new branch is quick AND simple. $ git add readme.txt $ git commit -m "AND simple"
-
切換到
master
分支:$ git checkout master vi readme.txt //在`master`分支上把readme.txt檔案的最後一行改為:Creating a new branch is quick & simple $ git add readme.txt $ git commit -m "& simple"
-
試圖合併
master
與feature1
:$ git merge feature1 Auto-merging readme.txt CONFLICT (content): Merge conflict in readme.txt Automatic merge failed; fix conflicts and then commit the result.
(1)使用:
$ git status
來檢視衝突檔案:$ git status # On branch master # Your branch is ahead of 'origin/master' by 2 commits. # # Unmerged paths: # (use "git add/rm ..." as appropriate to mark resolution) # # both modified: readme.txt # no changes added to commit (use "git add" and/or "git commit -a")
(2)直接檢視readme.txt檔案內容:
Git is a distributed version control system. Git is free software distributed under the GPL. Git has a mutable index called stage. Git tracks changes of files. <<<<<<< HEAD Creating a new branch is quick & simple. ======= Creating a new branch is quick AND simple. >>>>>>> feature1
Git用
<<<<<<<
,=======
,>>>>>>>
標記出不同分支的內容,我們修改如下後儲存:Creating a new branch is quick and simple.
-
再提交:
$ git add readme.txt $ git commit -m "conflict fixed" [master 59bc1cb] conflict fixed
PS: 用帶引數的
git log
也可以看到分支的合併情況:$ git log --graph --pretty=oneline --abbrev-commit * 59bc1cb conflict fixed | | * 75a857c AND simple * | 400b400 & simple |/ * fec145a branch test ...
-
最後,刪除
feature1
分支:$ git branch -d feature1
Deleted branch feature1 (was 75a857c).
分支管理策略
通常,合併分支時,如果可能,Git會用Fast forward
模式,但這種模式下,刪除分支後,會丟掉分支資訊。
如果要強制禁用Fast forward
模式,Git就會在merge
時生成一個新的commit
,這樣,從分支歷史上就可以看出分支資訊。
下面我們實戰一下--no-f
f方式的git merge
:
首先,仍然建立並切換dev
分支:
$ git checkout -b dev Switched to a new branch 'dev'
修改readme.txt檔案,並提交一個新的commit
:
$ git add readme.txt $ git commit -m "add merge" [dev 6224937] add merge 1 file changed, 1 insertion(+)
現在,我們切換回master
:
$ git checkout master Switched to branch 'master
準備合併dev
分支,請注意--no-ff
引數,表示禁用Fast forward
:
$ git merge --no-ff -m "merge with no-ff" dev Merge made by the 'recursive' strategy. readme.txt | 1 + 1 file changed, 1 insertion(+)
分支策略
在實際開發中,我們應該按照幾個基本原則進行分支管理:
首先,master
分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面幹活;
那在哪幹活呢?幹活都在dev
分支上,也就是說,dev
分支是不穩定的,到某個時候,比如1.0
版本釋出時,再把dev分支合併到master
上,在master
分支釋出1.0
版本;
你和你的小夥伴們每個人都在dev分支上幹活,每個人都有自己的分支,時不時地往dev分支上合併就可以了。
所以,團隊合作的分支看起來就像這樣:
Bug分支
軟體開發中,bug就像家常便飯一樣。有了bug就需要修復,在Git中,由於分支是如此的強大,所以,每個bug都可以透過一個新的臨時分支來修復,修復後,合併分支,然後將臨時分支刪除。
當你接到一個修復一個代號101的bug的任務時,很自然地,你想建立一個分支issue-101
來修復它,但是,等等,當前正在dev
上進行的工作還沒有提交:
$ git status # On branch dev # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: hello.py # # Changes not staged for commit: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: readme.txt #
並不是你不想提交,而是工作只進行到一半,還沒法提交,預計完成還需1天時間。但是,必須在兩個小時內修復該bug,怎麼辦?
幸好,Git還提供了一個stash
功能,可以把當前工作現場“儲藏”起來,等以後恢復現場後繼續工作:
$ git stash Saved working directory and index state WIP on dev: 6224937 add merge HEAD is now at 6224937 add merge
現在,用git status
檢視工作區,就是乾淨的(除非有沒有被Git管理的檔案),因此可以放心地建立分支來修復bug。
首先確定要在哪個分支上修復bug,假定需要在master
分支上修復,就從master
建立臨時分支:
$ git checkout master $ git checkout -b issue-101
現在修復bug,需要把“Git is free software …”改為“Git is a free software …”,然後提交:
$ git add readme.txt $ git commit -m "fix bug 101"
修復完成後,切換到master
分支,並完成合並,最後刪除issue-101
分支:
$ git checkout master $ git merge --no-ff -m "merged bug fix 101" issue-101 $ git branch -d issue-101
太棒了,原計劃兩個小時的bug修復只花了5分鐘!現在,是時候接著回到dev
分支幹活了!
$ git checkout dev Switched to branch 'dev' $ git status # On branch dev nothing to commit (working directory clean)
工作區是乾淨的,剛才的工作現場存到哪去了?用git stash list
命令看看:
$ git stash list stash@{0}: WIP on dev: 6224937 add merge
工作現場還在,Git把stash
內容存在某個地方了,但是需要恢復一下,有兩個辦法:
**一種方式:**用git stash apply
恢復,但是恢復後,stash
內容並不刪除,你需要用git stash drop
來刪除;
**另一種方式:**是用git stash pop
,恢復的同時把stash
內容也刪了:
$ git stash pop # On branch dev # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: hello.py # # Changes not staged for commit: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: readme.txt # Dropped refs/stash@{0} (f624f8e5f082f2df2bed8a4e09c12fd2943bdd40)
再用git stash list
檢視,就看不到任何stash內容了:
$ git stash list
你可以多次stash,恢復的時候,先用git stash list
檢視,然後恢復指定的stash,用命令:
$ git stash apply stash@{0}
刪除分支
軟體開發中,總有無窮無盡的新的功能要不斷新增進來。
新增一個新功能時,你肯定不希望因為一些實驗性質的程式碼,把主分支搞亂了,所以,每新增一個新功能,最好新建一個feature分支,在上面開發,完成後,合併,最後,刪除該feature分支。
還記得嗎?
建立新的分支:git checkout -b feature-new
工作提交:git add --a
,git commit -m "something..."
回到dev
開發分支:git checkout dev
合併分支:git merge --no-ff feature-new
一切順利的話,feature分支和bug分支是類似的,合併,然後刪除。
但是,就在此時,接到上級命令,因經費不足,新功能必須取消!雖然白乾了,但是這個分支還是必須就地銷燬:
(1)如果沒有合併之前,可以簡單的使用git branch -d [分支名]
來刪除分支(使用-D
命令,強制刪除分支)
(2)如果已經合併,除了上面的需要刪除以外,還需要使用前面講到的git reset --hard HEAD^
來退回到上一個版本。
PS:分支的刪除,不會影響到其他分支上已經合併的分支內容。
多人協作
多人協作的工作模式通常是這樣:
首先,可以試圖用git push origin branch-name
推送自己的修改;
如果推送失敗,則因為遠端分支比你的本地更新,需要先用git pull
試圖合併;
如果合併有衝突,則解決衝突,並在本地提交;
沒有衝突或者解決掉衝突後,再用git push origin branch-name
推送就能成功!
如果git pull
提示“no tracking information”,則說明本地分支和遠端分支的連結關係沒有建立,用命令git branch --set-upstream branch-name origin/branch-name。
這就是多人協作的工作模式,一旦熟悉了,就非常簡單。
注:所有工作流建立在已經建立了個人賬戶,並新增了SSH key到個人的文件中。見Profile Settings → SSH keys → Before you can add an SSH key you need to [generate it].
-
普通開發人員
情況一:程式設計師A是後加入到專案中的,專案已經存在程式碼倉庫。
如:
(1)克隆版本倉庫
git clone git@github.com:kanlidy/HelloGit.git
(2)建立分支
git checkout -b (分支名)
(3)提交程式碼
檢視程式碼修改的狀態:
git status
新增到工作區:
git add .
提交到本地倉庫:
git commit -m "(寫下提交日誌)"
推送到伺服器:
git push origin 分支名
(4)在伺服器上建立Merge Request,把自己的提交到遠端的分支,Merge到Dev(開發分支)
情況二:程式設計師B是在一個新專案中,本地有一些程式碼,需要建立一個版本控制倉庫
(1)在專案目錄下,初始化倉庫
git init
(2)新增到git版本控制系統:
git remote add origin git@github.com:kanlidy/HelloGit.git
(3)新增所有已經存在的檔案到專案中:
git add .
(4)提交程式碼到本地倉庫:
git commit -m "寫下日誌"
(5)提交程式碼遠端伺服器
git push origin <本地分支名>:<遠端分支名> git push origin master:master
對於單人專案,情況二足以滿足程式碼控制要求。→呂揚、劉揚。
-
倉庫管理人員
情況一:手工合併程式碼
(1)在指定分支上獲取更新
git checkout <指定分支>
(2)拉取伺服器上的程式碼
git pull origin <指定分支>
(3)切換到dev,並獲取dev上的更新,合併指定分支上的程式碼
git checkout dev git pull origin dev git merge <指定分支>
情況二:直接在gitlab上進行操作
直接點選accept merge request進行分支合併。
程式碼回撤參考
git reset
命令,獲取更新參考git fetch
命令,分支檢視git branch
,邏輯流程圖gitk
,狀態命令git status
,日誌命令git reflog
與git log
參考資料:
Git常用命令
這一部分介紹了git的常用命令,如git clone、git pull、git push等等。
git clone
該命令會在本地主機生成一個目錄,與遠端主機的版本庫同名。如果要指定不同的目錄名,可以將目錄名作為git clone
命令的第二個引數。
克隆倉庫git clone的語法:
$ git clone <版本庫的網址> <本地目錄名>
git clone支援多種協議,除了HTTP(s)以外,還支援SSH、Git、本地檔案協議等,下面是一些例子。
$ git clone http[s]://example.com/path/to/repo.git/ $ git clone ssh://example.com/path/to/repo.git/ $ git clone git://example.com/path/to/repo.git/ $ git clone /opt/git/project.git $ git clone file:///opt/git/project.git $ git clone ftp[s]://example.com/path/to/repo.git/ $ git clone rsync://example.com/path/to/repo.git/
SSH協議還有另一種寫法。
$ git clone [user@]example.com:path/to/repo.git/
還可以使用-b
和標籤名來克隆指定的分支和tags
:
git clone -b r01
git remote
為了便於管理,Git要求每個遠端主機都必須指定一個主機名。git remote
命令就用於管理主機名。
不帶選項的時候,git remote
命令列出所有遠端主機。
$ git remote origin
使用-v選項,可以參看遠端主機的網址。
$ git remote -v origin git@github.com:jquery/jquery.git (fetch) origin git@github.com:jquery/jquery.git (push)
上面命令表示,當前只有一臺遠端主機,叫做origin,以及它的網址。
克隆版本庫的時候,所使用的遠端主機自動被Git命名為origin。如果想用其他的主機名,需要用git clone
命令的-o
選項指定。
$ git clone -o jQuery $ git remote jQuery
上面命令表示,克隆的時候,指定遠端主機叫做jQuery。git remote show
命令加上主機名,可以檢視該主機的詳細資訊。
$ git remote show <主機名> git remote add命令用於新增遠端主機。 $ git remote add <主機名> <網址> git remote rm命令用於刪除遠端主機。 $ git remote rm <主機名> git remote rename命令用於遠端主機的改名。 $ git remote rename <原主機名> <新主機名>
git fetch
一旦遠端主機的版本庫有了更新(Git術語叫做commit),需要將這些更新取回本地,這時就要用到git fetch命令。
$ git fetch <遠端主機名>
上面命令將某個遠端主機的更新,全部取回本地。git fetch
命令通常用來檢視其他人的程式,因為它取回的程式碼對你本地的開發程式碼沒有影響。
預設情況下,git fetch取回所有分支(branch)的更新。如果只想取回特定分支的更新,可以指定分支名。
$ git fetch <遠端主機名> <分支名>
比如,取回origin主機的master分支。
$ git fetch origin master
所取回的更新,在本地主機上要用”遠端主機名/分支名”的形式讀取。比如origin主機的master,就要用origin/master讀取。git branch
命令的-r
選項,可以用來檢視遠端分支,-a
選項檢視所有分支。
$ git branch -r origin/master $ git branch -a * master remotes/origin/master
上面命令表示,本地主機的當前分支是master,遠端分支是origin/master。
取回遠端主機的更新以後,可以在它的基礎上,使用git checkout
命令建立一個新的分支。
$ git checkout -b newBrach origin/master
上面命令表示,在origin/master的基礎上,建立一個新分支。
此外,也可以使用git merge
命令或者git rebase
命令,在本地分支上合併遠端分支。
$ git merge origin/master # 或者 $ git rebase origin/master
上面命令表示在當前分支上,合併origin/master。
git pull
git pull
命令的作用是,取回遠端主機某個分支的更新,再與本地的指定分支合併。它的完整格式稍稍有點複雜。
$ git pull <遠端主機名> <遠端分支名>:<本地分支名>
比如,取回origin主機的next分支,與本地的master分支合併,需要寫成下面這樣。
$ git pull origin next:master
如果遠端分支是與當前分支合併,則冒號後面的部分可以省略。
$ git pull origin next
上面命令表示,取回origin/next分支,再與當前分支合併。實質上,這等同於先做git fetch
,再做git merge
。
$ git fetch origin $ git merge origin/next
在某些場合,Git會自動在本地分支與遠端分支之間,建立一種追蹤關係(tracking)。比如,在git clone
的時候,所有本地分支預設與遠端主機的同名分支,建立追蹤關係,也就是說,本地的master分支自動”追蹤”origin/master分支。
Git也允許手動建立追蹤關係。
git branch --set-upstream master origin/next
上面命令指定master分支追蹤origin/next分支。
如果當前分支與遠端分支存在追蹤關係,git pull就可以省略遠端分支名。
$ git pull origin
上面命令表示,本地的當前分支自動與對應的origin主機”追蹤分支”(remote-tracking branch)進行合併。
如果當前分支只有一個追蹤分支,連遠端主機名都可以省略。
$ git pull
上面命令表示,當前分支自動與唯一一個追蹤分支進行合併。
如果合併需要採用rebase模式,可以使用--rebase
選項。
$ git pull --rebase <遠端主機名> <遠端分支名>:<本地分支名>
如果遠端主機刪除了某個分支,預設情況下,git pull
不會在拉取遠端分支的時候,刪除對應的本地分支。這是為了防止,由於其他人操作了遠端主機,導致git pull不知不覺刪除了本地分支。
但是,你可以改變這個行為,加上引數 -p 就會在本地刪除遠端已經刪除的分支。
$ git pull -p # 等同於下面的命令 $ git fetch --prune origin $ git fetch -p
git push
git push
命令用於將本地分支的更新,推送到遠端主機。它的格式與git pull
命令相仿。
$ git push <遠端主機名> <本地分支名>:<遠端分支名>
注意,分支推送順序的寫法是<來源地>:<目的地>,所以git pull是<遠端分支>:<本地分支>,而git push
是<本地分支>:<遠端分支>
。
如果省略遠端分支名,則表示將本地分支推送與之存在”追蹤關係”的遠端分支(通常兩者同名),如果該遠端分支不存在,則會被新建。
$ git push origin master
上面命令表示,將本地的master分支推送到origin主機的master分支。如果後者不存在,則會被新建。
如果省略本地分支名,則表示刪除指定的遠端分支,因為這等同於推送一個空的本地分支到遠端分支。
$ git push origin :master # 等同於 $ git push origin --delete master
上面命令表示刪除origin主機的master分支。
如果當前分支與遠端分支之間存在追蹤關係,則本地分支和遠端分支都可以省略。
$ git push origin
上面命令表示,將當前分支推送到origin主機的對應分支。
如果當前分支只有一個追蹤分支,那麼主機名都可以省略。
$ git push
如果當前分支與多個主機存在追蹤關係,則可以使用-u選項指定一個預設主機,這樣後面就可以不加任何引數使用git push
。
$ git push -u origin master
上面命令將本地的master分支推送到origin主機,同時指定origin為預設主機,後面就可以不加任何引數使用git push
了。
不帶任何引數的git push
,預設只推送當前分支,這叫做simple方式。此外,還有一種matching方式,會推送所有有對應的遠端分支的本地分支。Git 2.0版本之前,預設採用matching方法,現在改為預設採用simple方式。如果要修改這個設定,可以採用git config命令。
$ git config --global push.default matching # 或者 $ git config --global push.default simple
還有一種情況,就是不管是否存在對應的遠端分支,將本地的所有分支都推送到遠端主機,這時需要使用–all選項。
$ git push --all origin
上面命令表示,將所有本地分支都推送到origin主機。
如果遠端主機的版本比本地版本更新,推送時Git會報錯,要求先在本地做git pull
合併差異,然後再推送到遠端主機。這時,如果你一定要推送,可以使用--force
選項。
$ git push --force origin
上面命令使用--force
選項,結果導致遠端主機上更新的版本被覆蓋。除非你很確定要這樣做,否則應該儘量避免使用--force
選項。
最後,git push
不會推送標籤(tag),除非使用--tags
選項。
$ git push origin --tags
以上就是關於Git你需要知道的知識點啦,掌握以上知識點,你在工作上就可以輕鬆玩轉Git版本控制了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4687/viewspace-2825742/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- redis相關知識點Redis
- shell相關知識點
- Oracle 相關知識點Oracle
- 【Java】容器相關知識點Java
- ivar layout 相關知識點
- LR模型相關知識點模型
- ARP相關知識點
- React相關知識點:關於ReduxReactRedux
- Java容器相關知識點整理Java
- 總結 MySQL 相關知識點MySql
- JVM相關知識點總結JVM
- UIBarButtonItem的相關知識點UI
- library cache相關知識點
- Extjs相關知識點梳理JS
- tmpwatch相關的知識點
- git 知識點Git
- 面試系列之View相關知識點面試View
- 資料庫相關知識點提要資料庫
- oracle檢查點的相關知識Oracle
- GreatSQL統計資訊相關知識點SQL
- Git 關鍵知識Git
- Fragment 相關知識點都在這裡了Fragment
- PHP物件相關知識點的總結PHP物件
- rman配置及常用操作相關知識點
- 異常處理及其相關知識點
- Shell相關知識
- .net相關知識
- mobile相關知識
- rollback相關知識
- Java併發相關知識點梳理和研究Java
- 資料庫相關知識點(秋招整理)資料庫
- 遊戲伺服器開發相關知識點遊戲伺服器
- C++中類相關知識點總結C++
- 音訊相關知識音訊
- Elasticsearch——search相關知識Elasticsearch
- SSL相關知識科普
- Redis的相關知識Redis
- RPM相關知識