Git的其餘用法

目錄:


減小【.git】文件夾的大小和文件數

隨着commit次數的增多,.git文件夾的文件數和文件夾大小都會不斷增大。html

雖然對於小項目,增大的速度極慢,文件夾也基本在10M左右。但若是你和我同樣,想減小該文件夾的文件數目(一般很多),能夠試試這個命令。固然,git是鼓勵你多使用這個命令的。見:Git - git-gc Documentationgit

Users are encouraged to run this task on a regular basis within each repository to maintain good disk space utilization and good operating performance.github

如何減小?特別簡單,就是你進入到一個repository,也就是你項目的根目錄,執行 git gc 就好了。shell

咱們來看看執行gc命令先後的對比:vim

運行 git gc 前:windows

運行 git gc 後:app

文件夾大小變化不大。變化最大的是文件數目(2561 -> 37)和文件夾數(274 -> 18)。編輯器

要講清楚這個命令,涉及到了git是如何存儲你的commit。這就要說到快照(Snapshot)ide

咱們先看看git的官方說明:直接記錄快照,而非差別比較工具

每次你提交更新,或在 Git 中保存項目狀態時,它主要對當時的所有文件製做一個快照並保存這個快照的索引。 爲了高效,若是文件沒有修改,Git 再也不從新存儲該文件,而是隻保留一個連接指向以前存儲的文件。 Git 對待數據更像是一個 快照流。

那麼問題來了:什麼是快照?

來實際感覺一下:

首先我準備了一個大的文件,這樣比較能說明問題。恰好今天整理一個文件,有55.3MB,就順手拿來用了。

能夠看到,源文件是55.3MB,而將其添加到倉庫裏後,倉庫的大小變爲46.3MB。這至關因而將整個文件複製到裏面去。

若是這還不能說明問題,再來一次。我刪除了文件裏的一大部份內容,將其減少至20.5MB。再將其提交到倉庫裏面。

增長了19MB,跟20.5MB很接近。

你能夠在 .git\objects\某個文件夾 裏找到這兩份快照。

因而咱們能夠得出一個近似的結論:在git中,一份快照就是你當前工做目錄的狀態。當你使用add命令時,它將你當前工做目錄的文件進行壓縮,造成一份快照。

不過,若是你有一些文件徹底沒有被修改過,它只保存指向以前版本的引用。這樣能夠減小快照所佔用的空間。這裏沒有試驗,可是官方對此有說明:
To be efficient, if files have not changed, Git doesn’t store the file again, just a link to the previous identical file it has already stored.

那麼這個時候咱們再去執行 git gc ,會變成什麼樣呢?

以前說的三個方面都有減小。

咱們再看看.git\objects裏的文件夾(事先不知道它會刪除文件夾,沒有截圖。。)

能夠看到咱們上面快照所在文件,即02f7文件夾已經不在objects這個文件夾裏面了。(info和pack兩個文件夾一直都在那裏)

點進pack文件夾:

.git 文件夾的46.5M都在這裏了。因此咱們能夠知道,git將以前兩個文件夾的快照文件合併到一塊兒了。


更換git for windows的文本編輯器

git for windows默認使用vim做爲文本編輯器,爲此我專門寫了篇vim的基本操做:vim編輯器的簡單使用

若是你不想學習vim的使用,也能夠把它換掉。

例如我想把它換成atom

  1. 先找到啓動atom的exe文件的路徑。個人在 C:\Users\Schaepher\AppData\Local\atom\app-1.13.0\atom.exe
  2. 啓動git for windows,執行git config --global core.editor "C:/Users/Schaepher/AppData/Local/atom/app-1.13.0/atom.exe --new-window --foreground --wait"

    注意,這裏路徑的斜槓與Windows顯示的相反,這是Linux的路徑格式。
    後面一串參數--new-window --foreground --wait是由各編輯器本身指定的。若是不這樣指定,執行git rebase -i commitId^的時候會直接退出編輯。


修改已經提交的commit說明

先用git log查看commit信息:

我打算更改下面那個commit,使用git rebase -i 版本號^

執行命令後,會進入這樣的界面:

它把咱們傳入的版本號之上的commit條目都顯示出來了,這裏只關注咱們要改的那一條。將第一個pick修改成reword,保存並退出。

過一下子,它會再進入這樣的界面:

將第一行的Android的ListView改成這個更改後的message,保存並退出。

再用git log查看:

不只commit message被更改了,從被更改的commit開始,commit id都會從新生成。


合併commit

先用git log查看commit信息:

若是你想把最近的四個commit合併成一個commit,有兩種方法。一種是用git reset --soft d7ac,在git commit -m "新的commit message",另外一種是用git rebase。接下來說第二種。

首先根據上圖的commit id,我想把afe14f以後的commit合併到afe14f裏面,執行 git rebase -i afe14f^。進入編輯界面:

根據提示,squash會把所在的commit合併到前一個commit上面。咱們要合併到afe14f,因此修改後三個。而在合併以後,咱們須要修改afe14f的commit message,因此使用reword

你也能夠用縮寫,好比squash的縮寫是s。而reword的縮寫是s

