使用這12個Git的訣竅與技巧來令你的版本控制經驗更加有用。java
Git,一個分佈式版本控制系統,它已經成爲了開源世界的源碼控制默認工具,在4月7號12歲了。可是使用Git中更另人沮喪的是,你須要瞭解多少才能讓你更有效的使用它。同時這也是使用Git中比較美妙的一件事,由於沒有什麼比發現一個新的小技巧來簡化或提升你的工做流的效率更加使人快樂了。git
爲了記念Git的12歲生日,這篇文章提供12個訣竅與技巧來讓你的Git經驗更加有用和強大,從一些你可能會忽視的基礎開始到一些真正的強大技巧!面試
1. 你的 ~/.gitconfig 文件算法
在第一次用git命令來提交一個倉庫的修改,你可能會首先看到像下面這種內容:shell
Please tell me who you are. Run git config --global user.email "you@example.com" git config --global user.name "Your Name" to set your account's default identity.
你可能尚未意識到那些命令正在修改~/.gitconfig文件的內容,這個文件就是Git存儲全局配置選項的文件。經過你的~/.gitconfig文件你可要作不少事情,包括定義別名,永久的打開(或關閉)一些特定的命令選項,還能夠修改Git如何工做的方面(例如:git diff使用哪一個diff算法,或者默認使用什麼類型的的合併策略)。你甚至能夠按條件地基於路徑包含其餘配置文件到一個倉庫!使用「man git-config」查看全部細節。npm
2. 你的倉庫的.gitconfig文件後端
在以前的技巧中,你可能會想知道在git config 命令中的—global標識是作什麼的。它告訴Git更新「global」配置,也就是~/.gitconfig發現的這個配置。固然,擁有一個全局的配置表明了一個本地配置,並且足夠確定的是,若是你省略—global選項,git config 會更新這個倉庫本身的配置,這個配置文件存儲在.git/config。多線程
在.git/config中設置的選項會推翻在~/.gitconfig文件中的對應設置。所以,例如,若是你須要在一個特定的倉庫中使用一個不一樣的郵箱地址,你能夠運行「git config user.email "also_you@example.com"」。而後,你在這個倉庫中提交會使用你單獨配置的這個郵箱地址。若是你使用一個工做的電腦在開源項目中工做,可是但願在這個項目中使用我的的郵箱地址,而其餘在主Git配置中仍然使用工做郵箱,這一點是很是有用的。架構
在~/.gitconfig中能夠設置的任何東西,均可以在.git/config中設置來對這個倉庫作特定設置。在下面的這些技巧中,當我提到在你的~/.gitconfig文件中添加什麼東西,同時也說明能夠在特定的倉庫的.git/config中添加來設置那個選項。分佈式
三、別名
別名是你能夠在你的~/.gitconfig文件裏作的另一件事。他的工做原理就像shell命令行裏的別名——設置一個新的命令名稱來調用一個或者多個其餘的命令,這些命令一般包括一些特定的選項或標識。別名對於你常用的那些又長又複雜的命令行是很是有效的。
你可使用git config命令來定義別名——例如,執行」git config —global —add alias.st status」命令後,會使得執行git st與執行git status作的是一樣的事情——然而,我發現當定義別名的時候,只須要直接在~/.gitconfig文件裏編輯一般會更加容易。
若是你選擇這麼作,你會發現~/.gitconfig文件就是一個INI文件,INI是一種帶有特定段落的基礎鍵值對文件格式。添加一個別名時,你將改變[alias]段落。例如:上面提到的定義相同的git st別名,須要添加下面這段代碼:
[alias] st = status
(若是已經有了[alias]這個段落,只須要在這個段落中添加到第二行)
4. shell命令中的別名
別名不只僅是運行其餘Git子命令——你也能夠定義別名,這些別名能夠運行其餘shell命令。這是一個很好的方法來處理一個重複的、罕見的、複雜的任務:一旦你已經想到第一次怎麼作,那就使用一個別名保存這個命令。例如,我有幾個倉庫是我fork了一個開源項目,並且在本地作了一些修改,這些修改不用貢獻給這個項目。在項目的持續的開發的過程當中我想保持最新的版本,同時保留個人本地修改。爲了完成這個想法,我須要按期地從upstream倉庫中合併這些修改到個人fork——我定義一個別名「upstream-merge」來完成這個操做。定義以下:
upstream-merge = !"git fetch origin -v && git fetch upstream -v && git merge upstream/master && git push"
別名定義開始的這個「!」是告訴Git來經過shell運行這個命令。這個例子包括了運行一些git命令,可是使用這種方式定義別名能夠運行任何shell命令。
(注意:若是你想複製個人upstream-merge別名,你將須要確認你有一個Git remote命名爲upstream來指定這個你fork的upstream倉庫。你能夠經過「git remote add upstream 」來添加一個。)
5. 可視化提交圖
若是你從事的是一個有不少分支活動的項目,有時可能很難掌握全部正在發生的工做以及它們之間的相關性。各類GUI工具可以讓你弄清楚不一樣分支的概況以及在所謂的「提交圖」中提交記錄。例如,如下是我使用 GitLab 提交圖查看器進行可視化的一個存儲卡的部分截圖:
John Anderson, CC BY
若是你是專一於命令行的用戶,就能夠不在多個工具之間切換致使分心,這個工具在命令行上實現了相似圖形界面的提交視圖。經過 -- graph 參數獲取 git 的記錄:
John Anderson, CC BY
下面的命令能夠獲得同樣的倉庫可視化片斷:
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
--graph 選項將圖表添加到日誌的左側, --abbrev-commit 存儲提交使用了 SHA 方法, --date=relative 表達式用相對的術語來表示日期,而且 --pretty 以 bit 格式處理自定義格式。我知道 git lg 的別名,它是我最常運行的10個命令之一。
6. 更優雅的強制推送(force-push)
有時,就跟你儘可能避免使用它同樣困難的是,你會發現你須要運行 git push --force 來覆寫你倉庫的遠程副本上的歷史記錄。你可能已獲得了一些反饋,他們會要求你進行交互式的變基(rebase),或者你可能已經搞砸了,而且但願隱藏證據。
當他人在倉庫的遠程副本的同一分支上進行改動後,會發生強制推送的風險。當你強制推送已重寫的歷史記錄時,某些提交將會丟失。這是 git push --force-with-lease 出現的緣由 - 若是遠程分支已更新,它不會容許你執行強制推送,這將確保你不會丟棄他人的工做。
7. git add -N
你是否使用過git commit -a在一次行動中提交你全部未完成的修改,只有在你push完你的提交後才發現git commit -a忽略了新添加的文件?解決這個問題你能夠用git add -N(「通知」)來告訴Git你想把新添加的文件包含在提交中在你第一次實際提交以前。
8. git add -p
一最佳的實踐爲當使用Git時確保每一個提交只包含一個邏輯更改--無論是修復一個bug仍是(實現)一個新功能。然而, 有時當你工做 ,會在你的倉庫中出現一個以上的修改 提交 。你怎麼樣把事情分開,使每一個提交只包含適當的修改呢?git add --patch來解救!
這個標誌將會使git add命令查看你工做副本中全部的變動,詢問你是否願意將它提交,跳過,或者推遲決定(還有其餘一些更強大的選項,你能夠經過在運行這命令後選擇?來查看)。git add -p是一個神奇的工具來生產結構良好的提交。
9. git checkout -p
與 git add -p相似,git checkout命令將使用 --patch 或 -p 選項,這會使 git 在本地工做副本中展現每一個「大塊」的改動,並容許丟棄對應改動 —— 簡單地說就是恢復本地工做副本到你改變以前的狀態。
某些場景下這很是有用,例如,在你跟蹤一個 bug 時引入了一堆調試日誌語句,在修正了這個 bug 以後,你能夠先使用 git checkout -p 刪除全部新加的調試日誌,以後使用 git add -p 來添加 bug 修復。沒有比組合一個極好的、結構良好的提交更使人滿意的了
10. Rebase with command execution
有些項目有一條規則,即存儲庫中的每一個提交都必須處於可工做狀態 - 也就是說,在每次提交時,代碼應該是可編譯的,或運行測試套件應該不會失敗的。當你在某分支上工做時間長時,但若是你最終由於某種緣由須要rebase時,那麼跳過每一個變基後的提交以確保你沒有意外引入一箇中斷是有些冗長乏味的。
幸運的是,git rebase已經支持了-x或--exec選項。git rebase -x 將在每次提交應用到rebase後運行該命令。所以,例如,若是你有一個項目,其中npm run tests會運行你的測試套件,那麼在rebase期間應用每次提交後,git rebase -x npm run tests將會運行測試套件。這使你能夠查看測試套件是否在任何變基後的提交中有失敗狀況,所以你能夠確保測試套件在每次提交時仍能經過。
11. 基於時間修改的指南
不少Git子命令都接受一個修正的參數來決定命令做用於倉庫的哪一個部分,多是某次特定的提交的 sha1 值,或者一個分支的名稱,又或者是一個符號性的名稱如 HEAD(表明當前檢出分支最後一次的提交),除了這些簡單的形式之外,你還能夠附加一個指定的日期或時間做爲參數,表示「這個時間的引用」。
這個功能在某些時候會變得十分有用,好比當你處理最新出現的 bug,自言自語道:「這個功能明明昨天仍是好好的,到底又改了些什麼」,不用盯着滿屏的 git 日誌的輸出試圖弄清楚何時更改了提交,您只需運行 git diff HEAD@{yesterday},會看到從昨天以來的全部修改,這也適用於較長的時間段(例如 git diff HEAD@{'2 months ago'}) ,以及一個確切的日期(例如git diff HEAD@{'2010-01-01 12:00:00'})。
您還能夠將這些基於日期的修改參數與使用修正參數的任何 Git 子命令一塊兒使用。在 gitrevisions 手冊頁中有關於具體使用哪一種格式的詳細信息。
12. 全知的 reflog
你是否是試過在 rebase 時幹掉過某次提交,後來又發現你須要保留此次提交的一些東西?你可能以爲這些提交的東西已經永遠找不回來了,只能從頭再來了。其實否則,但若是你在本地工做副本中提交了,提交就會進入到 "引用日誌" ,你仍然能夠訪問到。
運行 git reflog 將在本地工做副本中顯示當前分支的全部活動的列表,併爲您提供每一個提交的 SHA1 值。一旦發現你 rebase 時放棄的那個提交,你能夠運行 git checkout 來檢出該次提交,複製好你須要的信息,而後再運行 git checkout HEAD 返回到分支最新的提交去。
但願這些技巧中至少有一個能教你一些關於 Git 的新知識,Git 已經 12 歲了,在這個持續創新,不斷添加新特性的項目裏,你最喜歡哪一個技巧?
原文: https://opensource.com/articl...
譯文: https://www.oschina.net/trans...
關注公衆號Java技術棧回覆"面試"獲取我整理的2020最全面試題及答案。
推薦去個人博客閱讀更多:
2.Spring MVC、Spring Boot、Spring Cloud 系列教程
3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程
以爲不錯,別忘了點贊+轉發哦!