Git使用學習總結
git的組成
git有工作區(workspace)、暫存區(index)、本地倉庫(local repository),遠端倉庫(remote repository).遠端倉庫為我們儲存一份程式碼拷貝,如github,而工作區、暫存區和本地倉庫都在本地,這就是為什麼沒有網路我們也照樣使用git提交(commit)程式碼更新,因為提交僅是提交到本地倉庫,待有網路之後可以再推送(push)到遠端倉庫。
正如上圖所示,git fetch是將遠端倉庫的更新獲取到本地倉庫,不影響其他區域。而git pull則是一次性將遠端倉庫的程式碼更新到工作區(同時也會更新本地倉庫)。
通常來說,git fetch和merge與git pull的區別已經很明顯了,但是如果想再瞭解下git是如何操作的,則需要我們瞭解下分支這個git的強大特性,
我們用 (遠端倉庫名)/(分支名) 這樣的形式表示遠端分支。比如我們想看看上次同 origin 倉庫通訊時 master 分支的樣子,就應該檢視 origin/master 分支。如果你和同伴一起修復某個問題,但他們先推送了一個 iss53 分支到遠端倉庫,雖然你可能也有一個本地的 iss53 分支,但指向伺服器上最新更新的卻應該是 origin/iss53 分支。
將下載(fetch)和合並(merge)放到一個命令裡的另外一個弊端是,你的本地工作目錄在未經確認的情況下就會被遠端分支更新。
單獨進行下載和合並是一個好的做法,你可以先看看區別(diff),然後再決定是否和原生代碼合併。而且分開來做,可以清晰的區別開本地分支和遠端分支,方便選擇使用。所以儘量少用git pull,多用git fetch和merge。
常用命令
提交程式碼,要先放入快取區 ,再去提交 到 本地 倉庫,最後提交遠端倉庫,分為三步
1. git add 將改動的程式碼提交到快取區
2.git commit 將程式碼提交到 本地倉庫
3. git push 將程式碼 由本地倉庫 同步到 遠端倉庫
4.還原始碼 git reset
5.git pull 遠端拉程式碼相當於svn的更新
6.新建 分支 git branch
7.切換分支 git checkout
8.解決程式碼衝突 git merge
git clone
克隆一份程式碼到本地倉庫
獲取一個url對應的遠端Git repo, 建立一個local copy. 一般的格式是git clone [url],
clone下來的repo會以url最後一個斜線後面的名稱命名,建立一個資料夾,如果想要指定特定的名稱,可以git clone [url] newname指定.
git checkout
git checkout (branchname)切換到某個分支.
git checkout -b (branchname): 建立並切換到新的分支.
這個命令是將git branch newbranch和git checkout newbranch合在一起的結果.
git checkout -d test //刪除test分支
checkout branch_1.0/master 切換到branch_1.0/master分支
git commit
git commit 提交
git commit -m "This is the message describing the commit" 新增commit資訊
git commit -a
-a是代表add,把所有的change加到git index裡然後再commit git commit -a 會先把所有已經track的檔案的改動add進來,然後提交(有點像svn的一次提交,不用先暫存). 對於沒有track的檔案,還是需要git add一下.
git merge
把一個分支合併進當前的分支.
git merge master //假設當前在test分支上面,把master分支上的修改同步到test分支上
如果出現衝突,需要手動修改,可以用git merge tool.
git merge tool //呼叫merge工具
解決衝突的時候可以用到git diff,解決完之後用git add新增,即表示衝突已經被resolved.
在使用git pull程式碼時,經常會碰到有衝突的情況,提示如下資訊:
error: Your local changes to 'c/environ.c' would be overwritten by merge. Aborting.
Please, commit your changes or stash them before you can merge.
這個意思是說更新下來的內容和本地修改的內容有衝突,先提交你的改變或者先將本地修改暫時儲存起來。
git fetch
把遠端庫的程式碼更新到本地庫,相當於是從遠端獲取最新版本到本地,不會自動merge
可以git fetch [alias]取某一個遠端repo,也可以git fetch --all取到全部repo
git pull
把遠端庫的程式碼更新到工作臺
pull == fetch + merge FETCH_HEAD
git pull會首先執行git fetch,然後執行git merge,把取來的分支的head 合併到當前分支.這個同步操作會產生一個新的commit.
git pull --rebase origin master //強制把遠端庫的程式碼跟新到當前分支上面
git push
push your new branches and data to a remote repository.
把本地庫的修改提交到遠端庫中
git push [alias] [branch]
將會把當前分支merge到alias上的[branch]分支.如果分支已經存在,將會更新,如果不存在,將會新增這個分支.
如果有多個人向同一個remote repo push程式碼, Git會首先在你試圖push的分支上執行git log,檢查它的歷史中是否能看到server上的branch現在的tip,如果本地歷史中不能看到server的tip,說明本地的程式碼不是最新的,Git會拒絕你的push,讓你先fetch,merge,之後再push,這樣就保證了所有人的改動都會被考慮進來.
git reset
撤消更改和提交。
git reset HEAD:
unstage files from index and reset pointer to HEAD
這個命令用來把不小心add進去的檔案從staged狀態取出來,可以單獨針對某一個檔案操作: git reset HEAD - - filename, 這個- - 也可以不加.
這裡的HEAD關鍵字指的是當前分支最末梢最新的一個提交.也就是版本庫中該分支上的最新版本.
git reset --soft
move HEAD to specific commit reference, index and staging are untouched.
git reset --hard
unstage files AND undo any changes in the working directory since last commit.
使用git reset —hard HEAD進行reset,即上次提交之後,所有staged的改動和工作目錄的改動都會消失,還原到上次提交的狀態.
這裡的HEAD可以被寫成任何一次提交的SHA-1.
不帶soft和hard引數的git reset,實際上帶的是預設引數mixed.
git reset --hard HEAD //撤銷本地修改
總結:
git reset --mixed id,是將git的HEAD變了(也就是提交記錄變了),但檔案並沒有改變,(也就是working tree並沒有改變). 取消了commit和add的內容.
git reset --soft id. 實際上,是git reset –mixed id 後,又做了一次git add.即取消了commit的內容.
git reset --hard id.是將git的HEAD變了,檔案也變了.
按改動範圍排序如下:
soft (commit) < mixed (commit + add) < hard (commit + add + local working)
git revert
反轉撤銷提交.只要把出錯的提交(commit)的名字(reference)作為引數傳給命令就可以了.
git revert HEAD: 撤銷最近的一個提交.
git revert會建立一個反向的新提交,可以通過引數-n來告訴Git先不要提交.
git add
把本地的修改加到stage中
在提交之前,Git有一個暫存區(staging area),可以放入新新增的檔案或者加入新的改動. commit時提交的改動是上一次加入到staging area中的改動,而不是我們disk上的改動. git add 會遞迴地添加當前工作目錄中的所有檔案.
git init
初始化本地git環境
在本地新建一個repo,進入一個專案目錄,執行git init,會初始化一個repo,並在當前資料夾下建立一個.git資料夾.
git status
檢視當前分支有哪些修改
查詢repo的狀態.
git status -s: -s表示short, -s的輸出標記會有兩列,第一列是對staging區域而言,第二列是對working目錄而言.
git diff
1.不加引數的git diff:
show diff of unstaged changes.檢視當前沒有add的內容
此命令比較的是工作目錄中當前檔案和暫存區域快照之間的差異,也就是修改之後還沒有暫存起來的變化內容.
若要看已經暫存起來的檔案和上次提交時的快照之間的差異,可以用:
2.git diff --cached.
show diff of staged changes.檢視已經add但是沒有commit的內容
(Git 1.6.1 及更高版本還允許使用 git diff --staged,效果是相同的).
3.git diff HEAD
show diff of all staged or unstated changes.上面兩個內容的合併
也即比較woking directory和上次提交之間所有的改動.
如果想看自從某個版本之後都改動了什麼,可以用:
4.git diff [version tag]
跟log命令一樣,diff也可以加上--stat引數來簡化輸出.
5.git diff [branchA] [branchB]可以用來比較兩個分支.
它實際上會返回一個由A到B的patch,不是我們想要的結果.
一般我們想要的結果是兩個分支分開以後各自的改動都是什麼,是由命令:
git diff [branchA]…[branchB]給出的.
實際上它是:git diff $(git merge-base [branchA] [branchB]) [branchB]的結果.
git log
檢視當前分支上面的日誌資訊
git branch
git branch可以用來列出分支,建立分支和刪除分支.
git branch: 列出本地所有分支,當前分支會被星號標示出.
git branch (branchname): 建立一個新的分支(當你用這種方式建立分支的時候,分支是基於你的上一次提交建立的).
git branch -a 檢視所有的分支
git branch -r 檢視本地所有分支
git branch branch_0.1 master 從主分支master建立branch_0.1分支
git branch -m branch_0.1 branch_1.0 將branch_0.1重新命名為branch_1.0 git
git branch -v可以看見每一個分支的最後一次提交.
git branch -d (branchname): 刪除一個分支.
刪除remote的分支:
git push (remote-name) :(branch-name): delete a remote branch.
這個是因為完整的命令形式是:
git push remote-name local-branch:remote-branch
而這裡local-branch的部分為空,就意味著刪除了remote-branch
git stash
把當前的改動壓入一個棧.
git stash將會把當前目錄和index中的所有改動(但不包括未track的檔案)壓入一個棧,然後留給你一個clean的工作狀態,即處於上一次最新提交處.
git stash list會顯示這個棧的list.
git stash apply:取出stash中的上一個專案([email protected]{0}),並且應用於當前的工作目錄.
也可以指定別的專案,比如git stash apply [email protected]{1}.
如果你在應用stash中專案的同時想要刪除它,可以用git stash pop
刪除stash中的專案:
git stash drop: 刪除上一個,也可指定引數刪除指定的一個專案.
git stash clear: 刪除所有專案.
- git stash //把未完成的修改快取到棧容器中
- git stash list //檢視所有的快取
- git stash pop //恢復本地分支到快取狀態
git remote
list, add and delete remote repository aliases.
因為不需要每次都用完整的url,所以Git為每一個remote repo的url都建立一個別名,然後用git remote來管理這個list.
git remote: 列出remote aliases.
如果你clone一個project,Git會自動將原來的url新增進來,別名就叫做:origin.
git remote -v:可以看見每一個別名對應的實際url.
git remote add [alias] [url]: 新增一個新的remote repo.
git remote rm [alias]: 刪除一個存在的remote alias.
git remote rename [old-alias] [new-alias]: 重新命名.
git remote set-url [alias] [url]:更新url. 可以加上—push和fetch引數,為同一個別名set不同的存取地址.
git rebase
--rebase不會產生合併的提交,它會將本地的所有提交臨時儲存為補丁(patch),放在”.git/rebase”目錄中,然後將當前分支更新到最新的分支尖端,最後把儲存的補丁應用到分支上.
rebase的過程中,也許會出現衝突,Git會停止rebase並讓你解決衝突,在解決完衝突之後,用git add去更新這些內容,然後無需執行commit,只需要:
git rebase --continue就會繼續打餘下的補丁.
git rebase --abort將會終止rebase,當前分支將會回到rebase之前的狀態.
git reset、git revert和git checkout區別和聯絡
git reset
如果你的更改還沒有共享給別人,git reset是撤銷這些更改的簡單方法
reset命令有3種方式:
--soft – 快取區和工作目錄都不會被改變
--mixed – 預設選項。快取區和你指定的提交同步,但工作目錄不受影響
--hard – 快取區和工作目錄都同步到你指定的提交
把這些標記想成定義git reset操作的作用域就容易理解多了。
git checkout
你應該已經非常熟悉提交層面的git checkout。當傳入分支名時,可以切換到那個分支。
git checkout hotfix
上面這個命令做的不過是將HEAD移到一個新的分支,然後更新工作目錄。因為這可能會覆蓋本地的修改,Git強制你提交或者快取工作目錄中的所有更改,不然在checkout的時候這些更改都會丟失。和git reset不一樣的是,git checkout沒有移動這些分支。
git revert
Revert撤銷一個提交的同時會建立一個新的提交。這是一個安全的方法,因為它不會重寫提交歷史。
相比git reset,它不會改變現在的提交歷史。因此,git revert可以用在公共分支上,git reset應該用在私有分支上。
你也可以把git revert當作撤銷已經提交的更改,而git reset HEAD用來撤銷沒有提交的更改。
就像git checkout 一樣,git revert 也有可能會重寫檔案。所以,Git會在你執行revert之前要求你提交或者快取你工作目錄中的更改。
命令 |
作用域 |
常用情景 |
git reset |
提交層面 |
在私有分支上舍棄一些沒有提交的更改 |
git reset |
檔案層面 |
將檔案從快取區中移除 |
git checkou |
提交層面 |
切換分支或檢視舊版本 |
git checkou |
檔案層面 |
捨棄工作目錄中的更改 |
git revert |
提交層面 |
在公共分支上回滾更改 |
git revert |
檔案層面 |
(然而並沒有) |
參考文件:
http://blog.csdn.net/xingqingly/article/details/53172720
https://www.cnblogs.com/my--sunshine/p/7093412.html
https://www.cnblogs.com/allanli/p/git_commands.html
https://www.cnblogs.com/yishaochu/p/5402215.html
https://www.cnblogs.com/houpeiyong/p/5890748.html