Git的其他用法


目錄:


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

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

雖然對於小項目,增大的速度極慢,文件夾也基本在10M左右。但如果你和我一樣,想減少該文件夾的文件數目(通常不少),可以試試這個命令。當然,git是鼓勵你多使用這個命令的。見:Git - git-gc Documentation

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

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

我們來看看執行gc命令前后的對比:

運行 git gc 前:

運行 git gc 后:

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

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

我們先看看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 的,能防止因為其他沒配置好而產生錯誤。對我來說差別並不大……


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM