轉: SVN和Git的一些用法總結

轉:http://www.codelast.com/?p=5719

 

轉載請註明出處:http://www.codelast.com/html

如下都是比較基礎的操做,高手們請繞道,沒必要浪費時間來看了。java

(A)SVN

(1)查看日誌
提交的時候通常會寫上註釋,若是要查看提交日誌,用如下命令:git

1
svn log -l 4

其中,-l 4表示只查看最近4條日誌(也能夠沒有這樣的參數,就表示查看全部日誌)。可是你一般會很抓狂地發現,最近的幾條日誌中,居然沒有你纔剛剛提交的那一次的日誌!這是怎麼回事?日誌丟了嗎?
其實,是由於你要很用如下命令,更新本地的版本庫,才能看到最近提交的日誌:github

1
svn up

這事若是你沒注意到,那麼可能會浪費你不少時間。問Google也很差找答案,由於這個問題不太好描述,因此很差搜索答案。shell

(2)查看指定的版本修改了哪些文件緩存

1
svn diff --summarize -c 566

其中,566是你指定的版本。

(3)查看某個文件在指定的版本修改了什麼內容
bash

1
svn diff Test.java -c 566 > codelast. diff

其中,Test.java是你要檢查的文件,566是你指定的版本,最後diff被輸出到了codelast.diff文件中。curl

(4)提交svn

1
svn ci -m "Your comment"

其中,Your comment 就是你填寫的註釋,若是你想換行寫,也是能夠的,只要你不寫後面的那個引號,你能夠寫一行就回車一次,最後寫完了,再加上後面的引號,而後再回車,就執行提交動做了。工具

(5)檢出指定版本的版本庫

1
svn co https: //xxx -r 566

其中,https://xxx 是你的版本庫地址,566是你要檢出的版本號。版本庫將被檢出到當前路徑下。
文章來源:http://www.codelast.com/

(6)將指定version的trunk上的代碼拷貝到tags的指定目錄下

1
svn cp https: //svn .codelast.com /trunk/my-project @1333 https: //svn .codelast.com /tags/my-project-r1333

如上命令將trunk下的 my-project 項目的 1333 版本拷貝到了tags下的 my-project-r1333 中。

(7)將branches上的指定版本合併(merge)到trunk上
有時候咱們會在一個分支(branches)上開發,等開發完成的時候,須要把咱們已經提交到branches上的代碼合併到trunk上,假設你本地的工做目錄是在branches上(剛開發完branches上的一個版本,提交了代碼),那麼能夠像下面這樣作:

1
2
svn switch trunk-url-of-your-project
svn merge branch-url-of-your-project

其中,第一條命令是將本地工做目錄切換到trunk上。執行完這條命令後,你本地的工做目錄裏的文件就會變成與trunk裏的文件一致。
第二條命令是將branches上的文件合併到本地。執行完這條命令行,你本地的工做目錄裏的文件就會變成與branches合併的結果。可是請注意,因爲本地的工做目錄已是trunk了(用svn info可查看),因此這一更新,就致使本地有若干文件變成「已修改,但未提交」的狀態。所以,你須要把本地因merge被修改過的文件提交一次,就可使得trunk上的文件變成與branches合併後的版本:

1
svn ci -m "Merge branch to trunk"

文章來源:http://www.codelast.com/
關於svn merge的更詳細說明,可參考此文檔

(8)爲文件添加上可執行權限
假設你有一個腳本文件checkin到代碼庫中了,可是你在commit以前,卻忘了給它添加可執行權限,那麼,當checkout出來這份代碼時,就會獲得一個沒有x權限的腳本,還須要手工再爲它添加上x權限,很是麻煩。因此,要爲該文件添加上x權限:

1
svn propset svn:executable on your-script.sh

而後再 svn ci 提交修改便可(儘管你沒有修改文件內容,只是修改了文件的權限,也是會被標記爲已修改的,須要將此修改提交到代碼庫中)。

(9)checkout單個文件到本地
若是用 svn checkout 單個文件的URL 來檢出一個文件到本地的話,會獲得以下的錯誤提示:

svn: E200007: URL 'https://xxx' refers to a file, not a directory

那麼,如何checkout單個文件呢?答案是用svn export命令便可。

(10)Review Board提交svn的diff文件時,提示「The file 'https://svn.codelast.com/abc.txt' (r1030) could not be found in the repository」錯誤的解決辦法
我遇到的這例錯誤,是由於我在一個項目中新添加了一個文件abc.txt,因而用 svn add abc.txt 添加它,而後 svn diff > today.diff 生成了項目的diff文件,而後把該diff文件提交到Review Board中,想要生成一個新的review,結果就遇到了上面的錯誤提示。
這個錯誤提示乍一看很是搞笑:由於abc.txt是新添加的文件,它固然不會在repository中存在啊!這不是廢話麼?
同時我注意到,當我執行 svn add abc.txt時,命令行提示:

A  (bin)  abc.txt

雖然abc.txt是一個純文本文件,可是svn貌似把它認做了一個binary文件,因而我Google到了這個連接,按照裏面的說法,我在 svn add abc.txt 以後進行了以下操做:

1
svn propset svn:mime- type 'text/plain' abc.txt

而後再生成項目的diff文件,再提交到Review Board上,問題搞定!

(B)Git

(1)提交修改到遠程的git repository的基本流程(前提是你當前目錄已經處於git版本控制之下)
添加當前目錄下全部文件到「即將提交的列表」(固然也能夠指定某些指定的文件,將 . 換成指定的文件便可):

1
git add .

將修改提交到本地:

1
git commit -m "對本次修改的註釋寫在這裏"

提交到遠程的git repository:

1
git push

(2)刪除遠程git repository中的文件
假設要刪除當前目錄下的abc.txt文件(指遠程git repository中的),則:

1
git rm abc.txt

而後提交到本地:

1
git commit -m "delete a file"

而後提交到遠程的repository:

1
git push

文章來源:http://www.codelast.com/
(3)TortoiseGit提交代碼前彈出錯誤提示「username and email must be set...」的解決辦法
Git Commit(提交)的時候,若是Tortoise彈出一個錯誤對話框,提示你必須先設置用戶名和Email,那麼你理所固然地按它的指引點擊「Yes」去設置,奇葩的是,在個人Win7上,TortoiseGit settings→Git頁面中的「Name」和「Email」居然沒法輸入文字(彷彿輸入框是隻讀的同樣)!就算我找到了這篇教程,也無濟於事。
後來我又找到了這篇教程,嘗試用命令行去設置,果真OK了:

1
2
d:\git\bin>git.exe config --global user.name "你的用戶名"
d:\git\bin>git.exe config --global user.email "你的Email"

執行這兩條命令以後,再回到TortoiseGit的settings→Git頁面,就看到Name和Email已經設置好了。

(4)解決每次 git pull 的時候都提示輸入密碼的煩人問題
執行如下命令:

1
git config --global credential.helper "cache --timeout=360000"

其中,timeout值表示緩存密碼多少時間(單位是毫秒仍是秒,我不記得了),把它設置爲一個很是大的值便可,而後你再git pull的時候,按提示輸入密碼以後,下一次就不會再提示輸入密碼了(在timeout時間以內)。
文章來源:http://www.codelast.com/
(5)Windows下的TortoiseGit每次push的時候都提示要輸入密碼的問題
能夠經過修改TortoiseGit的配置來解決:
在設置界面中,「Git」設置子項中,點擊「編輯本地.git/config」,會打開一個文本文件,在最後加上以下內容並保存:

1
2
[credential]
   helper = store

而後再push一次並輸入密碼,TortoiseGit就能夠記住你的密碼啦。

(6)提交代碼到遠程的branch

1
git push -u origin local_branch_name:remove_branch_name

會把本地的 local_branch_name 這個分支提交到遠程的 remote_branch_name 這個分支上,若是遠程沒有這個分支,就會被建立。

(7)刪除遠程的branch
前面用 git push 命令把本地的分支推送到遠程的分支上,命令是很形象的,可是讓人很是費解的就是,要刪除遠程的branch,一樣能夠用這個push命令:

1
git push -u origin :remote_branch_name

表示刪除遠程的 remote_branch_name 這個分支。這個讓人費解的命令,能夠參考Git手冊中的說明來理解。

(8)修改已提交的信息
修改最近一次提交的信息很簡單:

1
git commit --amend

在彈出的編輯界面中修改並保存,再用 git log 看一下,提交的信息是否是已經變了?
但若是要編輯的信息,不是最近一次提交呢?這就須要用到 git rebase 命令了。步驟以下:
用 git log 命令查看到你要修改的那一次提交的版本,而後找到比它更舊的再前一個版本的版本號,例如 f0d1fad,而後:

1
git rebase -i f0d1fad

在彈出的編輯界面中,會看到相似於下面的信息:

1
2
pick a3d4def 修改了一處實現
pick d0ea224 添加了配置文件

假設咱們要修改的提交信息,是第二行那一次提交,則把它前面的「pick」改成「edit」或「e」(就是edit的縮寫),而後保存。
此時,再用 git log 查看一下,最近的一次提交居然變成了你剛修改的那次提交?沒錯,而後咱們就能夠像前面的方法同樣,用 git commit --amend 來修改最近一次的提交信息了。
修改完信息以後,還要把 git log 的信息順序改回來,經過以下命令完成最後一個操做:

1
git rebase -- continue

文章來源:http://www.codelast.com/
(9)配置命令別名
例如,git status這個超級經常使用的命令實在太長了,git st 就很好,能夠像下面這樣配置,使得執行 git st 的時候,等同於 git status:

1
git config --global alias .st status

(10)查看文件差別
修改了一個文件(該文件已經加入版本控制中了),尚未把它 git add 到暫存區,則用如下命令就能夠看到修改了什麼:

1
git diff

若是已經把該文件 git add 到了暫存區,再使用 git diff 命令,將沒有任何輸出。此時,應使用如下兩個命令中的任何一個,能夠查看到修改的內容(其實顯示的就是暫存區裏和上一次提早之間的差別):

1
2
git diff --cached
git diff --staged

(11)將一個文件移除出版本控制,可是並不將它從本地磁盤上刪除
git rm your_file 會將文件 your_file 從本地以及版本控制系統中都刪除掉,可是若是我只想把此文件移除出版本控制系統,但並不想把它從本地磁盤上刪除,則能夠這樣作:

1
git rm --cached your_file

(12)用meld及git-diffall來比較兩個版本之間的文件差別
Meld是一款超級強大的圖形化diff比較工具,比你用diff命令查看兩個文件的差別要直觀得多,那麼,如何讓git與Meld整合到一塊兒呢?須要用到一個叫git-diffall的第三方腳本,下面會說到。

安裝meld:

 

1
sudo apt-get install meld
解壓,把其中的腳本拷貝到 /usr/bin 目錄下:
1
sudo cp git-diffall /usr/bin
而後配置git的difftool:
1
2
git config --global diff .tool meld
git config --global alias .diffall git-diffall
如今回到一個項目的目錄下,比較一個文件的當前工做版本與master中的版本的差別:
1
git difftool ..master src /test/MyClass .java
最後一個參數也能夠是一個目錄,這樣就會比較一個目錄的差別(太賞心悅目了)。
每次執行此命令的時候,都會讓用戶確認是否加載meld,直接回車便可。
而後,在彈出的Meld界面中,盡情體驗強大的Meld帶給咱們的美妙感受吧!

文章來源:http://www.codelast.com/
(13)撤消修改的幾種狀況
在SVN中,修改了一個文件以後,尚未提交的話,咱們能夠用 svn revert your_file 命令,來撤消咱們對文件 your_file 所作的修改,使之恢復到沒修改以前的狀態。可是在Git中,等價的命令是什麼呢?在不多使用git以前,我也有這個問題,因而我到Google上一搜「svn revert git」,搜出來不少人都在問這個問題,其實要理解好這個問題,須要先理解好git有工做區、暫存區(stage)的概念,而SVN沒有暫存區的概念,因此,當你剛從SVN轉到Git時,會很困惑爲何Git撤消修改那麼麻煩。其實這纔是Git強大之處啊。
①修改了一個文件,尚未將它添加到暫存區,此時,要撤消所作的修改:

1
git checkout -- your_file 

②修改了一個文件,而且已經經過 git add your_file 把它添加到了暫存區,則想把這個文件復原,先要把它從暫存區「弄出來」:

1
git reset HEAD your_file

