一谷遂、Git介紹
Git是很強(qiáng)很實用的版本控制工檐迟,Git的優(yōu)點是方便使用,輕量級悯衬。Git輕量級的原因是Git不進(jìn)行文件的全量拷貝弹沽。
Git項目結(jié)構(gòu)
當(dāng)我們查看一個git項目下的文件時,會看到如圖所示的項目結(jié)構(gòu):objects存放了所有文件筋粗,refs記錄了所有的指針策橘,HEAD保存了當(dāng)前分支的最新commit指向,index代表了staged文件區(qū)娜亿。
Git輕量級探秘
GIt為什么是一個輕量級的版本控制工具丽已?Git分支本質(zhì)上是一個指針,包含了一個40bytes的SHA-1字符串和一個\n換行符买决,總計41個bytes沛婴。換句話說,git會為每個分支對應(yīng)的每次提交分配41bytes的空間來存放一個指針督赤,所以每次提交其實只占用41bytes嘁灯,這就決定了git的輕量性。
Git VS SVN
Git與SVN的主要區(qū)別在于git具備了本地代碼倉庫躲舌,用戶可以通過維護(hù)本地代碼庫的方式丑婿,創(chuàng)建穩(wěn)定的版本再推送到遠(yuǎn)程倉庫上,同時也能通過分支的方式,實現(xiàn)多人在一個項目上進(jìn)行互相之間無干擾的開發(fā)羹奉。
事實上
Git如何工作秒旋?
三棵樹
工作區(qū)(working directory/working tree) 即你能看到的代碼
暫存區(qū)(staged file/indexed file) 通過git add命令加入的代碼
倉庫(repository) push過的改動或者push了的新增文件
各個區(qū)域之間的變動和對應(yīng)操作如圖所示
Git commit
如圖所示是一次commit對應(yīng)的git保存記錄,一次commit記錄包含了commit的size和一個tree的指針尘奏,commit里的tree指針指向tree滩褥,tree里包含了指向本次提交所對應(yīng)的文件改動的指針,git就是通過這種存儲指針的方式實現(xiàn)了輕量級的版本控制炫加。
Git commits
如圖所示是多次commit的記錄之間是如何連接的瑰煎,新進(jìn)行的提交包含了一個父指針,指向上一次提交俗孝,git通過這種方式實現(xiàn)了commit之間的順序連接酒甸。
二、Git指令總結(jié)
如圖所示是git各個區(qū)域之間通過哪一條指令進(jìn)行代碼的轉(zhuǎn)換
git init/git clone
git init用來講一個項目初始化為git項目赋铝,git clone做的操作是從url指定的遠(yuǎn)程倉庫里拉取代碼到本地并且初始化為git項目插勤。
git clone -o ? ? ? ? ? ? ? ?#重命名clone的倉庫
git clone -b ? ? ? ? ? ?#重命名clone的分支
git branch
git branch用來執(zhí)行與分支有關(guān)的操作
git branch ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#創(chuàng)建新分支 命名為
git branch -d ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #刪除名為的分支
git branch -v? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示所有分支和其對應(yīng)的最新一次commit
git branch --merged? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示所有進(jìn)行過合并的分支
git branch --no-merged? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #顯示所有未進(jìn)行過合并的分支
git branch -f? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #重置分支
git branch -r? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #顯示遠(yuǎn)程分支
git branch -a? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示所有分支
git branch -u origin/dev dev? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #創(chuàng)建并初始化一個分支dev
git branch --set-upstream master origin/master? ? ? ? ? ? ? ? ? ? ? ?#默認(rèn)設(shè)置本地master分支跟蹤遠(yuǎn)程倉庫origin/master分支
git branch --set-upstream dev origin/dev? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#默認(rèn)設(shè)置本地dev分支跟蹤遠(yuǎn)程倉庫origin/dev分支
git branch --track ? ? ? ? ? ? ? ? ? ? ? ? ?#設(shè)置分支跟蹤遠(yuǎn)程分支
git branch ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #基于指定commit創(chuàng)建新分支
git branch -m ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#重命名分支
git checkout?
git checkout用于執(zhí)行分支之間的切換和文件的回滾
git checkout ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #切換到分支
git checkout -b --track /? ? ? ? ? ? ? #創(chuàng)建分支并切換到該分支 設(shè)置當(dāng)前分支追蹤遠(yuǎn)程分支/
git checkout -b ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #創(chuàng)建新分支并切換到該分支
git checkout -b ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #基于創(chuàng)建新分支并切換到該分支
git checkout -B ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #基于指定的commit創(chuàng)建新分支并切換到該分支
git branch ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#基于指定的commit創(chuàng)建新分支并切換到該分支
git checout -- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#回滾到最新一次commit的代碼
git checkout .? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #放棄工作區(qū)內(nèi)所有的改動
git add
git add .
git add -A? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#添加所有文件到暫存區(qū)
git add ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#添加指定文件到暫存區(qū)
git commit
git commit -m "message"? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#提交
git commit --amend -m "message"? ? ? ? ? ? ? ? ? ? ? ? ? #修改上一次commit
git commit --amend ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#針對指定文件進(jìn)行重新提交一次
git push
git push :? ? ? ? ? ? ? ? ? ?#推送本地分支到遠(yuǎn)程倉庫中的
git push ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#本地分支到遠(yuǎn)程倉庫repo 如果沒有指定遠(yuǎn)程分支則默認(rèn)推送到跟蹤分支
git push -u origin dev ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #首次推送代碼到遠(yuǎn)程分支dev
git push -all origin? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ?#推送所有分支
git push origin dev:master ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #標(biāo)準(zhǔn)推送 推送本地分支dev到遠(yuǎn)程倉庫origin遠(yuǎn)程分支master
git push origin ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#推送分支到遠(yuǎn)程倉庫origin 如果省略本地分支和遠(yuǎn)程分支 則默認(rèn)推送當(dāng)前分支到其跟蹤的遠(yuǎn)程分支
git push ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#推送分支 如果當(dāng)前項目只跟蹤了一個遠(yuǎn)程倉庫則可以省略遠(yuǎn)程倉庫名
git push origin :dev? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??#刪除遠(yuǎn)程倉庫origin中的分支dev
git fetch? ?
git fetch? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#獲取遠(yuǎn)程改動
git fetch --a? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#獲取所有的遠(yuǎn)程改動
git fetch ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #獲取遠(yuǎn)程倉庫中的改動
git fetch ? ? ? ? ? ? ?#獲取遠(yuǎn)程倉庫中中的改動
git fetch --prune? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#刪除本地倉庫中存在但遠(yuǎn)程倉庫中不存在的分支
git merge
git merge --commit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #合并后產(chǎn)生一個commit
git merge --no-commit? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#合并后不產(chǎn)生一個commit
git merge --ff? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #使用fast-forward模式進(jìn)行合并
git merge --no-ff? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#不使用fast-forward模式進(jìn)行合并
git merge ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#合并指定的commit
git merge ...? ? ? ? ? ? ? ?#合并多個分支
git pull
git pull = git fetch + git merge? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #git pull其實等于fetch+merge
git pull ? ? ? #拉取遠(yuǎn)程倉庫中的分支到本地分支
git remote
git remote -v? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示對應(yīng)的遠(yuǎn)程倉庫url
git remote add ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #添加本地倉庫連接的遠(yuǎn)程倉庫
git remote rm ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ?#移除遠(yuǎn)程倉庫連接
git remote rename ? ? ? ? ? ? ? ? ? ? ? #重命名
git remote set-head ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #設(shè)置默認(rèn)的主要分支
git remote set-branches ? ? ? ? ? ? ? ? ? ? ?#設(shè)置遠(yuǎn)程分支
git remote set-branches -add ? ? ? ? ? ? #添加本地跟蹤的遠(yuǎn)程分支
git remote show ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ?#打印遠(yuǎn)程倉庫信息
git diff??
git diff ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #顯示兩個分支之間的區(qū)別
git diff ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示指定文件工作區(qū)和暫存區(qū)之間的區(qū)別
git diff ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #顯示指定分支中指定文件工作區(qū)和暫存區(qū)之間的區(qū)別
git diff --cached ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示暫存區(qū)和repo里的指定文件的區(qū)別
git diff --cached ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示暫存區(qū)和指定提交的區(qū)別
git diff ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示工作區(qū)和指定commit中文件的區(qū)別
git diff ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示兩個commit的區(qū)別
git diff HEAD/HEAD^/HEAD^^/HEAD~3...? ? ? ? ? ? ? ? ?#顯示工作區(qū)和HEAD/HEAD^/HEAD^^/HEAD~3的區(qū)別
git diff —shortstat “@{0 day ago}"??? ? ? ? ? ? ? ? ? ? ? ? ? ? #顯示你今天寫了多少行代碼
git reset
git reset <file>? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#reset指定文件如果說文件是新建的那么reset無效 如果沒有指定commit那么就默認(rèn)reset到HEAD
git revert
git revert <commit>? ? ? ? ? ? ? ? ? ? ? ?#revert指定commit? ? ? ??e.g git revert HEAD~3...HEAD 撤銷多個commit
git status
顯示還未提交的改動
git status -s? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示簡潔版本
git status -b? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #顯示分支和分支跟蹤情況
git stash
git stash? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#stash所有的改動
git stash list ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示所有的stash記錄
git stash apply stash@{0} ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#取出指定的stash
git stash drop? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ?#丟棄指定的stash
git stash pop? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #取出最上層的stash記錄并且丟棄
git stash clear? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #清除所有stash記錄
git stash save ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #save一個stash記錄并且用message標(biāo)記
git stash pop = git stash apply + git stash drop
git rm
git rm ? ? ? ? ? ? ? ? ? ? ? #從工作區(qū)中移除指定文件
git rm --cached ? ? ? ?#從暫存區(qū)中移除指定文件
git mv
git mv <file> <renamed_file>? ? ? ? ? #重命名文件
git log
git log -n? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#只顯示n條記錄
git log ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示指定文件的提交記錄
git log ? ? ? ? ? ? ? ? ? ? ? ? ? ?#顯示指定分支的提交記錄
git log ? ? ?? ? ? ? ? ? ? ? ? ? ?#顯示指定commit的提交信息
git log ? ? ?#顯示[commit1, commit2]的提交信息 包括commit1
git log ..? ? #顯示(commit1, commit2]的提交信息 不包括commit1
git log -stat? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #只顯示少量信息
git rebase
git rebase test? ? ? ? ? ? ? ? #在當(dāng)前分支上重演目標(biāo)分支上的改動
git cherry-pick
git cherry-pick <commit>? ? ? ? ? ? ? ? ?#再次提交一個commit 常用于commit的移植
git show?
git show ? ? ? ? ? ? ? ? ? ? ? ? ? #顯示指定commit的信息
git show :? ? ? ? ? ? ? ? #顯示指定commit中指定文件的內(nèi)容
git config
git config —list? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #顯示config中的所有配置
git config --global?alias.co?checkout? ? ? ? ? ?#用于自定義git指令的簡寫版本
三、常用場景
如何進(jìn)行常規(guī)的bugfix革骨?
git branch bugfix? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#新建一個bugfix分支
git checkout bugfix? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#切換到該分支
#######fixing bugs#########? ? ? ? ? ? ? ? #修復(fù)bug
git add .? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #添加改動到暫存區(qū)
git commit -m "fix bugs"? ? ? ? ? ? ? ? ? ? ? ? ? ?#提交改動
git checkout master? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#切回到主要分支
git merge bugfix? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#merge改動
git branch -d bugfix? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #刪除bugfix分支
如何查看跟蹤的遠(yuǎn)程分支
git branch -vv? ? ? ? ? ? ? ? ? #查看所有分支和其對應(yīng)的遠(yuǎn)程分支
如何重新commit农尖?
git commit -amend? ? ? ? ? ?#使用amend option重新修訂commit
如何回滾之前的改動?
git reset? ? ? ? ? ? ? ? ? ? ? ? ?#reset將工作區(qū)和暫存區(qū)回滾到你指定的版本 你指定的提交之后的所有提交記錄都被丟棄了
git revert? ? ? ? ? ? ? ? ? ? ? ?#revert將撤銷指定commit的改動 對除此之外的所有commit都沒有影響
git revert會創(chuàng)建新的提交記錄
如何使用cherry-pick良哲?
使用cherry-pick重演指定分支上的提交改動 如果有沖突需要你解決
如何使用rebase盛卡?
使用git rebase命令將一個分支上的分支在另一個分支上重新演一次 如果有沖突需要解決沖突之后使用git rebase --continue繼續(xù)執(zhí)行rebase
四、Git進(jìn)階
如何設(shè)置/切換當(dāng)前分支所跟蹤的遠(yuǎn)程分支筑凫?
git checkout --track origin/dev? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#設(shè)置當(dāng)前分支跟蹤遠(yuǎn)程分支origin/dev
git checkout -b origin/? ? ? ? ? ? ? ? ? ? ? #創(chuàng)建新分支并且設(shè)置其跟蹤遠(yuǎn)程分支origin/tracked_branch
git branch -u origin/dev or git branch --set-upstream-to origin/dev? ? ? ?#初始化/更新當(dāng)前分支的tracking分支
Git merge VS Git rebase VS Git cherry-pick
Git reset VS Git checkout VS Git revert
為什么在實際工作中使用git revert回滾比使用git reset安全滑沧?
使用git reset之后指定的版本之后的提交內(nèi)的改動全部會被移除,如果A拉取了代碼之后并基于拉取的代碼進(jìn)行開發(fā)巍实,同時假設(shè)B使用了reset進(jìn)行了代碼回滾滓技,如果A通知B他進(jìn)行了回滾那么B可以在本地同時進(jìn)行回滾處理,但如果A沒有通知B棚潦,A回滾了代碼令漂、進(jìn)行了開發(fā)并且推送了代碼,那么遠(yuǎn)程倉庫中將是更新的代碼瓦盛,但是B并不知情洗显,也進(jìn)行了代碼推送,那么A進(jìn)行的回滾又被推送回了代碼庫原环,這是分布式代碼管理的優(yōu)點也是缺點挠唆,所以推薦在本地開發(fā)中使用git reset指令進(jìn)行回滾
如果使用git revert進(jìn)行代碼回滾,那么git會創(chuàng)建新的提交記錄嘱吗,假設(shè)A通過git resert撤銷了commit玄组,那么同時也會新建新的commit滔驾,當(dāng)A進(jìn)行代碼推送后,代碼庫中代碼進(jìn)行了更新俄讹,同時B不回收到提示自己的commit領(lǐng)先于遠(yuǎn)程commit哆致,那么B也可以通過推送代碼的形式發(fā)布自己的改動,并且因為執(zhí)行了revert操作患膛,B重新推上去的本應(yīng)該被撤銷的代碼也會被revert的commit撤銷掉改動摊阀,同時可以保留歷史代碼
五、常用指令Option
-v? ? ? ? ? ? ? ? ? #verbose
-q? ? ? ? ? ? ? ? ? #quiet
-f? ? ? ? ? ? ? ? ? ?#強(qiáng)制
--? ? ? ? ? ? ? ? ? ?#常用于分割命令和目標(biāo)文件
六踪蹬、Q&A