查看版本:git --version
創建版本庫:git init
查看git 腳本目錄:git --exec-path
把遠程分支拉到本地:git fetch origin dev(dev為遠程倉庫的分支名)
全局配置:
? ? ? ? ? ? ? ? ? git config --global user.name "xxx"??
? ? ? ? ? ? ? ? ? git config --unset --global user.name "xxx"? ?刪除設置
? ????????????????git config --global user.email "xxx@qq.com"
? ? ? ? ? ? ? ? ? git config --global alias.st status? 只在本用戶中使用
? ? ? ? ? ? ? ? ? git config --system alias.st status???被所有用戶使用
window下配置文件位置:C:\Users\Administrator\.gitconfig??
linux下配置文件位置:/etc/gitconfig
查看版本庫提交日志:
git log --pretty=fuller(全展示)|oneline(只顯示提交信息)|raw(顯示提交對象的parent屬性)? --stat 查看每次提交的文件變更統計
本地備份:
git clone demo demo1
合并解決沖突:
1、git?checkout?dev????????????????//切換到被合并的分支
2、git?pull?????????????????//拉取要合并分支的最新代碼
3、git?checkout?dev_activity???????//切換到要合并的分支
4、git?pull?????????????????//拉取最新代碼
5、git?checkout?-b?dev_activity_temp?//創建臨時分支用于合并,防止合并后沖突一時間解決不了而污染分支代碼
6、git?merge?dev???????????????????????????????//合并dev代碼到?dev_activity_temp
7、用tortoiseGit?或者其他可視化工具解決沖突
8、git?commit?-m?"合并?dev?解決沖突"??//提交解決沖突到臨時分支
9、git?checkout?dev_activity??//切換到?dev_activity??分支
10、git?merge?dev_activity_temp?//合并已經合并dev的臨時分支
11、git?push?????????????????//將合并代碼推送到遠端
12、git?branch?-D?dev_activity_temp??//刪除臨時分支
查看g工作區狀態:
git status -s(顯示精簡信息)
ADD之前,說明工作區當前文件與暫存區的有改動
ADD之后,說明暫存區當前文件與版本庫的有改動
ADD后追加內容,工作區暫存區版本庫三者都有改動
重要概念:
ADD推至暫存區(stage)
HEAD(當前工作分支)
當執行git reset HEAD時,緩存區的目錄樹會被重寫,但工作區不受影響,可用于取消add
當執行git rm --cached <file>時會直接刪除暫存區文件,工作區不受影響
當執行git checkout 或git checkout -- <file>時,暫存區的文件會替換工作區的文件,這個操作很危險,因為會清除工作區的所有改動
當執行git checkout HEAD或git checkout HEAD <file>時,會用HEAD指向的master分支的全部或部分替換工作區和暫存區的文件,這個操作也很危險!
查看改動:
git diff :比較工作區與暫存區的差異
git diff HEAD:比較工作區與HEAD(當前工作分支)的差異
git diff --staged|--cached:比較暫存區與版本庫文件的差異
查砍版本庫中當前提交:git ls-tree -l HEAD? ?其中-l顯示文件的大小
文件屬性(rw-r--r--),文件類型,對象ID,文件大小,文件名
查看暫存區目錄內容:git ls-files -s
文件屬性(rw-r--r--),對象ID,暫存區編號,文件名
如果想針對暫存區使用git ls-tree命令,可以使用:git write-tree|xargs git ls-tree -l -r -t
查看Git對象ID命令:git cat-file? ?-t(類型)-p(內容)
顯示引用的對應提交ID:git rev-parse (結合git cat-file可以進行版本追蹤)
git log --oneline精簡版追蹤日志,1.6.3版本及以后才有
git log --graph --stat 查看分支與合并信息
重置:
master分支在版本庫的引用目錄(.git/refs)中體現為一個引用文件.git/refs/heads/master,其內容就是分支中最新提交的提交ID。引用refs/heads/master就像一個游標,當有新提交發生時指向新的提交。git reset可以使游標指向任意一個存在的ID。
git reset --hard HEAD^? ?(HEAD^代表HEAD的父提交,既游標移動到上一個提交),使用重置命令可以回退到任意版本,但重置讓歷史改變了,意味著無法找到丟失的提交!慎用!
用reflog挽救錯誤的重置:.git/logs目錄記錄下的日志文件記錄了分支的變更,帶有工作區的版本庫有有以下配置git config core.logAllRefUpdates? --》 true。可以查看.git\logs\refs\heads\master文件,該文件記錄了master分支指向的變遷。命令模式:git reflog show master。
重置master為5次改變前的值:git reset --hard master@{5},提交歷史也會回來。
reset用法:
? ? 用法一:git reset [-q] [<commit>] [--] [paths] ...? -q為安靜模式,沒有提示信息
? ? 用法二:git reset [--soft | --mixed | --hard |--merge| --keep ] [-q] [<commit>]
其中<commit>都是可選項,可以使用引用或提交ID,如果省略了<commit>就相當于使用了HEAD的指向作為提交的ID。
用法一不會重置引用,也不會改變工作區,而是指定提交狀態<commit>下的<paths>替換掉緩存區中的文件,例如命令git reset HEAD <paths> 相當于取消之前add到暫存區時改變的暫存區。
用法二會重置引用。根據不同的選項,可以對暫存區和工作區進行重置:
使用--hard 如git reset --hard <commit>會執行三個動作:
1,替換引用的指向,引用指向新的提交ID
2,替換暫存區。替換后,暫存區的內容與引用指向的目錄樹一致。
3,替換工作區。替換后,工作區的內容和暫存區,HEAD指向的目錄樹內容相同。
使用--soft會執行1操作,既只改變了引用的指向,不改變暫存區和工作區
使用--mixed或不使用參數(默認為--mixed)會執行1,2操作,既改變引用指向和暫存區,不改變工作區。
命令:git reset,僅用HEAD指向的目錄樹重置暫存區,工作區不會受影響,相當于取消add
命令:git reset -- filename。僅將指定文件的改動撤出暫存區
命令:git reset --soft HEAD^。工作區和暫存區不變,但是引用向前回退一次。相當于取消上一次的commit。
命令:git reset? HEAD^。工作區不改變,暫存區和引用會回退一次。
命令:git reset --mixed HEAD^。同上。
命令:git reset --hard HEAD^。徹底撤銷最近的一次提交。而且工作區和暫存區都會回退到上一次提交狀態。自上一次提交全部消失。
檢出:
HEAD的重置既檢出。HEAD可以理解為頭指針,是當前工作區的基礎版本,這時執行git branch -v會看到當前處于master分支。當執行提交時,HEAD指向的提交將作為新提交的父提交。
git提示的大致意思
什么是分離頭指針:分離頭指針指的是HEAD頭指針指向了一個具體的提交ID,而不是一個引用(分支)。這個時候指向master變成了指向一個提交的ID。
查看一下HEAD和master對應的提交ID,會發現他們的指向不一樣:
master指向并沒有改變,而HEAD指向變了
如果現在添加新文件,會有以下提示:
這是因為HEAD處于分離頭指針模式
執行提交,在提交輸出中會出現detached HEAD標識。
detached HEAD提示
新提建立在之前的提交之上
? ? 切換到master分支上,git checkout master。HEAD重新指向了分支,沒有了斷頭模式(分離頭指針模式)
工作區的文件消失,提交日志也消失
使用git show 查看之前的提交ID可以看到這個提交仍然存在于版本庫,但這個提交不會永久存在,當reflog中含有該提交的日志過期后,該提交會被徹底清除。
分離頭指針模式下的提交只能使用提交ID訪問,如果master需要提交的內容,可以用git merge進行合并操作。
流程:1 確認當前分支(git branch -v)2.執行合并操作,將目標提交ID合并到當前分支。3.可查看日志,會看到合并的分支圖(git log --graph --pretty=oneline)4.查看最新提交的內容(git cat-file -p HEAD)可以看到這個提交有兩個父提交。
合并流程
檢出操作是最常用的命令之一,同時也是個危險的命令,因為這條命令會重寫工作區。
用法如下:
用法一:git checkout [-q] [<commit>] -- <paths>
用法二:git checkout [<breach>]
用法三:git checkout [-m] [-b|--orphan? <new_branch>]? [<start_point>]
用法一的<commit>是可選項,如果省略則從暫存區檢出。與重置命令大不相同:重置的默認值是HEAD,而檢出的默認值是暫存區。因此,重置一般用于重置暫存區(除非使用--hard否則不重置工作區),而檢出命令主要是覆蓋工作區(如果<commit>不省略,也會替換暫存區的相應文件)
用法一(包含<paths>的用法)不會改變HEAD頭指針,主要是用于指定版本的文件覆蓋工作區的對應文件。如果省略<commit>則會用暫存區的文件覆蓋工作區的文件,否則用指定提交中的文件覆蓋暫存區和工作區的文件。
用法二(不使用<paths>的用法)會改變HEAD頭指針,之所以后面參數寫作<branch>是因為只有HEAD切換到一個分支才可以對提交進行跟蹤。否則仍然會進入分離頭指針狀態。在分離頭指針狀態下的提交不能被引用關聯到,從而可能丟失。所以用法二的最主要作用就是切換到分支。如果省略<branch>則相當于對工作區進行狀態檢查。
用法三主要是用于創建和切換到新的分支(<new_branch>),新的分支從(<start_point>)指定的提交開始創建,新分支和我們熟悉的master分支沒有什么實質的不同,都是在refs/heads命名空間下的引用。
命令:git checkout branch。檢出branch分支,更新HEAD以指向branch分支,以及用branch指向的書更新暫存區和工作區。
命令:git checkout。匯總顯示工作區、暫存區與HEAD的差異。
命令:git checkout HEAD。同上。
命令:git checkout -- filename。用暫存區的filename文件來覆蓋工作區中的filename文件。相當于取消自上次執行git add filename以來的本地修改。這個命令很危險,因為對本地的修改會悄無聲息的覆蓋,毫不留情。
命令:git checkout branch -- filename。維持HEAD的指向不變,用branch所指向的提交中的filename替換暫存區和工作區中的相應文件,注意是直接覆蓋!
命令:git checkout --?.或寫作git checkout?.?。注意最后參數為一個點,這條命令最危險!會取消所有本地的修改(相對于暫存區)。用暫存區的所有文件直接覆蓋本地文件,不給用戶任何確認機會!
暫存區進度保存與恢復
保存進度命令:git stash
查看保存的進度:git stash list 可以多次保存工作進度,并在恢復時進行選擇。
恢復進度:git stash pop?
刪除多余目錄命令:git clean -nd(顯示會刪除哪些目錄)git clean -fd(真正強制刪除)
命令:git stash pop [--index] [<stash>] 如果不使用任何參數,會恢復最新保存的工作進度,并將恢復的進度從存儲的工作進度列表中清除。選項--index除了恢復工作區的文件之外,還嘗試恢復暫存區。<stash> git stash list中的進度列表 如 0 1 2
命令:git stash apply [--index] [<stash>]除了不刪除恢復的進度之外,其余和git pop一樣
命令:git stash drop [<stash>]刪除一個存儲的進度,默認刪除最新的進度
命令:git stash clear 。刪除所有存儲的進度
命令:git stash branch [branchname] <stash>
查看保存進度的引用信息:git reflog show refs/stash
刪除與移動、恢復
刪除命令:git rm 執行后會直接保存到暫存區,本地刪除則不會自動保存到暫存區
恢復上一次刪除的文件:git cat-file -p HEAD~1:filename > filename?
可使用show命令?git show HEAD~1:filename > filename代替,效果相同
最簡單可使用:git checkout HEAD~1 -- filename
HEAD~1相當于HEAD^。執行git add -A會將工作區所有改動以及新增文件添加到暫存區。
移動命令:git mv file1 file2
版本表示法
顯示分支: git rev-parse --symbolic --branches
顯示里程碑: git rev-parse --symbolic --tags
顯示定義的所有引用:git rev-parse --symbolic --glob=refs/*
將對應的git對象表達式表示為對應的SHA1值。
顯示里程碑:git describe --tags
版本范圍表示法
顯示該版本的所有歷史提交:git rev-list --online,實際上一個提交ID就可以代表一個版本列表
取兩個版本的并集?git rev-list --online a b?
取反,既排除這個版本及其歷史版本??git rev-list --online a^
點點表示法 表示上面如git rev-list --online a..b 相當于^a b
三點表示法含義是兩個版本共同能訪問到的排除出去。
某提交的歷史提交,將自身除外?git rev-list --online a^@
提交本身不包括其歷史提交git rev-list --oneline a^!
查看分支指向的提交ID git rev-parse brachname1 brachname2
瀏覽日志:git log
可接表示版本范圍的參數
分支圖表示:
git config --global alias.glog "log --graph"?
git glog --oneline
顯示每次提交的具體改動:git log -p -1
顯示每次提交的變更概要:git log --stat --oneline?
只顯示改動了哪些文件
定制顯示:--pretty?
--pretty=raw 顯示commit的原始數據,可以顯示提交對應的樹ID
--pretty=fuller -1會先作者和提交者
--pretty=oneline -1 會顯示精簡輸出
如果想查看和分析某一個提交,也可以使用git show 或git cat-file?
差異比較:git diff
比較里程碑B和里程碑A。git diff A B
比較工作區和里程碑A。git diff? A
比較暫存區和里程碑A。git diff --cached A
比較工作區和暫存區。git diff?
比較暫存區和HEAD。git diff --cached
比較工作區和HEAD。git diff HEAD
文件不同版本的比較。git diff <commit1> <commit2>? -- <paths>
非git目錄/文件的比較。git diff <path1> <path2>
文件回溯:git blame 會顯示文件,在每一行顯示此行最早在什么版本引入的,由誰引入的
二分查找:git bisect? start?
標記當前版本:git bisect?bad |good?
當找到壞提交后:標記git bisect?bad
修復好后:git bisect reset
git修補提交信息:git commit --amend -m "修補提交"。
命令git rebase是對提交進行變基操作。可實現將指定范圍內的提交“嫁接”到另一個提交上。
歸一化命令:git rebase --onto <newbase> <since> <till>
變基操作過程:1.首先會執行git checkout 切換到<till> ,如果<till>指向的不是一個分支(如master),則變基操作是在detacached HEAD(分離頭指針)狀態下進行的。當變基結束后,要對master分支執行重置以實現變基結果在分支中提交。2,.將<since>..<till>所標識的提交范圍寫到一個臨時的文件中,<since>..<til>是指包括<till>的所有提交排除<since>及<since>的歷史提交后形成的版本范圍。3.將當前分支強制重置(git reset --hard)到<newbase>。4.從保存在臨時文件中的提交列表按提交順序重新提交到重置之后的分支上。5.如遇到提交已經在分支中包含,則跳過該提交。? ? 6.如果在提交過程中遇到沖突,則變基過程暫停,用戶解決沖突后,執行git rebase --continue繼續變基操作,或執行git rebase --skip跳過此提交。或執行git rebase --abort終止變基操作并切換到變基前的分支上。
場景1:有A,B,C,D,E的歷史提交,現在要去掉C。
方法1:1、git rebase --onto B D^ E 。這時會進入分離頭指針狀態,,需要將master分支指向變基后的提交上
? ? ? ? ? ? ?2、git checkout master 。切換回master分支
? ? ? ? ? ? ?3、git reset --hard HEAD@{1}。使用了reflog語法HEAD@{1}相當于切換回master分支前的HEAD指向。
? ? ? ? ? ? ?4、完成變基操作。
? ? ? ? ? ? ?5、git reset --hard E重新布景
方法2:1、git checkout D。將HEAD指向D,這時會進如detached狀態。
? ? ? ? ? ? ?2、git reset --soft HEAD^^。回退兩次提交操作,B、C回到暫存區。
? ? ? ? ? ? ?3、git commit -C C。重新提交B、C所改動的內容,-C說明重用C的提交說明
? ? ? ? ? ? ?4、git tag newbase。用里程碑是記憶提交ID最好的方法。
? ? ? ? ? ? ?5、git rebase --onto newbase E^ master。執行變基操作,這個操作會直接修改master分支,無需對master進行重置操作。
? ? ? ? ? ? ?6、git tag -d newbase。刪除不需要的里程碑。
? ? ? ? ? ? ?7、完成變基操作。
git克隆:
用法1:將<repository>指向的版本庫創建一個克隆到<directory>目錄,目錄<directory>相當于克隆版本庫的工作區,文件都會檢出,版本庫位于工作區下的.git目錄中
用法2:克隆出的版本庫不包含工作區,只有版本庫的內容,這樣的版本庫稱為裸版本庫,一般約定以.git為后綴。
用法3:與用法2的區別在于版本庫對上游版本庫進行了注冊,這樣可以用git fetch命令與上游版本庫進行持續同步。
git分支:
用法1:用于顯示本地分支列表,當前分支會以*號顯示。
用法2:基于當前HEAD指針指向的提交創建新分支。
用法3:基于提交<start-point>創建新分支。
用法4:用與刪除分支,刪除時要檢查所刪除的分支是否已經合并到其他分支中,否則拒絕刪除。
用法5:強制刪除分支。
用法6:重命名分支,如果已經存在該分支名則拒絕執行。
用法7:強制重命名分支。
創建分支后立刻切換分支:git checkout -b <branchname> [<start_point>]。
分支合并到master: git merge branchname,實際上合并后master分支和開發分支指向同一個提交,這是因為合并前master分支的提交就是開發分支的父提交,所以相當與本次將分支master重置到開發分支。默認情況下,Git執行"快進式合并"(fast-farward merge),會直接將Master分支指向Develop分支。
fast-farward merge
使用--no-ff參數后,會執行正常合并,在Master分支上生成一個新節點
查看本地分支哪些提交領先遠程版本庫:git cherry
創建發布分支:
場景:發布版本出現bug,master分支存在修改,就必須以基于發布版本的代碼創建分支。因此在發布版本時需要給發布版本打上里程碑,當線上出現bug時使用命令:git checkout -b? fix_v1.0? v1.0 ,修復后推送至遠程共享庫git push origin,其他開發者使用命令git fetch拉取該分支,拉取完后切換到該分支git checkout -b fix_v1.0 origin/fix_v1.0,該遠程分支不能直接檢出,而是需要基于該遠程分支創建本地分支然后基于該本地分支進行開發,當開發完成后需要將代碼推送至本地倉庫,此時推送會遇到非快進式推送的問題。此時需要一個拉回操作,將遠程服務器的改動獲取到本地并和本地提交進行合并,合并之后就可以推送至遠程倉庫了。
合并到主線:
當開發者在fix_v1.0中將相應的bug修改完后,就需要將代碼合并到主線。
流程:切換至master分支,從遠程代碼庫同步master分支,查看分支fix_v1.0的日志,確認要揀選的提交ID,git log -3 --graph --oneline fix_v1.0。
揀選到主線git cherry-pick fix_v1.0^。
沖突解決:當挑選分支上的一個提交到master分支時,可能出現多個提交在重疊位置更新代碼,通過以下命令可以看到底是哪些提交引起的沖突
git log master...fix_v1.0。并使用圖形話界面解決沖突。解決沖突后執行推送命令將本地master分支同步到遠程版本庫。
刪除本地分支:git branch -d branchname
刪除遠程分支:git push origin :branchname
遠程版本庫
? ? 多版本交互:
? ? 流程:1、克隆2個版本庫裸版本git clone --bare .git user.git。 2、?查看遠程版本庫有哪些版本:git ls-remote --heads file:///d:/user.git
3、克隆user.git版本庫git clone file:///d:/user1.git。4、進入user本地版本庫cd d:/user。5、執行git branch會看到只有一個master分支。
6、執行git show-ref可以查看所有的本地引用。
? ? 查看遠程倉庫分支:git branch -r?
? 注冊新遠程版本庫:git remote add new-remote file:///d:/user2.git
? 顯示已經注冊的遠程版本庫:git remote -v
? 從新的遠程版本庫中獲取分支:git fetch new-remote
? 重命名遠程分支名:git remote rename newname oldname
? 當注冊了多個遠程版本庫并希望獲得所有版本庫的更新時,使用命令:git remote update?
? 刪除遠程版本庫:git remote rm new-remote
git pull和git fetch 的區別:
.一、遠端跟蹤分支不同
1、Git fetch:Git fetch能夠直接更改遠端跟蹤分支。
2、git pull:git pull無法直接對遠程跟蹤分支操作,我們必須先切回本地分支然后創建一個新的commit提交。
二、拉取不同
1、Git fetch:Git fetch會將數據拉取到度本地倉庫 - 它并不會自動合專并或修改當前的工作。
2、git pull:git pull是從遠程獲取最新版本并merge到本地,會自動合并或修改當前的工作。
三、commitID不同
1、Git fetch:使用Git?fetch更新代碼,屬本地的庫中master的commitID不變,還是等于1。
2、git pull:使用git pull更新代碼,本地的庫中master的commitID發生改變,變成了2。
Git協同模型
容易帶入不成熟代碼,造成數據丟失
1.創建本地分支git checkout -b my/dev 2.創建遠程獨享分支git push origin my/dev 3.開發完成后將本地分支合并到主線上,推送到共享版本庫
Git子模組協同模型:
創建子模組:git submoddule add submodule.git? localpath
添加完成后在super版本庫根目錄上多了一個.gitmodules文件
查看子模組狀態git submodule status,前面的減號含義是該子模組尚未檢出
如果需要克隆子模組形式引用的外部庫,需要先執行git submodule init,然后執行git submodule update完成子模組版本庫的克隆。
子模組的修改和更新:在父項目中修改子模組內容后,需進入到子模組,此時子模組會進入分離頭指針狀態,此時執行提交后,git checkout master切換到master分支,執行git merge操作,然后執行git push推送至遠程子模組。然后cd 到父項目,將子模組添加并提交,執行git push完成子模組更新。
fast-farward merge