您好,登錄后才能下訂單哦!
本篇內容主要講解“Git使用技巧實例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Git使用技巧實例分析”吧!
在安裝好git后,你第一件該做的事是設置你的名字和電子郵箱,因為每次提交都要用到這些信息:
$ git config --global user.name "some one" $ git config --global user.email "someone@gmail.com"
保存在git里的一切都是文件。當你創建一個提交的時候,會建立一個包含你的提交信息和相關數據(名字,郵件地址,日期/時間,前一個提交,等等)的文件,并把它鏈接到一個樹文件中。這個樹文件中包含了對象或其他樹的列表。這里的提到的對象(或二進制大對象)是和本次提交相關的實際內容(它也是一個文件,另外,盡管文件名并沒有包含在對象里,但是存儲在樹中)。所有這些文件都使用對象的sha-1哈希值作為文件名。
用這種方式,分支和標簽就是簡單的文件(基本上是這樣),包含指向該提交的sha-1哈希值。使用這些索引會帶來優秀的靈活性和速度,比如創建一個新分支就是簡單地用分支名字和所分出的那個提交的sha-1索引來創建一個文件。當然,你不需要自己做這些,而只要使用git命令行工具(或者gui),但是實際上就是這么簡單。
你也許聽說過叫head的索引。這只是簡單的一個文件,包含了你當前指向的那個提交的sha-1索引值。如果你正在解決一次合并沖突然后看到了head,這并不是一個特別的分支或分支上的一個必需的特殊位置,只是標明你當前所在位置。
所有的分支指針都保存在.git/refs/heads里,head在.git/head里,而標簽保存在.git/refs/tags里 - 自己可以隨便進去看看。
在歷史中查看一個合并提交的信息時,你將看到有兩個父節點(不同于工作副本上的常規提交的情況)。第一個父節點是你所在的分支,第二個是你合并過來的分支。
目前我相信你碰到過合并沖突并且解決過。通常是編輯一下文件,去掉<<<<,====,>>>>標志,保留需要留下的代碼。有時能夠看到這兩個修改之前的代碼會很不錯,比如,在這兩個現在沖突的分支之前的改動。下面是一種方式:
$ git diff --merge diff --cc dummy.rb index 5175dde,0c65895..4a00477 --- a/dummy.rb +++ b/dummy.rb @@@ -1,5 -1,5 +1,5 @@@ class myfoo def say - puts "bonjour" - puts "hello world" ++ puts "annyong haseyo" end end
如果是二進制文件,比較差異就沒那么簡單了...通常你要做的就是測試這個二進制文件的兩個版本來決定保留哪個(或者在二進制文件編輯器里手工復制沖突部分)。從一個特定分支獲取文件拷貝(比如說你在合并master和feature123兩個分支):
$ git checkout master flash/foo.fla # 或者... $ git checkout feature132 flash/foo.fla $ # 然后... $ git add flash/foo.fla
另一種方式是通過git輸出文件 - 你可以輸出到另外的文件名,然后當你決定了要用哪個后,再將選定的正確文件復制為正常的文件名:
$ git show master:flash/foo.fla > master-foo.fla $ git show feature132:flash/foo.fla > feature132-foo.fla $ # 檢出master-foo.fla和feature132-foo.fla $ # 假如說我們決定來自feature132的文件是正確的 $ rm flash/foo.fla $ mv feature132-foo.fla flash/foo.fla $ rm master-foo.fla $ git add flash/foo.fla
更新:感謝carl在原博客文章上評論里的提醒,你實際上可以用“git checkout —ours flash/foo.fla”和“git checkout —theirs flash/foo.fla”來檢出特定版本的文件,而不用記住你在合并的分支名字。就我個人來說喜歡更精確一點,但這也是一種方式...
記著在解決完沖突后要將文件加入提交(像我上面做的那樣)。
git的一個超強大的功能就是可以有不止一個遠端服務器(實際上你一直都在一個本地倉庫上工作)。你并不是一定都要有這些服務器的寫權限,你可以有多個可以讀取的服務器(用來合并他們的工作)然后寫入到另外一個倉庫。添加一個新的遠端服務器很簡單:
$ git remote add john git@github.com:johnsomeone/someproject.git
如果你想查看遠端服務器的信息可以這樣做:
# 顯示每個遠端服務器的url $ git remote -v # 提供更多詳細信息 $ git remote show name
你隨時都可以查看本地分支和遠端分支的差異:
$ git diff master..john/master
你也可以查看沒有在遠端分支上的head的改動:
$ git log remote/branch.. # 注意:..后面沒有結束的特定引用
在git里有兩種類型的標簽 - 輕量級標簽和帶注釋標簽。記住技巧2里說過git是基于指針的,這兩者之間的差異也很簡單。輕量級標簽只是一個簡單的指向一次提交的帶名字指針。你隨時都可以將它指向另一個提交。帶注釋標簽是一個指向標簽對象的帶名字指針,帶有自己的信息和歷史。因為有自己的信息,它可以根據需要用gpg簽名。
建立這兩種類型的標簽都很簡單(只有一個命令行開關的差異)
$ git tag to-be-tested $ git tag -a v1.1.0 # 會提示輸入標簽的信息
在git里建立分支非常簡單(而且像閃電一樣快,因為它只需要創建一個小于100字節的文件)。用普通方式建立新分支并切換過去:
$ git branch feature132 $ git checkout feature132
當然,如果你確定自己直接切換到新建的分支,可以用一個命令實現:
$ git checkout -b feature132
如果你想重命名一個本地分支也很簡單(可以顯示發生了什么的較長的方式):
$ git checkout -b twitter-experiment feature132 $ git branch -d feature132
更新:你也可以(像brian palmer在原博客文章的評論里提出的)只用“git branch”的-m開關在一個命令里實現(像mike提出的,如果你只指定了一個分支參數,就會重命名當前分支):
$ git branch -m twitter-experiment $ git branch -m feature132 twitter-experiment
也許在將來的某個時候,你希望將改動合并。有兩種方式:
$ git checkout master $ git merge feature83 # 或者... $ git rebase feature83
merge和rebase之間的差別是merge會嘗試處理改動并建立一個新的混合了兩者的提交。rebase會嘗試把你從一個分支最后一次分離后的所有改動,一個個加到該分支的head上。不過,在已經將分支推到遠端服務器后不要再rebase了 - 這會引起沖突/問題。
如果你不確定在哪些分支上還有獨有的工作 - 所以你也不知道哪些分支需要合并而哪些可以刪除,git branch有兩個開關可以幫你:
# 顯示已經全部合并到當前分支的分支 $ git branch --merged # 顯示沒有合并到當前分支的分支 $ git branch --no-merged
如果你在本地有一個分支希望推到遠端服務器上,你可以用一行命令推送上去:
$ git push origin twitter-experiment:refs/heads/twitter-experiment # origin是我們服務器的名字,而twitter-experiment是分支名字
更新:感謝erlend在原博客文章上的評論 - 這個實際上和git push origin twitter-experiment效果一樣,不過使用完整的語法,你可以在兩者之間使用不同的分支名(這樣本地分支可以是
add-ssl-support而遠端是
issue-1723)。
如果你想在遠端服務器上刪除一個分支(注意分支名前面的冒號):
$ git push origin :twitter-experiment
如果你想查看所有遠端分支的狀態可以這樣做:
$ git remote show origin
這個命令可能會列出服務器上一些以前有過但現在已經不在了的分支。如果碰到這種情況你可以用下面的命令從你本地分支里清理掉:
$ git remote prune
最后,如果你想在本地跟蹤一個遠端分支,普通的方式是:
$ git branch --track myfeature origin/myfeature $ git checkout myfeature
不過,新版的git在使用-b標記檢出分支時會自動設定跟蹤:
$ git checkout -b myfeature origin/myfeature
在git里你可以把當前工作狀態放進一個儲藏堆棧中,然后可以再取出來。最簡單的情形是下面這樣:
$ git stash # 做點其他事情... $ git stash pop
許多人建議使用git stash apply來代替pop,不過如果這樣做的話最后會遺留一個很長的儲藏列表。而“pop”會在全部加載后自動從堆棧中移除。如果使用過
git stash apply,你也可以使用下面的命令從堆棧上移除最后一項:
$ git stash drop
git會基于當前的提交信息自動創建評論。如果你更希望有自定義信息的話(因為它可能和前一個提交沒有任何聯系):
$ git stash save "my stash message"
如果你希望從列表中取出一個特定的儲藏點(不一定非得是最后一個)可以先列出它們然后用下面的方式取出:
$ git stash list stash@{0}: on master: changed to german stash@{1}: on master: language is now italian $ git stash apply stash@{1}
在subversion的世界里你只能修改文件然后提交所有改動。而在git里你有強大得多的方式來提交部分文件或者甚至是部分補丁。提交部分文件或文件中的部分改動你需要進入交互式模式:
$ git add -i staged unstaged path *** commands *** 1: status 2: update 3: revert 4: add untracked 5: patch 6: diff 7: quit 8: help what now>
這會讓你進入一個基于菜單的交互式提示。你可以使用命令中的數字或高亮的字母(如果你在終端里打開了高亮的話)來進入相應的模式。然后就只是輸入你希望操作的文件的數字了(你可以使用這樣的格式,1或者1-4或2,4,7)。
如果你想進入補丁模式(交互式模式下按‘p'或‘5'),你也可以直接進入:
$ git add -p diff --git a/dummy.rb b/dummy.rb index 4a00477..f856fb0 100644 --- a/dummy.rb +++ b/dummy.rb @@ -1,5 +1,5 @@ class myfoo def say - puts "annyong haseyo" + puts "guten tag" end end stage this hunk [y,n,q,a,d,/,e,?]?
你可以看到下方會有一些選項供選擇用來添加該文件的這個改動、該文件的所有改動,等等。使用‘?'命令可以詳細解釋這些選項。
有些項目(比如git項目本身)在git文件系統中直接保存額外文件而并沒有將它們加入到版本控制中。
讓我們從在git中存儲一個隨機文件開始:
$ echo "foo" | git hash-object -w --stdin 51fc03a9bb365fae74fd2bf66517b30bf48020cb
這樣這個目標文件就已經保存到數據庫中了,但是如果你沒有設定一個指向它的指針的話它會被當做垃圾回收。最簡單的方式是設定一個標簽:
$ git tag myfile 51fc03a9bb365fae74fd2bf66517b30bf48020cb
注意這里我們使用了標簽myfile。當我們需要使用這個文件的時候可以這樣做:
$ git cat-file blob myfile
這個對于一些工具文件很有用,開發者可能會用到(密碼,gpg密鑰,等等)但是又不希望每次都檢出到硬盤(尤其是在實際工作中)。
長時間使用 git 的話,不會沒用過‘git log'來查看最近的提交。不過,有一些技巧來更好地應用。比如,你可以使用下面的命令來查看每次提交的具體改動:
$ git log -p
或者你可以僅僅查看有哪些文件改動:
$ git log --stat
有個很不錯的別名你可以試試,會顯示簡短提交名和一個不錯的分支圖并在一行里顯示提交信息(有點像gitk,但是是在命令行下):
$ git config --global alias.lol "log --pretty=oneline --abbrev-commit --graph --decorate" $ git lol * 4d2409a (master) oops, meant that to be in korean * 169b845 hello world
如果你想找特定提交者可以這樣做:
$ git log --author=andy
更新:感謝johannes的評論,我已經去掉了之前這里的一些有混淆的地方。
或者你想在提交信息里找一些相關字段:
$ git log --grep="something in the message"
也有一個更強大的叫做pickaxe的命令用來查找包含了刪除或添加的某個特定內容的提交(比如,該內容第一次出現或被刪除)。這可以告訴你什么時候增加了一行(但這一行里的某個字符后面被改動過就不行了):
$ git log -s "todo: check for admin status"
假如你改動了一個特定的文件,比如lib/foo.rb
$ git log lib/foo.rb
比如說你有一個feature/132分支和
feature/145分支,然后你想看看這兩個分支上不在master分支里的提交(注意符號是不在的意思):
$ git log feature/132 feature/145 ^master
你也可以使用activesupport格式的日期來縮小到某個日期范圍:
$ git log --since=2.months.ago --until=1.day.ago
默認情況下會用or來組合查詢,但你可以輕易地改為and(如果你有超過一條的查詢標準)
$ git log --since=2.months.ago --until=1.day.ago --author=andy -s "something" --all-match
有很多方式可以用來引用一個版本,看你記得哪個:
$ git show 12a86bc38 # 根據版本 $ git show v1.0.1 # 根據標簽 $ git show feature132 # 根據分支名 $ git show 12a86bc38^ # 一次提交的父節點 $ git show 12a86bc38~2 # 一次提交的祖父節點 $ git show feature132@{yesterday} # 時間相關 $ git show feature132@{2.hours.ago} # 時間相關
注意和之前部分有些不同,末尾的的意思是該提交的父節點 - 開始位置的的意思是不在這個分支。
最簡單的方式:
$ git log origin/master..new # [old]..[new] - 所有你還沒有推送的提交
你也可以省略[new],將使用當前的head。
如果你還沒有提交的話可以用下面的命令輕松地取消改動:
$ git reset head lib/foo.rb
通常會使用‘unstage'的別名,因為上面的看上去有些不直觀。
$ git config --global alias.unstage "reset head" $ git unstage lib/foo.rb
如果你已經提交了該文件,你可以做兩件事 - 如果是最后一次提交你還可以改正:
$ git commit --amend
這會取消最后一次提交,把工作分支回退到提交前標記了所有改動的狀態,而且提交信息也都準備好可以修改或直接提交。
如果你已經提交過多次而且希望全部回退,你可以將分支重置到合適的位置。
$ git checkout feature132 $ git reset --hard head~2
如果你實際上希望將分支指向一個完全不同的sha1(也許你要將一個分支的head替換到另一個分支,或者之后的某次提交)你可以使用下面的較長的方式:
$ git checkout foo $ git reset --hard sha
實際上有一個快速的方式(不需要先把你的工作分支切換到foo再前進到sha):
$ git update-ref refs/heads/foo sha
好吧,假如說你已經提交到了master,但卻應該創建一個叫experimental的主題分支更合適。要移動這些改動,你可以在當前位置創建分支,回退head再檢出新分支:
$ git branch experimental # 創建一個指向當前master的位置的指針 $ git reset --hard master~3 # 移動master分支的指針到3個版本之前 $ git checkout experimental
如果你的改動是在分支的分支的分支上會更復雜。那樣你需要做的是將分支基礎切換到其他地方:
$ git branch newtopic startpoint $ git rebase oldtopic --onto newtopic
這是一個我之前看過展示卻沒真正理解過的很贊的功能,現在覺得它就很簡單了。假如說你提交了3次但是你希望更改順序或編輯(或者合并):
$ git rebase -i master~3
然后這會啟動你的編輯器并帶有一些指令。你所要做的就是修改這些指令來選擇/插入/編輯(或者刪除)提交和保存/退出。然后在編輯完后你可以用git rebase --continue命令來讓每一條指令生效。
如果你有修改,將會切換到你提交時所處的狀態,之后你需要使用命令git commit --amend來編輯。
注意:在rebase的時候千萬不要提交 - 只能先添加然后使用參數--continue,--skip或--abort。
如果你提交了一些內容到你的分支(也許你從svn導入了一些舊倉庫),然后你希望把某個文件從歷史記錄中全部刪掉:
$ git filter-branch --tree-filter 'rm -f *.class' head
如果你已經推送到origin了,但之后提交了一些垃圾改動,你也可以在推送前在本地系統里這樣做:
$ git filter-branch --tree-filter 'rm -f *.class' origin/master..head
如果你知道自己之前查看過一個sha-1,但是隨后做了一些重置/回退的操作,你可以使用reflog命令來列出最近查看過的sha-1記錄:
$ git reflog $ git log -g # 和上面一樣,但是使用'log'格式輸出
一個可愛的小技巧 - 別忘了分支名并不限于a-z和0-9。名字中可以用/和.將非常方便用來建立偽命名空間或版本,例如:
$ # 生成版本132的改動歷史 $ git shortlog release/132 ^release/131 $ # 貼上v1.0.1的標簽 $ git tag v1.0.1 release/132
通常找出來誰改動了某個文件里的某行代碼會很有用。實現這個功能的最簡單命令是:
$ git blame file
有時候這些改動來自其他文件(如果你合并了兩個文件,或者你移動了某個函數)所以你可以使用下面的命令:
$ # 顯示內容來自哪個文件 $ git blame -c file
有時候通過點擊各個改動然后回到很早很早以前來跟蹤改動會很不錯。有一個很好的內建gui命令來做這個:
$ git gui blame file
通常git不需要經常維護,它把自己照顧的很好。不過,你可以通過下面的命令查看數據統計:
$ git count-objects -v
如果占用很多空間的話,你可以選擇在你的本地倉庫做垃圾回收。這不會影響推送或其他人,卻會讓一些命令運行更快而且減少空間占用:
$ git gc
經常運行完整性檢查也很有意義:
$ git fsck --full
你也可以在末尾加上--auto參數(如果你在服務器上通過crontab經常/每天都運行這個命令的話),然后它只會在必要的時候才執行fsck動作。
在檢查的時候,看到“dangling”或“unreachable”是正常的,通常這是由回退head或切換基礎的結果。而看到“missing”或“sha1 mismatch”就不對了...找專業人士幫忙吧!
如果你使用-d參數刪除了experimental分支,可以用下面的命令重新建立:
$ git branch experimental sha1_of_hash
如果你最近訪問過的話,你通常可以用git reflog來找到sha1哈希值。
另一種方式是使用git fsck —lost-found。其中一個dangling的提交就是丟失的head(它只是已刪除分支的head,而head被引用為當前的head所以它并不處于dangling狀態)
到此,相信大家對“Git使用技巧實例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。