如今,你再用 git status 命令查看的話,會發現它已經被從暫存區「拿出來」了,變成了沒有 git add 的狀態,可是,它仍然是咱們修改過內容的,要繼續撤消咱們修改的內容的話,繼續像上面同樣,用 git checkout -- your_file 命令,便可將你所作的修改徹底復原了。

(14)查看每一個版本修改的文件
git log 能夠查看提交日誌,再加一個參數就能夠看到每一個版本修改的文件都有哪些了:

1
git log --name-status

文章來源:http://www.codelast.com/
(15)一次git add全部modified的文件到暫存區
若是你修改了100個文件,那麼一個個地 git add 它們到暫存區無異於自虐,此時你須要的是批量add:

1
git add -i

而後就進入了交互式界面:

1
2
1: status   2: update   3: revert   4: add untracked
5: patch    6: diff   7: quit   8: help

選擇2,回車,會列出全部將要被 add 的文件,輸入星號(*)並回車(表示選擇全部文件),而後又會回到上面的菜單界面,選擇7回車退出,這時再用 git status 看一下,是否是全部修改過的文件都添加到了暫存區裏了?

(16)利用Bitbucket在兩地同步私有代碼
與Github不一樣,Bitbucket能夠建立private的代碼倉庫,這對我的而言很是有用。例如,你在臺式機A上寫的代碼,當你出差到其餘城市後,還想在你帶的筆記本(記爲B)上繼續寫,那麼這時候怎麼辦?有一個傻傻的辦法就是連上電腦A(若是能夠的話),而後把整個項目打一個tar包,傳到B上,但若是你的整個項目目錄很是大,壓縮以後仍有幾百M,那麼你可能須要耗費大量時間來傳輸。更爲可取的一個辦法就是利用相似於Bitbucket這樣的服務,來同步代碼,使得只須要更新少許數據就OK了。
下面是步驟:

1
git remote add origin https: //codelast @bitbucket.org /codelast/my-repo .git
在A處,將代碼push到Bitbucket上:
1
git push -u origin my-branch:my-branch
這表示將my-branch這個branch的代碼push到Bitbucket上的同名branch下(若是Bitbucket上沒有這個branch,將被建立)。
在B處:
1
2
git checkout master
git fetch
這會將Bitbucket上的最新修改下載到本地——可是並無merge到本地的任何一個branch上。
在B處,建立同名的branch並切換過去:
1
2
git checkout -b my-branch
git merge origin /my-branch
這會將剛纔從遠程倉庫(origin/my-branch)下載回來的最新的代碼,merge到當前的branch上,所以,本地的my-branch倉庫立刻就會變成最新的代碼了。
看到的提示信息形如:
1
2
3
4
Updating e8b4538..6bc7bcd
Fast-forward
  src/java/com/codelast/Demo.java        |  11 +++++++
  ......
至此,B的my-branch這個branch上的代碼就與A的代碼同步了。
文章來源: http://www.codelast.com/
上面從git fetch開始的步驟,也能夠換一種方法實現:
1
2
git checkout -b my-branch
git pull
這裏的git pull在效果上至關於git fetch + git merge的組合。可是第一次運行這個命令的時候,會看到相似於下面的提示:
1
2
3
4
5
6
7
8
9
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details
 
     git pull <remote> <branch>
 
If you wish to set tracking information for this branch you can do so with:
 
     git branch --set-upstream-to=origin/<branch> my-branch
這說明本地的branch沒有和remote的branch關聯上,因此git pull不知道「從哪裏pull」。根據最後一次的提示,須要執行如下命令:
1
git branch -- set -upstream-to=origin /my-branch my-branch
會獲得提示:
1
Branch my-branch set up to track remote branch my-branch from origin.
則如今再執行git pull命令,就能夠把remote的branch下載下來而且merge到本地的branch中了。

文章來源:http://www.codelast.com/
(17)查看當前版本比上一個版本修改了什麼內容

1
git diff HEAD^ HEAD

其中,HEAD表明當前版本,後面帶一個 ^ 號表示其以前一個版本。

(18)Git子命令的自動完成/自動補全
在Ubuntu下用 apt-get install git 安裝好Git後,Git的子命令就已經能自動完成了,例如你輸入 git ad,而後按 TAB,會發現它被補全成了 git add,可是在Arch Linux ARM下,這個功能卻沒有,咱們能夠參考這個連接中的教程本身作。
基本思想就是獲取github上的一個 git-completion.bash 腳本,而後把它添加到開機自動執行的腳本中:

1
2
curl https: //raw .githubusercontent.com /git/git/master/contrib/completion/git-completion . bash -o ~/.git-completion.sh
chmod +x ~/.git-completion.sh

而後編輯 /etc/profile 文件,在最後添加以下代碼:

1
2
3
if [ -f ~/.git-completion.sh ]; then
     . ~/.git-completion.sh
fi

重啓系統,搞定,Git已經能夠自動完成子命令了。

(19)檢出指定版本的某個文件

1
git checkout <commit_id> <your_file_path>

例如:

1
git checkout 3493c0ec MyClass.java

(20)To be added...
文章來源:http://www.codelast.com/

(C)git-svn

git-svn是Subversion 雙向橋接工具,用於:Git做爲本地的版本控制工具,SVN做爲遠程的倉庫。
有人可能會有疑問:爲何會出現git-svn這個東西?這是因爲Git實在是比SVN要好用太多太多了,因此有時候,儘管咱們不得不使用遠程的SVN倉庫來和你們同步工做(例如,你公司的代碼庫就是SVN的),可是在本地,咱們仍然可使用Git來作版本控制,這就是git-svn工具的做用。

(1)初始化
用SVN做爲版本控制工具時,咱們檢出一個項目,用的是 svn co http://xxx 這樣的方法,可是用git-svn時,咱們應該這樣作:

1
git svn clone http: //xxx

(2)只查看SVN log
git log 命令會列出你的全部git commit日誌,可是若是隻想看SVN的commit日誌,就須要用:

1
git svn log

可是這樣輸出的信息可能太雜亂了,能夠用以下命令,讓一次提交只顯示一行信息:

1
git svn log --oneline

(3)本地已經commit了幾個版本到git版本庫中,可是隻想提交一個較舊的版本到遠端SVN庫中
假設遠端repo使用的是SVN,本地使用git-svn來管理,在開發過程當中,本地的my-branch中已經提交了A→B→C三個版本,版本A是時間最先的一次提交,版本C是時間最新的一次提交,如今想把版本A上的修改提交到遠端SVN repo中,而版本B和版本C暫時不想提交到SVN repo中。可是咱們知道,git-svn dcommit命令會將當前版本的修改所有提交到SVN repo中去,所以,不能在當前版本C中進行此操做,一個可用的方法以下:
切換到工做的branch:

1
git checkout my-branch

在當前branch基礎上,再建立一個新的branch,並切換過去:

1
git checkout -b my-branch-to-commit

這時,my-branch-to-commit這個分支上也有版本A、B、C了。假設版本A的commit id爲d939ac4,則將此分支的HEAD指向版本A:

1
git reset --hard d939ac4

這時,my-branch-to-commit這個分支上,最新的版本就是版本A了,因而,咱們能夠把它提交到遠端的SVN repo中去了:

1
git svn dcommit

因而咱們完成了「提交版本A到SVN」的任務,可是,咱們還要在版本B、版本C的基礎上繼續開發,因此,下面,咱們要把這兩個版本「找回來」。
先切換回master分支:

1
git checkout master

更新到最新的SVN版本:

1
git svn rebase

這時,master分支上已是版本A的代碼了。
再建立一個新的工做分支my-branch-to-continue:

1
git checkout -b my-branch-to- continue

這時,git cherry-pick命令就大顯神威了,它能夠挑選指定版本的修改,並應用到當前分支上,因此,咱們須要作的是,把my-branch這個分支中的版本B、版本C的修改cherry-pick過來,應用到my-branch-to-continue分支上。
假設版本B的commit id爲c37d531,版本C的commit id爲822dbbd,則:

1
2
git cherry-pick c37d531
git cherry-pick 822dbbd

這會生成兩個新的commit。
如今,在my-branch-to-continue這個分支上,咱們的狀態就是:版本A已是提交到了SVN,版本B、版本C已經提交到了本地git repo中。
如今能夠把my-branch這個分支刪掉了,由於它已經沒用了:

1
git branch -D my-branch

大功告成。

相關文章
相關標籤/搜索