保存並退出,會進入下一個界面。修改第一行的commit message,即reword的那個message,爲添加Android學習筆記,特別是ListView的介紹;添加對git commit的修改教程。以下圖:

保存並退出。自動進入下一個界面:

此時要將其餘三個message去掉,只要在那三行前面加#就好了。以下圖:

保存並退出,等待git處理完成。

再次使用git log查看commit信息:

完成!

這裏貌似能夠不使用reword,待實驗。


解決merge時出現的衝突

當你和其餘團隊成員對同一個文件進行修改後,merge的時候有可能會出現衝突。你能夠打開每一個衝突的文件,手工解決衝突;也能夠藉助衝突處理工具來解決衝突。這裏分別介紹這兩種方式:

  1. 手工解決衝突

    衝突提示以下圖所示:

    CONFLICT表示有衝突,在這一行的末尾,顯示衝突文件。這裏有兩個文件衝突,分別是README.md和app.iml
    這裏以README.md爲例,解決衝突:

    被紅框框住的符號 ======= 是衝突的分割線。

    <<<<<<< HEAD 和分割線之間的是本地的文本,分割線和 >>>>>>> upstream/dev 之間的是遠程分支的文本

    你能夠選擇保留其中一個版本的文本,而後將三個衝突符號都刪除。這樣表示已解決衝突。若是你想同時保留兩個版本,那麼只需將衝突符號刪除。

    解決衝突後以下圖所示:

  2. 藉助衝突處理工具
    我的認爲Meld這個工具比較好用,Android Studio自帶的衝突處理工具和它很類似。我用過tortoisegit的工具,感受沒有Meld好用,這裏就不介紹了。

    (1) 首先去Meld的官網下載安裝文件並安裝。->點此進入Meld官網

    (2) 安裝完後,打開你的git工具,好比msysgit。執行 git config --edit --global ,此時會打開一個配置文件。在文件最後添加如下四行:

    [merge]  
                 tool = meld  
        [mergetool "meld"] 
                 path = e:/software/MeldMergeTool/Meld.exe

    提示:path是根據你安裝Meld的路徑來決定的,同時要把路徑中的 \ 改爲 / 。從上面能夠看出個人安裝路徑爲 e:\software\MeldMergeTool\

    (3) 在merge的時候,若是出現衝突,運行命令 git mergetool 這時就會打開Meld。

    (4) Meld的界面以下:

    衝突的地方會顯示紅色,若是你想保留本地的代碼,則點擊左邊的 箭頭。

    把全部紅色(衝突)區域解決後,能夠根據實際狀況去解決綠色(添加)和灰色(更改)。

    通常保存中間的修改就行。如上圖紅框處。


回退一個merge

  1. 若是是merge一個GitHub的Pull Request,能夠進入要回退的那個Pull Request,在下面有一個revert按鈕,能夠用來revert一個Pull Request。以下圖紅框處:

  2. 在命令行裏revert

    (1)用 git log 看commit記錄

    如今咱們要回退 commit 561dab (也就是圖中第一個commit),該commit將Pull Request #113 merge到項目中。

    (2)使用 git revert HEAD -m 1 命令回退

    若是是非merge的回退,用 git revert 版本號 就好了。可是這裏是對merge操做進行revert,須要加上參數 -m 。命令最後加個 1

    爲何要加上 1 呢?看上面(1)的圖中的第二個紅框,這個 1 對應紅框中的 6a3c30c 版本。而若是填 2 ,則對應 b7831df

    繼續看log,會發現 6a3c30c 是merge這個Pull Request以前的狀態。而 b7831df 則是當前版本以前的一個merge。

    輸入命令回車後,會跳出一個文本。

    目前無視它就行。關閉文本,回到shell,回車。

    回退成功!這個回退不會刪除掉中間的commit記錄,而是將此次revert做爲一個commit加到commit記錄上面。


獲取某一commit的修改

假設有commit a b c ,從左到右,c 爲最新版。
這時你發現 b 的一個修改有問題,想回退到 a 。可是若是回退到 ac 的commit也會被取消。
這時能夠用 git cherry-pick 版本號 這個命令獲取 c 的commit。

下圖是示例的log記錄,從①能夠看出,這裏從②回退到⑤。

如今我想獲取④的commit。使用 git cherry-pick 版本號 將選定版本的提交合併到當前版本。


將低版本push到Github(刪掉高版本Commit)

有時候會由於各類緣由,想要回退版本。若是沒有關聯Github或者沒有push上去,那問題不大。可是若是你已經push到Github上了,這時候就比較尷尬了,由於普通的push是會被Github拒絕的。雖然Github提供了Revert功能,可是這並不能徹底消去一個commit。

先看看reset後被拒絕的樣子:

解決方法就是:

  1. 先用 git reset --hard 版本號 回到你想要的版本
  2. 執行 git push --force

    再看看Github:

    固然,通常是推薦用 git push origin HEAD --force 的,能防止由於其餘沒配置好而產生錯誤。對我來講差異並不大……

相關文章
相關標籤/搜索