標(biāo)簽: Git
描寫性文字:
不要問(wèn)我為何用這類騷豬風(fēng)格的標(biāo)題,現(xiàn)在寫博文,標(biāo)題不騷,人家都不樂(lè)意看~
接觸Git到現(xiàn)在有1年多了,對(duì)Git使用也是日漸精進(jìn),雖然說(shuō)不上很熟絡(luò),但也算
入門,決定年前總結(jié)下,所以有了此文。Git博大精深,還有很多的東西需要學(xué)習(xí),
比如自己搭建啊,1些便利工具的使用啊,1些疑問(wèn)雜癥解決方案啊等等,固然
這就是下1話的事了。本文講述的是Git基礎(chǔ)的1些東西,沒(méi)有Git大法那個(gè)系列
那末通熟易懂,但是還是對(duì)關(guān)鍵性的知識(shí)點(diǎn)進(jìn)行了淺析,相信看完本文你的Git
使用會(huì)更進(jìn)1步,謝謝~
按大類劃分,分為兩種狀態(tài):Tracked(已跟蹤)和Untracked(未跟蹤),
根據(jù)是:該文件是不是已加入版本控制?
流程簡(jiǎn)述:
假定某個(gè)項(xiàng)目已加入版本控制系統(tǒng)
- 1.新建1個(gè)文件,該文件處于 Untracked 狀態(tài);
- 2.通過(guò)git add命令添加到緩存區(qū),此時(shí)文件處于Tracked狀態(tài)又或說(shuō)
此時(shí)這個(gè)文件已被版本控制系統(tǒng)所跟蹤,而且他處于Staged(暫存)狀態(tài);- 3.通過(guò)git commit命令把暫存區(qū)的文件提交提交到本地倉(cāng)庫(kù),此時(shí)文件
處于Unmodified(未修改)狀態(tài);- 4.此時(shí)如果去編輯這個(gè)文件,文件又會(huì)變成Modified(修改)狀態(tài);
Git關(guān)心的是:文件整體是不是產(chǎn)生變化,而SVN關(guān)心的是:文件內(nèi)容的具體差異!
SVN每次提交記錄的是:哪些文件進(jìn)行了修改,和修改了哪些行的哪些內(nèi)容
如圖:版本2中記錄的是文件A和C的變化,而版本3中記錄文件C的變化,以此類推;
而Git中,其實(shí)不保存這些前后變化的差異數(shù)據(jù),而是保證全部緩存區(qū)中的所有文件,
又叫快照,有變化的文件保存,沒(méi)變化的文件不保存,而是對(duì)上1次的保存的快照
做1個(gè)鏈接!由于這類不同的保存方式,Git切換分支的速度比SVN快很多!
分為4個(gè)對(duì)象:
blob對(duì)象:寄存文件數(shù)據(jù);
tree對(duì)象:目錄,內(nèi)容為blob對(duì)象的指針或其他tree對(duì)象的指針
commit對(duì)象:快照,包括指向前1次提交對(duì)象的指針,commit相干的信
通過(guò)索引找到文件快照。
tag對(duì)象:1種特殊的commit對(duì)象,1般對(duì)某次重要的commit加TAG,以示重要(方便找)
辨別global 和 local,前者代表 全局設(shè)置,就是設(shè)置了在全部系統(tǒng)中,
所有的帶Git版本管理的項(xiàng)目都是這樣的配置;后者代表 本地設(shè)置 即在某個(gè)項(xiàng)目
中獨(dú)立的設(shè)置,后者優(yōu)先級(jí)高于前者。比如全局設(shè)置的用戶名是”Coder-pig”,本地
設(shè)置的是”Jay”,commit的時(shí)候author就是Jay而不是Coder-pig。
處理命令行,還可以直接修改對(duì)應(yīng)文件:
全局配置文件:etc/gitconfig
本地配置文件:當(dāng)前倉(cāng)庫(kù)/.git/config
# 安裝完Git后第1件要做的事,設(shè)置用戶信息(global可換成local在單獨(dú)項(xiàng)陌生效): git config --global user.name "用戶名" # 設(shè)置用戶名 git config --global user.email "用戶郵箱" #設(shè)置郵箱 git config --global user.name # 查看用戶名是不是配置成功 git config --global user.name # 查看郵箱是不是配置 # 其他查看配置相干 git config --global --list # 查看全局設(shè)置相干參數(shù)列表 git config --local --list # 查看本地設(shè)置相干參數(shù)列表 git config --system --list # 查看系統(tǒng)配置參數(shù)列表 git config --list # 查看所有Git的配置(全局+本地+系統(tǒng))
git help 命令 # 如:git help init
git init 倉(cāng)庫(kù)名 # 創(chuàng)建1個(gè)新的帶Git倉(cāng)庫(kù)的項(xiàng)目 git init # 為已存在的項(xiàng)陌生成1個(gè)Git倉(cāng)庫(kù)
可使用git add 文件名,將工作空間的文件添加到暫存區(qū),或批量添加文件
git add 文件名 # 將工作區(qū)的某個(gè)文件添加到暫存區(qū) git add -u # 添加所有被tracked文件中被修改或刪除的文件信息到暫存區(qū),不處理untracked的文件 git add -A # 添加所有被tracked文件中被修改或刪除的文件信息到暫存區(qū),包括untracked的文件 git add . # 將當(dāng)前工作區(qū)的所有文件都加入暫存區(qū) git add -i # 進(jìn)入交互界面模式,按需添加文件到緩存區(qū)
附:交互界面模式示例
上圖流程:
1.先在GitForTest的文件夾里創(chuàng)建了兩個(gè)文件
2.鍵入git add -i,進(jìn)入后,鍵入4,選擇添加untracked的文件
3.他給我們列出了untracked的文件,然后我們根據(jù)序號(hào)來(lái)添加文件
4.輸入?會(huì)彈出相干提示,然后直接回車,結(jié)束選擇!
5.然后再次輸入git add -i,輸入4,可以看到已不存在untacked的文件了!
將未tracked的文件添加到緩存區(qū)后,Git就會(huì)開(kāi)始跟蹤這個(gè)文件了!
對(duì)1些比如:自動(dòng)生成的文件,日志,臨時(shí)編譯文件等,就
沒(méi)必要進(jìn)行跟蹤了,這個(gè)時(shí)候可以編寫.gitignore文件,在里面
把不需要跟蹤的文件或文件夾都寫上,git就不會(huì)對(duì)這些文件進(jìn)行跟蹤!
另外.gitignore文件與.git文件夾在同級(jí)目錄下!
如果不想自己寫,可以直接到:https://github.com/github/gitignore 復(fù)制粘貼!
也能夠自行編寫,支持簡(jiǎn)化了的正則表達(dá)式(規(guī)范與示例模板摘自:Git王者超神之路)
- * : 匹配零個(gè)或多個(gè)任意字符
- [abc]:只匹配括號(hào)內(nèi)中的任意1個(gè)字符
- [0⑼]:- 代表范圍,匹配0⑼之間的任何字符
- ?:匹配任意1個(gè)字符
- *:匹配任意的中間目錄,例如a/*/z可以匹配:a/z,a/b/z,a/b/c/z等
示例模板:
# 疏忽所有以 .c結(jié)尾的文件 *.c # 但是 stream.c 會(huì)被git追蹤 !stream.c # 只疏忽當(dāng)前文件夾下的TODO文件, 不包括其他文件夾下的TODO例如: subdir/TODO /TODO # 疏忽所有在build文件夾下的文件 build/ # 疏忽 doc/notes.txt, 但不包括多層下.txt例如: doc/server/arch.txt doc/*.txt
# 疏忽所有在doc目錄下的.pdf文件
doc/**/*.pdf
git commit -m "提交說(shuō)明" # 將暫存區(qū)內(nèi)容提交到本地倉(cāng)庫(kù) git commit -a -m "提交說(shuō)明" # 跳過(guò)緩存區(qū)操作,直接把工作區(qū)內(nèi)容提交到本地倉(cāng)庫(kù)
如果不加-m “提交說(shuō)明”,git會(huì)讓用你讓默許編輯器(如vi)來(lái)編寫提交說(shuō)明,
vi難用(最少我不會(huì)用),要末別漏掉-m “提交說(shuō)明”,要末自己設(shè)置編譯器:
git config --global core.edit 喜歡的編輯器
除此以外,有時(shí)可能需要修改上次提交的內(nèi)容,比如修改提交說(shuō)明,或修改文件等:
# 合并暫存區(qū)和最近的1次commit,生成新的commit并替換掉老的
# 如果緩存區(qū)沒(méi)內(nèi)容,利用amend可以修改上次commit的提交說(shuō)明
# 注:由于amend后生成的commit是1個(gè)全新的commit,舊的會(huì)被
# 刪除,所以別在公共的commit上使用amend!切記!
git commit --amend
git commit --amend --no-edit # 沿用上次commit的提交說(shuō)明
git status # 查看工作區(qū)與暫存區(qū)確當(dāng)前情況 git status -s # 讓結(jié)果以更簡(jiǎn)短的情勢(shì)輸出
git diff # 工作區(qū)與緩存區(qū)的差異 git diff 分支名 #工作區(qū)與某分支的差異,遠(yuǎn)程分支這樣寫:remotes/origin/分支名 git diff HEAD # 工作區(qū)與HEAD指針指向的內(nèi)容差異 git diff 提交id 文件路徑 # 工作區(qū)某文件當(dāng)前版本與歷史版本的差異 git diff --stage # 工作區(qū)文件與上次提交的差異(1.6 版本前用 --cached) git diff 版本TAG # 查看從某個(gè)版本后都改動(dòng)內(nèi)容 git diff 分支A 分支B # 比較從分支A和分支B的差異(也支持比較兩個(gè)TAG) git diff 分支A...分支B # 比較兩分支在分開(kāi)后各自的改動(dòng) # 另外:如果只想統(tǒng)計(jì)哪些文件被改動(dòng),多少行被改動(dòng),可以添加 --stat 參數(shù)
git log # 查看所有commit記錄(SHA-A校驗(yàn)和,作者名稱,郵箱,提交時(shí)間,提交說(shuō)明) git log -p -次數(shù) # 查看最近多少次的提交記錄 git log --stat # 簡(jiǎn)略顯示每次提交的內(nèi)容更改 git log --name-only # 僅顯示已修改的文件清單 git log --name-status # 顯示新增,修改,刪除的文件清單 git log --oneline # 讓提交記錄以精簡(jiǎn)的1行輸出 git log –graph –all --online # 圖形展現(xiàn)分支的合并歷史 git log --author=作者 # 查詢作者的提交記錄(和grep同時(shí)使用要加1個(gè)--all--match參數(shù)) git log --grep=過(guò)濾信息 # 列出提交信息中包括過(guò)濾信息的提交記錄 git log -S查詢內(nèi)容 # 和--grep類似,S和查詢內(nèi)容間沒(méi)有空格 git log fileName # 查看某文件的修改記錄,找背鍋專用
除此以外,還可以通過(guò) –pretty 對(duì)提交信息進(jìn)行定制,比如:
更多規(guī)則與定制以下(摘自:Git王者超神之路),或參見(jiàn):Viewing the Commit History:
format對(duì)應(yīng)的經(jīng)常使用占位符:(注:作者是指最后1次修改文件的人,提交者是提交該文件的人)
占位符 | 說(shuō)明 | 占位符 | 說(shuō)明 |
---|---|---|---|
%H | 提交對(duì)象(commit)的完全哈希字串 | %h | 提交對(duì)象的簡(jiǎn)短哈希字串 |
%T | 樹(shù)對(duì)象(tree)的完全哈希字串 | %t | 樹(shù)對(duì)象的簡(jiǎn)短哈希字串 |
%P | 父對(duì)象(parent)的完全哈希字串 | %p | 父對(duì)象的簡(jiǎn)短哈希字串 |
%an | 作者(author)的名字 | %ae | 作者的電子郵件地址 |
%ad | 作者修訂日期(可以用 –date= 選項(xiàng)定制格式) | %ar | 按多久之前的方式顯示 |
%cn | 提交者(committer)的名字 | %ce | 提交者的電子郵件地址 |
%cd | 提交日期 | %cr | 提交日期,按多久之前的方式顯示 |
%s | 提交說(shuō)明 |
|
|
1些其他操作:
選項(xiàng) | 說(shuō)明 |
---|---|
-p | 按補(bǔ)釘格式顯示每一個(gè)更新之間的差異 |
–stat | 顯示每次更新的文件修改統(tǒng)計(jì)信息(行數(shù)) |
–shortstat | 只顯示 –stat 中最后的行數(shù)修改添加移除統(tǒng)計(jì) |
–name-only | 僅在提交信息后顯示已修改的文件清單 |
–name-status | 顯示新增、修改、刪除的文件清單 |
–abbrev-commit | 僅顯示 SHA⑴ 的前幾個(gè)字符,而非所有的 40 個(gè)字符 |
–relative-date | 使用較短的相對(duì)時(shí)間顯示(比如,“2 weeks ago”) |
–graph | 顯示 ASCII 圖形表示的分支合并歷史 |
–pretty | 格式定制,可選選項(xiàng)有:oneline,short,full,F(xiàn)ullerton和format(后跟指定格式) |
還有1些限制log輸出的選項(xiàng)
選項(xiàng) | 說(shuō)明 |
---|---|
-(n) | 僅顯示最近的 n 條提交 |
–since, –after | 僅顯示指定時(shí)間以后的提交。 |
–until, –before | 僅顯示指定時(shí)間之前的提交。 |
–author | 僅顯示指定作者相干的提交。 |
–committer | 僅顯示指定提交者相干的提交。 |
–grep | 僅顯示含指定關(guān)鍵字的提交 |
-S | 僅顯示添加或移除某個(gè)關(guān)鍵字的提交 |
git brame 文件名 # 查看某文件的每行代碼的作者,最新commit和提交時(shí)間
可以為常見(jiàn)的命令起個(gè)簡(jiǎn)單的別名,就不用每次都敲完全命令,比如可以設(shè)置:
status為st,checkout為co ; commit為ci ; branch為br等
git config --global alias.st status
對(duì)某些提交,我們可以為它打上Tag,表示這次提交很重要,
比如為1些正式發(fā)布大版本的commit,打上TAG,當(dāng)某個(gè)版本
出問(wèn)題了,通過(guò)TAG可以快速找到此次提交,拿到SHA1值,再
去查找問(wèn)題,比起1個(gè)個(gè)commit看,省事很多!
Git標(biāo)簽分兩種:輕量標(biāo)簽 和 附加標(biāo)簽
前者只是在提交上加個(gè)Tag,指向提交的Hash值;
而后者還會(huì)保存打標(biāo)簽者的信息,時(shí)間和附加信息;
git tag 標(biāo)記內(nèi)容 # 輕量標(biāo)簽 git tag -a 標(biāo)記內(nèi)容 -m "附加信息" # 附加標(biāo)簽
如果想為之前的某次commit打TAG的話,可以先找出SHA1值,設(shè)置調(diào)下述命令:
git tag -a 標(biāo)記內(nèi)容 版本id # 比如:git tag -a v1.1 bcfed96
默許情況,git push不會(huì)把標(biāo)簽推送TAG到遠(yuǎn)程倉(cāng)庫(kù),如果想推送到服務(wù)器,可以:
git push origin 標(biāo)記內(nèi)容 # 推送某標(biāo)簽到 # 刪除所有本地倉(cāng)庫(kù)中不存在的TAG: git push origin --tags
另外,可以在新建分支的時(shí)候也加上TAG
git checkout -b 分支名 標(biāo)記內(nèi)容
最后,還可以用show命令查看標(biāo)簽對(duì)應(yīng)的信息
git show 標(biāo)記內(nèi)容
如果在工作區(qū)直接刪除被Git Tracked的文件,暫存區(qū)中還會(huì)存在該文件,
此時(shí)鍵入:git status,會(huì)是這樣:
Git告知你工作區(qū)的文件被刪除,你可以 刪掉暫存區(qū)里的文件或 恢復(fù)被刪文件
# 刪除暫存區(qū)中的文件: git rm 文件名
git commit -m "提交說(shuō)明" # 誤刪恢復(fù)文件 git checkout -- 文件名 # 另外注意:git checkout會(huì)拋棄當(dāng)前工作區(qū)的更改!!!不可恢復(fù)?。。?wù)必謹(jǐn)慎?。?!
如果更改后add到了暫存區(qū),想恢復(fù)原狀,下述指令可讓文件恢復(fù)原狀:
git reset HEAD 文件名
git checkout 文件名
文件已commit了,想恢復(fù)成上次commit的版本或上上次,可以:
git reset HEAD^ # 恢復(fù)成上次提交的版本 git reset HEAD^^ # 恢復(fù)成上上次提交的版本,就是多個(gè)^,以此類推或用~次數(shù) git reset --hard 版本號(hào) # git log查看到的SHA1值,取前7位便可,根據(jù)版本號(hào)回退
reset命令其實(shí)就是:重置HEAD指針,讓其指向另外一個(gè)commit
而這個(gè)動(dòng)作可能會(huì)對(duì)工作區(qū)與緩存區(qū)造成影響,舉個(gè)例子
- 本來(lái)的分支線:- A - B - C (HEAD, master)
- git reset B后:- A - B (HEAD, master)
解釋:看不到C了,但是他還是存在的,可以通過(guò)git reset C版本號(hào)找回,條件是
C沒(méi)有被Git當(dāng)作垃圾處理掉(1般是30天)。
reset3個(gè)可選參數(shù)解析:
- –soft:只是改變HEAD指針指向,緩存區(qū)和工作區(qū)不變;
- –mixed:修改HEAD指針指向,暫存區(qū)內(nèi)容丟失,工作區(qū)不變;
- –hard:修改HEAD指針指向,暫存區(qū)內(nèi)容丟失,工作區(qū)恢復(fù)之前狀態(tài);
Git會(huì)記住你輸入的每一個(gè)Git指令,比如上面的git reset 切換成1個(gè)舊的
commit,然后git log后發(fā)現(xiàn)新提交的記錄沒(méi)了,想切換回新的那次commit,
可以先調(diào)git reflog 獲得新commit的SHA1碼,然后git reset 回去。
git reflog
注意:這個(gè)指令記錄不會(huì)永久保存!Git會(huì)定時(shí)清算用不到的對(duì)象!!!
有時(shí)可能我們想撤消某次提交所做的更改,可使用revert命令
git revert HEAD # 撤消最近的1個(gè)提交 git revert 版本號(hào) # 撤消某次commit
不是真的把提交給撤消了,而是生成1個(gè)新的提交來(lái)覆蓋舊的提交,被撤消的提交
和新的提交記錄都會(huì)保存?。?!不信你再調(diào)1次revert HEAD 會(huì)發(fā)現(xiàn)被撤消的更改
又變回來(lái)了,另外,每次revert后,都需要發(fā)起新的commit!
簡(jiǎn)單點(diǎn)說(shuō),撤消的只是文件變化,提交記錄照舊是存在的!
git show 提交id # 查看某次commit的修改內(nèi)容
git rev-parse 分支名 # 查看分支commit的版本號(hào),可以寫HEAD
由于你的某次誤操作致使commit丟失,如果git reflog都找不到,你
可以斟酌使用git fsck,找到丟失的對(duì)象的版本id,然后恢復(fù)便可。
git fsck --lost-found
提交記錄串成的時(shí)間線,默許初始創(chuàng)建的分支(時(shí)間線) —— master分支,
如果不切換到其他分支上,每次commit生成的快照都會(huì)串在這條分支上!
另外還有個(gè) —— HEAD指針,該指針指向正在工作的本地分支,前面的版
本回退其實(shí)修改的就是這個(gè)HEAD指針的指向!
比如:在master分支上履行4次commit,分支的狀態(tài)圖以下
不難發(fā)現(xiàn)這樣的規(guī)律:
- 每次commit,master都會(huì)向前移動(dòng)1步,指向最新的提交
- HEAD則指向正在工作的本地分支,而git reset修改的就是HEAD指針的指向!
通過(guò)兩個(gè)場(chǎng)景來(lái)體會(huì)創(chuàng)建其他分支的必要性
- 場(chǎng)景1:
項(xiàng)目1般都是1步步迭代升級(jí)的,有大版本和小版本的更新:大版本1般是改
頭換面的更新,比如UI大改,架構(gòu)大改,版本是:v2.0.0這樣;小版本的更新
1般是UI小改,Bug修復(fù)優(yōu)化等,版本是:v2.0.11這樣;
只有1條master分支,意味著:你的分支線會(huì)非常非常的長(zhǎng),假設(shè)你已發(fā)布
到了第2個(gè)大版本,然后用戶反饋第1個(gè)版本有很嚴(yán)重的BUG,這時(shí)候候想切回
第1個(gè)版本改BUG,然后改完BUG切會(huì)第2個(gè)大版本,想一想夠戧。- 場(chǎng)景2:
只有1個(gè)master分支的話,假設(shè)某次提交沖突了,而這個(gè)沖突很難解決或
解決不了, 那末,那個(gè)全部開(kāi)發(fā)就卡住在這里了,沒(méi)法繼續(xù)向落后行了!
為了解決只有1個(gè)master分支引發(fā)的問(wèn)題,可以引入分支管理,最簡(jiǎn)單的1種策略以下:
在master分支上開(kāi)辟1個(gè)新的develop分支,然后我們根據(jù)功能或業(yè)務(wù),再在develop
分支上另外開(kāi)辟其他分支,完成份支上的任務(wù)后,再將這個(gè)分支合并到develop分支上!
master與develop分支都作為長(zhǎng)時(shí)間分支,而其他創(chuàng)建的分支作為臨時(shí)性分支!
簡(jiǎn)述各個(gè)分支的劃分:
git branch 分支名 # 創(chuàng)建分支 git branch # 查看本地分支
比如在master分支上創(chuàng)建develop分支,此時(shí)的分支狀態(tài)以下:
git checkout 分支名 # 切換分支 git checkout -b 分支名 # 創(chuàng)建分支同時(shí)切換到這個(gè)分支
切換到develop分支后,改點(diǎn)東西,再commit,此時(shí)的分支狀態(tài)以下:
git checkout master 切回master分支,打開(kāi)之前修改的文件,發(fā)現(xiàn)內(nèi)容
并沒(méi)有產(chǎn)生更改,由于剛剛的更改是在develop上提交的,而master上沒(méi)有
變化,此時(shí)的分支狀態(tài)以下:
Git中,可使用 git merge 和 git rebase 兩個(gè)命令來(lái)進(jìn)行分支的合并
git merge合并分支
合并的方式分為兩種:快速合并 和 普通合并,二者的區(qū)分在于:
前者合并后看不出曾做過(guò)合并,而后合并后的歷史會(huì)有分支記錄,如圖:
快速合并: 普通合并 :
示例:
快速合并,把develop分支合并到master分支上,來(lái)到master分支后,鍵入下述命令
git merge develop
打開(kāi)文件:
普通合并,切到develop分支下,修改note_2.txt的內(nèi)容,再通過(guò)下述指令合并分支:
注:–no-ff參數(shù)表示禁用快速合并!
git merge --no-ff -m "合并的信息(TAG)" develop
分支線情況:
git reabse合并分支
rebase(衍合),發(fā)現(xiàn)很多所謂的教程把這個(gè)東西寫得太深?yuàn)W了,其實(shí)并沒(méi)有
那末復(fù)雜,只是這類合并會(huì)使得樹(shù)整潔,易于跟蹤,舉個(gè)簡(jiǎn)單的例子來(lái)對(duì)照下
有1個(gè)項(xiàng)目由兩個(gè)人同時(shí)開(kāi)發(fā), 當(dāng)前遠(yuǎn)程倉(cāng)庫(kù)的提交記錄是這樣的:
然后A和B各自開(kāi)了1個(gè)條分支來(lái)完成相應(yīng)功能,接著他們?cè)谧约旱?
分支上都做了屢次的commit,此時(shí)兩人的分別分支線是這樣的:
A先合并,再到B合并,這里我們假定兩人做的是完全不關(guān)聯(lián)的模塊,合并沒(méi)有沖突
merge合并
rebase合并
用法:
git rebase 想合并到哪一個(gè)分支的分支名
在我們合并分支的時(shí)候,有時(shí)會(huì)遇到合并沖突,然后合并失敗的問(wèn)題,
此時(shí)需要我們先解決沖突后才能進(jìn)行合并,個(gè)人開(kāi)發(fā)倒很少會(huì)遇到,多人
開(kāi)發(fā)的時(shí)候遇到合并沖突則是家常便飯。
1個(gè)最簡(jiǎn)單的例子,A和B在develop分支上開(kāi)辟出兩個(gè)分支來(lái)完成相干的
功能,A做完了,把自己的分支合并到develop分支,此時(shí)develop分支向前
移動(dòng)了幾次commit,接著B(niǎo)也完成了他的功能,想把自己分支合并到develop
分支,如果改動(dòng)的文件和和A改動(dòng)的文件相同的話,此時(shí)就會(huì)合并失敗,
然后需要處理完沖突,才能夠繼續(xù)合并!簡(jiǎn)單摹擬下這個(gè)例子,先試試merge!
merge分支后處理沖突
打開(kāi)沖突文件,然后處理沖突部份,保存甚么代碼你自己決定,處理完后把
<<< 和 >>> 這些去掉:
處理后:
然后add,然后commit便可,合并結(jié)束:
此時(shí)的分支線:
接著試試
rebase分支后處理沖突
重新來(lái)1遍,然后把A直接merge到master,再切到B,rebase master,此時(shí)出現(xiàn)
合并沖突,這里有3個(gè)可選的操作:
git rebase --continue # 處理完沖突后,繼續(xù)處理下1個(gè)補(bǔ)釘 git rebase --abort # 放棄所有的沖突處理,恢復(fù)rebase前的情況 git rebase --skip # 跳過(guò)當(dāng)前的補(bǔ)釘,處理下1個(gè)補(bǔ)釘,不建議使用,補(bǔ)釘部份的commit會(huì)丟失!
好的,有3次補(bǔ)釘要處理,1個(gè)個(gè)來(lái):
處理后:
接著git add 添加修改后的文件,git rebase –continue繼續(xù)處理補(bǔ)釘:
接側(cè)重復(fù)之前的進(jìn)程:
處理后:
第3個(gè)補(bǔ)釘是與A分支無(wú)關(guān)聯(lián)的改動(dòng),所以沒(méi)有沖突,所以也就直接合并了!
如果合并中途出了甚么過(guò)失可以git rebase –abort 恢復(fù)rebase前的狀態(tài)!
最后看下分支線會(huì)發(fā)現(xiàn)是1條直線,這也是用rebase合并分支的優(yōu)點(diǎn):
附上栗子,可以自己試試:GitTest.7z
對(duì)合并完的分支,基本都沒(méi)甚么作用了,可使用下述命令刪除:
git branch -d 分支名 # 刪除分支,分支上有未提交更改是不能刪除的 git branch -D 分支名 # 強(qiáng)行刪除分支,雖然這個(gè)分支上有未提交的更改
兩步,找出被刪除分支的最新commit的版本號(hào),然后恢復(fù)分支
git log --branches="被刪除的分支名" # 找到被刪分支最新的commitb版本號(hào) git branch 分支名 版本號(hào)(前7位便可) # 恢復(fù)被刪分支
有時(shí)我們可能在某個(gè)分支上正編寫著代碼,然后有1些突發(fā)的情況,需要
我們暫時(shí)切換到其他分支上,比如要緊急修復(fù)bug,或切換分支給同事
review代碼,此時(shí)如果直接切換分支是會(huì)提示切換失敗的,由于這個(gè)分支
上做的更改還沒(méi)有提交,你可以直接add后commit,然后再切換,不過(guò)我們
習(xí)慣寫完某個(gè)功能再提交,我們想:
先暫存這個(gè)分支上的改動(dòng),切去其他分支上弄完事,然后回來(lái)繼續(xù)
繼續(xù)在之前的改動(dòng)上寫代碼。
那末可使用:
git stash # 保存當(dāng)前的改動(dòng)
然后放心的切換分支,然后再切換回來(lái),接著使用:
git stash apply # 恢復(fù)保存改動(dòng)
另外有1點(diǎn)1定要注意!??!可以stash多個(gè)改動(dòng)!!如果你切換
到另外一個(gè)分支又stash了,然后切換回來(lái)stash apply是恢復(fù)成另外一個(gè)
分支的stash?。。?
如果你這樣stash了屢次的話,我建議你先鍵入:
git stash list # 查看stash列表
找到自己想恢復(fù)的那個(gè)
比如我這里恢復(fù)的應(yīng)當(dāng)是netword上的stash,而第1個(gè)stash是devlop上的
直接git stash apply恢復(fù)的就是這個(gè),但是恢復(fù)的應(yīng)當(dāng)是network的那個(gè)stash:
git stash apply stash@{1}
就是這樣,按自己需要恢復(fù)便可!
git branch -m 老分支名 新分支名 # 分支重命名
用于代碼托管,可以自己搭建遠(yuǎn)程倉(cāng)庫(kù),或選擇專業(yè)的代碼托管平臺(tái):
自己搭建的好處有:可控,內(nèi)網(wǎng)安全,可以做1些定制,比如集成編譯,IM等,
固然,肯定是需要1些學(xué)習(xí)本錢的,(PS:我廠就是自己搭的Gitlab)
常見(jiàn)的代碼托管平臺(tái)(自己搜關(guān)鍵字去~):
Github,Git@OSC,GitCafe,GitLab,coding.net,gitc,BitBucket,Geakit,Douban CODE
首先建立好與本地倉(cāng)庫(kù)同名的遠(yuǎn)程倉(cāng)庫(kù),然后復(fù)制下遠(yuǎn)程倉(cāng)庫(kù)的地址,比如:
鍵入下述命令關(guān)聯(lián)本地與遠(yuǎn)程倉(cāng)庫(kù)
git remote add origin 遠(yuǎn)程倉(cāng)庫(kù)地址
可以鍵入下述命令可查看遠(yuǎn)程倉(cāng)庫(kù)狀態(tài)
接著把本地倉(cāng)庫(kù)推送到遠(yuǎn)程倉(cāng)庫(kù),這里的 -u參數(shù) 作為第1次提交使用,
作用是把本地master分支和遠(yuǎn)程master分支關(guān)聯(lián)起來(lái)(設(shè)置默許遠(yuǎn)程主機(jī)),
后續(xù)提交不需要這個(gè)參數(shù)!
git push -u origin master
另外,如果想修改遠(yuǎn)程倉(cāng)庫(kù)地址,可鍵入:
git remote set-url origin 遠(yuǎn)程倉(cāng)庫(kù)地址 # 也能夠先刪除origin后再添加 git remote rm origin # 刪除倉(cāng)庫(kù)關(guān)聯(lián) git remote add origin 遠(yuǎn)程倉(cāng)庫(kù)地址 # 添加倉(cāng)庫(kù)關(guān)聯(lián)
或直接修改.git文件夾中的config文件,直代替換圈住位置
還要說(shuō)明1點(diǎn),origin 其實(shí)不是固定的東西,只是后面倉(cāng)庫(kù)地址的1個(gè) 別名??!
可以寫成其他的東西,然后你也能夠設(shè)置多個(gè)倉(cāng)庫(kù)關(guān)聯(lián),用不同的別名標(biāo)志,比如:
git remote add github https://github.com/coder-pig/SimpleTea.git git remote add osc git@git.oschina.net:coder-pig/SimpleTea.git
把項(xiàng)目推送到遠(yuǎn)程倉(cāng)庫(kù)后,其他開(kāi)發(fā)者就能夠把項(xiàng)目clone到本地
git clone 倉(cāng)庫(kù)地址 # 克隆項(xiàng)目到當(dāng)前文件夾下 git clone 倉(cāng)庫(kù)地址 目錄名 # 克隆項(xiàng)目到特定目錄下
關(guān)于獲得遠(yuǎn)程服務(wù)器更新的方式有兩種,他們分別是fetch和pull,
雖然都可以獲得遠(yuǎn)程服務(wù)器更新,但是二者卻又是不1樣的。
git fetch:
僅僅只是從遠(yuǎn)處服務(wù)器獲得到最新版本到本地,假設(shè)你不去合并(merge)
的話,本地工作空間是不會(huì)產(chǎn)生變化的!比如:
我們?cè)贕ithub上創(chuàng)建1個(gè)README.md文件,然后調(diào) git fetch 去獲得遠(yuǎn)程
倉(cāng)庫(kù)的更新。
git pull:
1步到位,或說(shuō):pull = fetch + merge,比如:一樣修改Github上的
README.md 文件,然后git pull 同步遠(yuǎn)程倉(cāng)庫(kù)的更新
區(qū)分不言而喻,實(shí)際開(kāi)發(fā)中,使用git fetch會(huì)更安全1些,畢竟merge的時(shí)候
我們可以查看更新的情況,再?zèng)Q定是不是進(jìn)行合并,固然看實(shí)際需要吧!
依照前面所講,在本地開(kāi)辟分支來(lái)完成某些工作,本地提交了屢次后,
你想把分支推送到遠(yuǎn)程倉(cāng)庫(kù),此時(shí)遠(yuǎn)程倉(cāng)庫(kù)并沒(méi)有這個(gè)分支,你可以:
git push origin 分支名 # 推送本地分支的內(nèi)容到遠(yuǎn)程分支
git branch -r # 查看所有分支
git checkout -b 本地分支 遠(yuǎn)程分支 # 會(huì)在本地新建分支,并自動(dòng)切換到該分支 git fetch origin 遠(yuǎn)程分支:本地分支 # 會(huì)在本地新建分支,但不會(huì)自動(dòng)切換,還需checkout git branch --set-upstream 本地分支 遠(yuǎn)程分支 # 建立本地分支與遠(yuǎn)程分支的鏈接
git push origin :分支名 # 就是前面的本地分支名改成1個(gè)問(wèn)號(hào)而已
先刪除遠(yuǎn)程分支,然后重命名本地分支,接著再Push到遠(yuǎn)程倉(cāng)庫(kù)
不知道仔細(xì)的你有無(wú)發(fā)現(xiàn),倉(cāng)庫(kù)地址除Https外,還有1個(gè)SSH,
這里我們簡(jiǎn)單介紹下二者的區(qū)分,第1點(diǎn):使用Https url可以任意克隆
Github上的項(xiàng)目;而是用SSH url克隆的話,你必須是項(xiàng)目的具有者或
管理員,而且還要添加SSH Key,否則會(huì)沒(méi)法克隆。還有1點(diǎn)是,
Https每次push都需要輸入用戶名和密碼,而使用SSH則不需要輸入
用戶名如果配置SSH Key時(shí)設(shè)置了密碼,則需要輸入密碼,否則直接
git push就能夠了!
另外,SSH,Secure shell(安全外殼協(xié)議),專為遠(yuǎn)程登陸會(huì)話
與其他網(wǎng)絡(luò)服務(wù)提供安全性的協(xié)議,而SSH傳輸?shù)臄?shù)據(jù)是可以經(jīng)過(guò)緊縮的,
可以加快傳輸?shù)乃俣龋鲇诎踩耘c速度,我們優(yōu)先斟酌使用SSH協(xié)議,
而SSH的安全驗(yàn)證規(guī)則又分為基于密碼和基于密鑰兩種!
我們這里用的是基于第2種的,即在本地創(chuàng)建1對(duì)密鑰,
公鑰(id_rsa.pub)和私鑰(id_rsa),然后把公鑰的內(nèi)容貼到
Github賬號(hào)的ssh keys中,這樣就建立了本地和遠(yuǎn)程的認(rèn)證關(guān)系,
當(dāng)我們?cè)賞ush到遠(yuǎn)程倉(cāng)庫(kù),會(huì)將你本地的公共密鑰與服務(wù)器的進(jìn)行匹配,
如果1致驗(yàn)證通過(guò)直接推送更新!
下面我們來(lái)建立ssh key,首先來(lái)到電腦的根目錄下,這里假定我們沒(méi)
創(chuàng)建過(guò)SSH key:
履行完ssh-keygen那個(gè)指令后,后面順次要你輸入文件名,
直接回車會(huì)生成兩個(gè)默許的秘鑰文件,接著提示輸入密碼,
直接回車,如果這里你輸入密碼了的話,那末push的時(shí)候
你還是需要輸入密碼,接著又輸多1次密碼,一樣回車,
然后出現(xiàn)最下面的這串東西就說(shuō)明ssh key已創(chuàng)建成功了!
我們接著可以用編輯器打開(kāi)id_rsa.pub文件或鍵入:
clippub
復(fù)制文件內(nèi)容,然后打開(kāi)Github,點(diǎn)擊你的頭像,選擇:Settings,
然后點(diǎn)擊左邊SSH Keys,然后New SSH Key
然后Github會(huì)給你發(fā)來(lái)1個(gè)提示創(chuàng)建了1個(gè)新ssh key的郵件,
疏忽就好,接下來(lái)我們可以鍵入:ssh -T git@github.com,
后面的是你的注冊(cè)郵箱,然后如果你上面設(shè)置過(guò)密碼則需要輸入密碼,
否則直接輸入yes然后1直按回車就好!,最后出現(xiàn)Hi xxx那句話
就說(shuō)明ssh key配置成功了!
PS:其他遠(yuǎn)程倉(cāng)庫(kù)配置方法與此類同,
內(nèi)容參考自:https://help.github.com/articles/generating-an-ssh-key/
其實(shí),安裝好Git后,就1有1個(gè)GitGui的東東了,就能夠直接
用有用戶界面的Git來(lái)做版本管理的工作了,而Github客戶端則是
Github給我們提供的1個(gè)專門用來(lái)管理Github項(xiàng)目的1個(gè)工具而已。
比如,假設(shè)你裝了Github客戶端,在Clone項(xiàng)目的時(shí)候,你只需點(diǎn)擊:
就可以直接把項(xiàng)目clone下來(lái),就是1些Git操作的圖形化罷了,首先來(lái)到下面的鏈接
下載Github客戶端:https://desktop.github.com/
文件很小,后面點(diǎn)擊運(yùn)行文件后,他還要在線下載安裝,100多m,
然后傻瓜式安裝,安裝完成后,會(huì)自動(dòng)打開(kāi)Github客戶端,然后
使用你的Github賬號(hào)登陸,接著他會(huì)默許為你創(chuàng)建SSH Key信息,
接著的你自己摸索了!
這里另外補(bǔ)充1點(diǎn),就是win 8.1裝Github客戶端的問(wèn)題,
昨晚安裝的時(shí)候1直報(bào)這個(gè)毛病:
直接,win + x,選擇”命令行提示符(管理員)“,履行以下下面的這個(gè)指令:
%SYSTEMROOT%\SYSTEM32\REGSVR32.EXE %SYSTEMROOT%\SYSTEM32\WUAUENG.DLL
然后再點(diǎn)擊Github的安裝程序,等待安裝完成便可,下載其實(shí)不需梯子。
點(diǎn)擊進(jìn)入你的倉(cāng)庫(kù),點(diǎn)擊Setting,拉到最后:
點(diǎn)擊Delete this repository
彈出的對(duì)話框中輸入要?jiǎng)h除的倉(cāng)庫(kù)名稱,接著點(diǎn)擊刪除
你可以Clone他人的開(kāi)源項(xiàng)目,在看他人代碼的時(shí)候,你覺(jué)得作者有
某些地方寫得不好,寫錯(cuò),或你有更好的想法,你在本地修改后,
想把修改push推送到開(kāi)源項(xiàng)目上,想法很好,但是你不是項(xiàng)目的擁
有著和參與者,是沒(méi)法推送更改的?。?!這樣是為了
避免熊孩子,畢竟熊孩子無(wú)處不在,參與開(kāi)源項(xiàng)目的方法有兩種:
第1種方法:
是讓作者把你加為寫作者,添加協(xié)作者流程:點(diǎn)擊倉(cāng)庫(kù)的Settings
–>Collaborators然后輸入想添加的人的用戶名或郵箱,點(diǎn)擊
添加便可。
第2種方法:
點(diǎn)擊Fork按鈕,把這個(gè)項(xiàng)目fork到自己的賬號(hào)下,然后Clone
到本地,然后做你想做的修改,commit提交,然后push到自己賬
號(hào)里的倉(cāng)庫(kù),然后打開(kāi)開(kāi)源項(xiàng)目,點(diǎn)擊 ,然后新建1個(gè)
pull request,接著設(shè)置自己的倉(cāng)庫(kù)為源倉(cāng)庫(kù),設(shè)置源分支,
目標(biāo)倉(cāng)庫(kù)與目標(biāo)分支,然后還有pull request的標(biāo)題和描寫信息,
填寫終了后,肯定,這個(gè)時(shí)候開(kāi)源項(xiàng)目的作者就會(huì)收到1個(gè)pull
request的要求,由他來(lái)進(jìn)行審核,作者審查完代碼覺(jué)得沒(méi)問(wèn)題
的話,他可以點(diǎn)擊1下merge按鈕便可將這個(gè)pull request合并
到自己的項(xiàng)目中,假設(shè)作者發(fā)現(xiàn)了你代碼中還有些bug,他可以
通過(guò)Pull Request跟你說(shuō)明,要修復(fù)了xxBUG才允許合并,那末
你再修改下BUG,提交,更改后的提交會(huì)進(jìn)入Pull Request,
然后作者再審核這樣!
PS:假設(shè)作者不關(guān)閉或merge你的這個(gè)Pull Request,你可以1直
commit騷擾主項(xiàng)目…( ╯□╰ )
關(guān)于Git工作流,看到1篇圖文并茂很好的文章,就不重復(fù)造輪子了,
此處只是做下對(duì)應(yīng)工作流的簡(jiǎn)述,詳情見(jiàn):Git Workflows and Tutorials
類似于SVN,不過(guò)只有1條master分支,然后1群人就在這條分支上嗨,比如有小A和小B:
(沖突解決參照上面的套路)
- 1.項(xiàng)目管理者初始化倉(cāng)庫(kù),然后推到遠(yuǎn)程倉(cāng)庫(kù)
- 2.其他人克隆遠(yuǎn)程倉(cāng)庫(kù)項(xiàng)目到本地
- 3.小A和小B完成各自的工作
- 4.小A先完成了,git push origin master 把代碼推送到遠(yuǎn)程倉(cāng)庫(kù)
- 5.小B后完成了,此時(shí)推送代碼到遠(yuǎn)程倉(cāng)庫(kù),出現(xiàn)文件修改沖突
- 6.小B需要先解決沖突,git pull –rebase origin master,然后rebase漸漸玩
- 7.小B把沖突解決后,git push origin master 把代碼推送到遠(yuǎn)程倉(cāng)庫(kù)
生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
![]()