git 快速入門
一、git 全域性配置
全域性配置:
設定編碼 gitconfig--globalgui.encodingutf-8 gitconfig--globali18n.commitencodingutf-8 gitconfig--globali18n.logoutputencodingutf-8 指定git或gitlab的使用者名稱與郵箱 bogon:~yuanjicai$gitconfig--globaluser.namemeteor bogon:~yuanjicai$gitconfig--globaluser.email[email protected] bogon:~yuanjicai$gitconfig--globalcolor.uitrue 換行設定 gitconfig--globalcore.autocrlfinput#提交時轉換為LF,檢出時不轉換 gitconfig--globalcore.safecrlfwarn#提交包含混合換行符的檔案時給出警告
檢視配置:
bogon:~yuanjicai$gitconfig--list|tail-3 user.name=meteor [email protected] color.ui=true bogon:~yuanjicai$
實質上是將配置寫入了~/.gitconfig檔案(當然直接修改該檔案也可以達到配置的目的)
bogon:~yuanjicai$ls.gitconfig .gitconfig bogon:~yuanjicai$cat.gitconfig [user] name=meteor email=[email protected] [color] ui=true bogon:~yuanjicai$
二、git新建專案及初始化
方法一、新建立專案:
bogon:~yuanjicai$mkdir-pgithub/project bogon:~yuanjicai$cdgithub/project/ bogon:projectyuanjicai$gitinit#初始化倉庫 InitializedemptyGitrepositoryin/Users/yuanjicai/github/project/.git/ bogon:projectyuanjicai$ls-a ....git bogon:projectyuanjicai$cd.git bogon:.gityuanjicai$ls HEADconfighooksobjects branchesdescriptioninforefs bogon:.gityuanjicai$#git儲存分支的地方
方法二:
bogon:githubyuanjicai$pwd /Users/yuanjicai/github bogon:githubyuanjicai$ls project bogon:githubyuanjicai$gitclonehttps://github.com/kennethreitz/requests.git Cloninginto'requests'... remote:Countingobjects:17906,done. remote:Compressingobjects:100%(35/35),done. remote:Total17906(delta11),reused0(delta0),pack-reused17871 Receivingobjects:100%(17906/17906),4.79MiB|643.00KiB/s,done. Resolvingdeltas:100%(11665/11665),done. Checkingconnectivity...done. bogon:githubyuanjicai$ls projectrequests bogon:githubyuanjicai$lsrequests/ AUTHORS.rstMakefilerequests CONTRIBUTING.mdNOTICErequirements-to-freeze.txt HISTORY.rstREADME.rstrequirements.txt LICENSEdocssetup.py MANIFEST.inexttests bogon:githubyuanjicai$lsrequests/.git HEADconfighooksinfoobjectsrefs branchesdescriptionindexlogspacked-refs bogon:githubyuanjicai$
三、建立檔案並提交
bogon:githubyuanjicai$cdproject/ bogon:projectyuanjicai$ls.git/ COMMIT_EDITMSGORIG_HEADconfighooksinfoobjects HEADbranchesdescriptionindexlogsrefs bogon:projectyuanjicai$ls bogon:projectyuanjicai$vimtest1.py bogon:projectyuanjicai$pythontest1.py helloworld bogon:projectyuanjicai$vimtest2.py bogon:projectyuanjicai$pythontest2.py helloYeeCall bogon:projectyuanjicai$gitstatus Onbranchmaster Untrackedfiles: (use"gitadd<file>..."toincludeinwhatwillbecommitted) test1.py test2.py nothingaddedtocommitbutuntrackedfilespresent(use"gitadd"totrack) bogon:projectyuanjicai$gitaddtest1.pytest2.py bogon:projectyuanjicai$gitstatus Onbranchmaster Changestobecommitted: (use"gitresetHEAD<file>..."tounstage) newfile:test1.py newfile:test2.py bogon:projectyuanjicai$gitcommit-m"initcommit" [master547a6b0]initcommit 2fileschanged,2insertions(+) createmode100644test1.py createmode100644test2.py bogon:projectyuanjicai$gitstatus Onbranchmaster nothingtocommit,workingtreeclean bogon:projectyuanjicai$
四、git status
bogon:projectyuanjicai$vimtest2.py bogon:projectyuanjicai$pythontest2.py helloYeeCall hellogit bogon:projectyuanjicai$gitstatus Onbranchmaster Changesnotstagedforcommit: (use"gitadd<file>..."toupdatewhatwillbecommitted) (use"gitcheckout--<file>..."todiscardchangesinworkingdirectory) modified:test2.py nochangesaddedtocommit(use"gitadd"and/or"gitcommit-a") bogon:projectyuanjicai$echo'*~'>.gitignore bogon:projectyuanjicai$gitadd.gitignore bogon:projectyuanjicai$gitstatus-s A.gitignore Mtest2.py#第二位的M表示workingdirectory有修改 bogon:projectyuanjicai$gitadd.gitignore bogon:projectyuanjicai$gitaddtest2.py bogon:projectyuanjicai$gitstatus-s A.gitignore Mtest2.py bogon:projectyuanjicai$vimtest2.py bogon:projectyuanjicai$pythontest2.py helloYeeCall hellogit hellomaven bogon:projectyuanjicai$gitstatus-s A.gitignore MMtest2.py#第一個M表示staging有修改,第二個M表示workingdirectory有修改
五、git diff
bogon:projectyuanjicai$vimtest1.py bogon:projectyuanjicai$pythontest1.py helloworld helloop bogon:projectyuanjicai$gitstatus-s Mtest1.py bogon:projectyuanjicai$gitdiff#預設gitdiff只檢查第二個標誌位(即檢查workingdirectory與staging的資料是否一致) diff--gita/test1.pyb/test1.py indexa968078..6e43c62100644 ---a/test1.py +++b/test1.py#表示本行為新新增的內容 @@-1+1,2@@ print'helloworld' +print'helloop' bogon:projectyuanjicai$gitaddtest1.py bogon:projectyuanjicai$gitstatus-s Mtest1.py bogon:projectyuanjicai$gitdiff bogon:projectyuanjicai$gitdiff--staged#表示檢查stage與history中的資料是否一致 diff--gita/test1.pyb/test1.py indexa968078..6e43c62100644 ---a/test1.py +++b/test1.py @@-1+1,2@@ print'helloworld' +print'helloop' bogon:projectyuanjicai$gitdiffHEAD#檢查workingdirectory與history是否一致,HEAD指標就指向最後一次提交的內容 diff--gita/test1.pyb/test1.py indexa968078..6e43c62100644 ---a/test1.py +++b/test1.py @@-1+1,2@@ print'helloworld' +print'helloop' bogon:projectyuanjicai$ bogon:projectyuanjicai$gitdiff--stat#輸出簡要資訊 bogon:projectyuanjicai$gitdiff--staged--stat test1.py|1+ 1filechanged,1insertion(+) bogon:projectyuanjicai$gitdiffHEAD--stat test1.py|1+ 1filechanged,1insertion(+) bogon:projectyuanjicai$ bogon:projectyuanjicai$gitcommit-m'secondcommit'#從stage中將資料提交致history中 [masterb89e642]secondcommit 1filechanged,1insertion(+) bogon:projectyuanjicai$
六、下載
bogon:projectyuanjicai$vimtest1.py bogon:projectyuanjicai$cattest1.py print'helloworld' print'helloop.....' bogon:projectyuanjicai$gitdiff--stat test1.py|2+- 1filechanged,1insertion(+),1deletion(-) bogon:projectyuanjicai$gitaddtest1.py bogon:projectyuanjicai$gitdiff--stat bogon:projectyuanjicai$gitdiff--staged--stat#比較stage與history中的資料是否一致 test1.py|2+- 1filechanged,1insertion(+),1deletion(-) bogon:projectyuanjicai$gitresettest1.py#下載歷史history中的最後一個版本致stage中 Unstagedchangesafterreset: Mtest1.py bogon:projectyuanjicai$gitdiff--staged--stat bogon:projectyuanjicai$gitdiffHEAD--stat#比較workingdirectory與history中的資料是否一致 test1.py|2+- 1filechanged,1insertion(+),1deletion(-) bogon:projectyuanjicai$gitcheckouttest1.py#下載stage中的資料致workingdirectory bogon:projectyuanjicai$gitdiffHEAD--stat bogon:projectyuanjicai$echo"xxxxx">>test1.py bogon:projectyuanjicai$gitdiffHEAD--stat#發現stage與workingdirectory已經不一致 test1.py|1+ 1filechanged,1insertion(+) bogon:projectyuanjicai$gitcheckoutHEADtest1.py#從history中直接下載歷史版本到workingdirectory bogon:projectyuanjicai$gitdiffHEAD--stat bogon:projectyuanjicai$ bogon:projectyuanjicai$vimtest1.py bogon:projectyuanjicai$cattest1.py print'helloworld' print'helloop!!' bogon:projectyuanjicai$gitcommit-am'thirdcommit'#直接由workingdirectory提交到history [masterbcc815a]thirdcommit 1filechanged,1insertion(+),1deletion(-) bogon:projectyuanjicai$gitdiff--staged
七、刪除資料
bogon:projectyuanjicai$echo"newfile">test3.txt#新建立檔案test3.txt bogon:projectyuanjicai$gitaddtest3.txt新增並提交 bogon:projectyuanjicai$gitcommit-m"addtest3.txt" [master5626d79]addtest3.txt 1filechanged,1insertion(+) createmode100644test3.txt bogon:projectyuanjicai$gitrmtest3.txt#刪除test3.txt rm'test3.txt' bogon:projectyuanjicai$gitstatus Onbranchmaster Changestobecommitted: (use"gitresetHEAD<file>..."tounstage) deleted:test3.txt bogon:projectyuanjicai$gitstatus-s Dtest3.txt bogon:projectyuanjicai$gitcommit-m"deletetest3.txt"#提交刪除 [master6e928e5]deletetest3.txt 1filechanged,1deletion(-) deletemode100644test3.txt bogon:projectyuanjicai$gitstatus-s bogon:projectyuanjicai$ bogon:projectyuanjicai$ bogon:projectyuanjicai$gitrm--cachedtest2.py#僅刪除staging中的檔案 rm'test2.py' bogon:projectyuanjicai$gitstatus-s Dtest2.py ??test2.py bogon:projectyuanjicai$gitresettest2.py#再次從history中下載最後一個版本的檔案 bogon:projectyuanjicai$gitstatus-s bogon:projectyuanjicai$ bogon:projectyuanjicai$gitrm--cachetest2.py#刪除staging中的檔案,將workingdirectory中的資料改名,並再次新增、提交 rm'test2.py' bogon:projectyuanjicai$mvtest2.pytest4.py bogon:projectyuanjicai$gitaddtest4.py bogon:projectyuanjicai$gitstatus-s Rtest2.py->test4.py bogon:projectyuanjicai$gitcommit-m'renametest2.pytotest4.py' [master9845bda]renametest2.pytotest4.py 1filechanged,0insertions(+),0deletions(-) renametest2.py=>test4.py(100%) bogon:projectyuanjicai$gitstatus-s bogon:projectyuanjicai$
八、stash暫存
bogon:projectyuanjicai$vimtest1.py bogon:projectyuanjicai$cattest1.py#修改原始檔 print'helloworld' print'helloop!!' print'xxxxxxxxxxx' print'yyyyyyyyyyy' bogon:projectyuanjicai$gitstash#暫存當前正在進行的工作 SavedworkingdirectoryandindexstateWIPonmaster:9845bdarenametest2.pytotest4.py HEADisnowat9845bdarenametest2.pytotest4.py bogon:projectyuanjicai$gitstatus Onbranchmaster nothingtocommit,workingtreeclean bogon:projectyuanjicai$cattest1.py#檢視檔案的內容(已經是之前沒有修改前的內容) print'helloworld' print'helloop!!' bogon:projectyuanjicai$vimtest1.py bogon:projectyuanjicai$cattest1.py#編輯原始碼檔案(加了兩個感嘆號) print'helloworld!!' print'helloop!!' bogon:projectyuanjicai$gitcommit-am'quickupdate'#提交修改後的程式碼 [master23a727c]quickupdate 1filechanged,1insertion(+),1deletion(-) bogon:projectyuanjicai$gitstashlist#檢視之前的暫存區 [email protected]{0}:WIPonmaster:9845bdarenametest2.pytotest4.py [email protected]{1}:filter-branch:rewrite [email protected]{2}:WIPonmaster:7f68a1aupdate bogon:projectyuanjicai$gitstashpop#取出上次的暫存 Auto-mergingtest1.py Onbranchmaster Changesnotstagedforcommit: (use"gitadd<file>..."toupdatewhatwillbecommitted) (use"gitcheckout--<file>..."todiscardchangesinworkingdirectory) modified:test1.py nochangesaddedtocommit(use"gitadd"and/or"gitcommit-a") Droppedrefs/[email protected]{0}(33fb283741bb2747c55a9ddee45118f84b65c498) bogon:projectyuanjicai$cattest1.py#檢視檔案的內容(已經又回到了暫存時狀態) print'helloworld!!' print'helloop!!' print'xxxxxxxxxxx' print'yyyyyyyyyyy' bogon:projectyuanjicai$
九、history 詳解
git commit 之後就會提交到history area。然後history area 中儲存 本次提交 的commit history 。每次的commit history 又由 parent 和 tree組成。而每個 parent 都會指向它前一個commit history 。最後一次提交的commit history被標記為 HEAD。前一次的被標記為 HEAD~ ,再前一次的被標記為HEAD~2 … 依次類推。
每個tree 又由多個檔案或子目錄組成,每個子目錄下又可以由多個檔案或子目錄組成。
輸入git log 可以看到之前提交的記錄,以及每次提交時,每個commit history的hash碼。
git cat-file -t HEAD 可以檢視最後一次commit history 的指向型別
git cat-file -p HEAD可以檢視最後一次commit history中的內容,包括 tree 、parent的hash值
git cat-file -t Tree的hash 說明: -t 檢視型別 -p 檢視內容
可以檢視到每個檔案或目錄也對應一個hash 值 。其中blob表示二進位制
bogon:projectyuanjicai$gitlog--oneline 23a727cquickupdate 9845bdarenametest2.pytotest4.py 6e928e5deletetest3.txt 5626d79addtest3.txt bcc815athirdcommit b89e642secondcommit f492923firstcommit 547a6b0initcommit bogon:projectyuanjicai$gitcat-file-t23a727c commit bogon:projectyuanjicai$gitcat-file-p23a727c treebfbf9746b6279366e43117c3a94ff38692d1b60f parent9845bda97fdaca363b07f703a88259976a58261c authormeteor<[email protected]>1471422986+0800 committermeteor<[email protected]>1471422986+0800 quickupdate bogon:projectyuanjicai$gitcat-file-tHEAD#等同於gitcat-file-t23a727c命令 commit bogon:projectyuanjicai$gitcat-file-pHEAD#等同於gitcat-file-p23a727c命令 treebfbf9746b6279366e43117c3a94ff38692d1b60f parent9845bda97fdaca363b07f703a88259976a58261c authormeteor<[email protected]>1471422986+0800 committermeteor<[email protected]>1471422986+0800 quickupdate bogon:projectyuanjicai$gitcat-file-pHEAD~#等同於gitcat-file-p9845bda treebee185fc174697cf400998818e4ca099ca00e275 parent6e928e51ab05ad2c60b0d51cfd6b7d0cae783ec3 authormeteor<[email protected]>1471422174+0800 committermeteor<[email protected]>1471422174+0800 renametest2.pytotest4.py bogon:projectyuanjicai$gitcat-file-pbee185f 100644blobb25c15b81fae06e1c55946ac6270bfdb293870e8.gitignore 100644blobb351508c3cadddc4ea579967d1c3177364fd5a48test1.py 100644blob5de2b690c836079832d879f9d2902ac58043f5b9test4.py bogon:projectyuanjicai$ bogon:projectyuanjicai$gitcat-file-pb3515 print'helloworld' print'helloop!!' bogon:projectyuanjicai$gitshow-pb3515 print'helloworld' print'helloop!!' bogon:projectyuanjicai$
十、tree-ish
bogon:projectyuanjicai$ls-A .git.gitignoretest1.pytest4.py bogon:projectyuanjicai$cd.git bogon:.gityuanjicai$ls COMMIT_EDITMSGORIG_HEADconfighooksinfoobjects HEADbranchesdescriptionindexlogsrefs bogon:.gityuanjicai$catHEAD ref:refs/heads/master說明HEAD指向master分支 bogon:.gityuanjicai$cdrefs/ bogon:refsyuanjicai$tree . |____heads ||____mastermaster實質上是一個分支(branch) |____original ||____refs |||____heads ||||____master |||____stash |____stash |____tags bogon:refsyuanjicai$catheads/master#master又指向23a72 23a727c534d620339d3382d8284859f6a75f3194 bogon:refsyuanjicai$gitlog--oneline|head-2#hash23a727就是最後一次的提交 23a727cquickupdate 9845bdarenametest2.pytotest4.py bogon:refsyuanjicai$gitcat-file-t23a727#檢視hash23a727的型別是commithistory commit bogon:refsyuanjicai$ #從上述可以看到HEAD實質上是指幾最後一個commithistory的masterbranch,而masterbranch再指向本次的commithistory(另外master~等同於HEAD~) bogon:refsyuanjicai$gitrev-parseHEAD 23a727c534d620339d3382d8284859f6a75f3194 bogon:refsyuanjicai$gitrev-parsemaster 23a727c534d620339d3382d8284859f6a75f3194 bogon:refsyuanjicai$ bogon:refsyuanjicai$gitrev-parseHEAD~#說明:gitrev-parsemaster~等同gitrev-parseHEAD~ 9845bda97fdaca363b07f703a88259976a58261c bogon:refsyuanjicai$gitrev-parsemaster~ 9845bda97fdaca363b07f703a88259976a58261c bogon:refsyuanjicai$ bogon:refsyuanjicai$gitrev-parseHEAD~^{tree}#說明:檢視倒數第二次commithistory中的tree的hash值 bee185fc174697cf400998818e4ca099ca00e275 bogon:refsyuanjicai$gitrev-parseHEAD~:test1.py b351508c3cadddc4ea579967d1c3177364fd5a48 bogon:refsyuanjicai$gitcat-file-pb3515 print'helloworld' print'helloop!!' bogon:refsyuanjicai$gitshowHEAD~:test1.py print'helloworld' print'helloop!!' bogon:refsyuanjicai$
十一、branch分支
bogon:projectyuanjicai$gitstatus Onbranchmaster Changesnotstagedforcommit: (use"gitadd<file>..."toupdatewhatwillbecommitted) (use"gitcheckout--<file>..."todiscardchangesinworkingdirectory) modified:test1.py nochangesaddedtocommit(use"gitadd"and/or"gitcommit-a") bogon:projectyuanjicai$cattest1.py print'helloworld!!' print'helloop!!' print'xxxxxxxxxxx' print'yyyyyyyyyyy' bogon:projectyuanjicai$gitcommit-am"stashcommit" [master26415ad]stashcommit 1filechanged,2insertions(+) bogon:projectyuanjicai$gitbranch#檢視分支(*表示當前的branch) *master bogon:projectyuanjicai$gitbranchnewidea#建立分支 bogon:projectyuanjicai$gitbranch#再次檢視分支 *master newidea bogon:projectyuanjicai$gitcheckoutnewidea#切換新的分支 Switchedtobranch'newidea' bogon:projectyuanjicai$cat.git/HEAD#檢視當前HEAD指向newidea分支 ref:refs/heads/newidea bogon:projectyuanjicai$ls.git/refs/heads/#檢視現有分支的儲存情況 masternewidea bogon:projectyuanjicai$cat.git/refs/heads/*#檢視兩個分支都指向同一個commithistory 26415adb026d04fd2e375adedd6afcad8c0322ea 26415adb026d04fd2e375adedd6afcad8c0322ea bogon:projectyuanjicai$gitcheckoutmaster#現次切換回master分支 Switchedtobranch'master' bogon:projectyuanjicai$gitbranch-dnewidea#刪除指定分支 Deletedbranchnewidea(was26415ad). bogon:projectyuanjicai$gitbranch#再次檢視分支 *master bogon:projectyuanjicai$ bogon:projectyuanjicai$gitcheckout-bnewcode#引數-b作用:檢查如果沒有branch則新建立 Switchedtoanewbranch'newcode' bogon:projectyuanjicai$ls test1.pytest4.py bogon:projectyuanjicai$vimtest1.py bogon:projectyuanjicai$cattest1.py print'helloworld!!' print'helloop!!' print'xxxxxxxxxxx' print'yyyyyyyyyyy' print'zzzzzzzzzzz' bogon:projectyuanjicai$gitcommit-am'newcodeupdate' [newcode6c10be1]newcodeupdate 1filechanged,1insertion(+) bogon:projectyuanjicai$gitcheckoutmaster Switchedtobranch'master' bogon:projectyuanjicai$gitbranch *master newcode bogon:projectyuanjicai$gitbranch-dnewcode#此時刪除新分支時無法刪除 error:Thebranch'newcode'isnotfullymerged. Ifyouaresureyouwanttodeleteit,run'gitbranch-Dnewcode'. bogon:projectyuanjicai$gitmergenewcode#合併分支 Updating26415ad..6c10be1 Fast-forward#合併型別為Fast-forward test1.py|1+ 1filechanged,1insertion(+) bogon:projectyuanjicai$ bogon:projectyuanjicai$gitbranch-dnewcode#合併分支後就可以刪除newcode分支了 Deletedbranchnewcode(was6c10be1). bogon:projectyuanjicai$gitbranch *master bogon:projectyuanjicai$ bogon:projectyuanjicai$gitcheckout-bbugfix Switchedtoanewbranch'bugfix' bogon:projectyuanjicai$vimtest1.py bogon:projectyuanjicai$gitcommit-am'bugfix1' [bugfixeba1606]bugfix1 1filechanged,1insertion(+),1deletion(-) bogon:projectyuanjicai$vimtest1.py bogon:projectyuanjicai$gitcommit-am'bugfix2' print'helloworld!!' [bugfix48a5fd6]bugfix2 1filechanged,1insertion(+),1deletion(-) bogon:projectyuanjicai$gitlog--oneline|head-3 48a5fd6bugfix2 eba1606bugfix1 6c10be1newcodeupdate bogon:projectyuanjicai$gitcheckoutmaster Switchedtobranch'master' bogon:projectyuanjicai$vimtest1.py bogon:projectyuanjicai$gitcommit-am'lastupdate' [master329577a]lastupdate 1filechanged,1insertion(+),1deletion(-) bogon:projectyuanjicai$gitlog--oneline|head-2 329577alastupdate 6c10be1newcodeupdate bogon:projectyuanjicai$gitmergebugfix#合併分支 Auto-mergingtest1.py CONFLICT(content):Mergeconflictintest1.py#衝突內容:合併衝突在test1.py檔案中 Automaticmergefailed;fixconflictsandthencommittheresult.#自動合併失敗;修改衝突然後提交修改後的結果 然後檢視test.py原始檔內容,如下 <<<<<<<<HEAD 當前分支的程式碼 =============== 被合併分支的程式碼 >>>>>>>>>>>>>>>
這種衝突首先先分析兩部分程式碼是實現相同功能而寫的重複的程式碼,還是各自實現的不同的功能的程式碼。如果是重複程式碼:兩個二選一刪除一個,然後再把這些衝突標示符刪除即可;如果不是重複程式碼,兩個都需要保留,只需要把衝突符號刪除即可。工程編譯通過之後可以重新提交。如下所示:
bogon:projectyuanjicai$vimtest1.py#刪除重複程式碼,保留需要的部分 bogon:projectyuanjicai$gitaddtest1.py#重新新增 bogon:projectyuanjicai$gitcommit-m'mergeupdate'#重新提交 [master2b677c0]mergeupdate bogon:projectyuanjicai$gitbranch-dbugfix#刪除無用的分支 Deletedbranchbugfix(was48a5fd6). bogon:projectyuanjicai$gitbranch#檢視當前分支 *master bogon:projectyuanjicai$
轉載於:https://blog.51cto.com/caiyuanji/1839598