用這個要當心,它會把那個commit之后的commit全部刪除。一個好的辦法是:先建立一個臨時的分支,然后再git-reset,再git-rebase,最后再刪除臨時的分支。 詳細可以看這里。
$ git add -p // 為你做的每次修改,Git將為你展示變動的代碼,并詢問該變動是否應是下一次提交的一部分。回答“y”或者“n”。也有其他選項,比如延遲決定:鍵入“?”來學習更多。
git add <path>表示 add to index only files created or modified and not those deleted
我通常是通過git add <path>的形式把我們<path>添加到索引庫中,<path>可以是文件也可以是目錄。
git不僅能判斷出<path>中,修改(不包括已刪除)的文件,還能判斷出新添的文件,并把它們的信息添加到索引庫中。
三、git add -u
git add -u 表示 add to index only files modified or deleted and not those created
git add -u [<path>]: 把<path>中所有tracked文件中被修改過或已刪除文件的信息添加到索引庫。它不會處理untracted的文件。
省略<path>表示.,即當前目錄。
四、git add -A
git add -A: [<path>]表示把<path>中所有tracked文件中被修改過或已刪除文件和所有untracted的文件信息添加到索引庫。
省略<path>表示.,即當前目錄。
五、git add -i
我們可以通過git add -i [<path>]命令查看<path>中被所有修改過或已刪除文件但沒有提交的文件,
并通過其revert子命令可以查看<path>中所有untracted的文件,同時進入一個子命令系統。
比如:
git add -i
staged unstaged path
1: +0/-0 nothing branch/t.txt
2: +0/-0 nothing branch/t2.txt
3: unchanged +1/-0 readme.txt
*** Commands ***
1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked
5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp
What now>
這里的t.txt和t2.txt表示已經被執行了git add,待提交。即已經添加到索引庫中。
readme.txt表示已經處于tracked下,它被修改了,但是還沒有被執行了git add。即還沒添加到索引庫中。
5.1、revert子命令
可以通過git add -i的revert子命令(3: [r]evert)把已經添加到索引庫中的文件從索引庫中剔除。
(3: [r]evert)表示通過3或r或revert加回車執行該命令。執行該命令后,git會例出索引庫中的文件列表.
然后通過數字來選擇。輸入"1"表示git會例出索引庫中的文件列表中的第1個文件。
"1-15"表示git會例出索引庫中的文件列表中的第1個文件到第15個文件.回車將執行。
如果我們不輸入任何東西,直接回車,將結束revert子命令,返回git add -i的主命令行。
5.2、update子命令
可以通過update子命令(2: [u]pdate)把已經tracked的文件添加到索引庫中。其操作和revert子命令類似。
5.3、add untracked子命令
通過add untracked子命令(4: [a]dd untracked)可以把還沒被git管理的文件添加到索引庫中。其操作和revert子命令類似。
5.4、diff子命令
可以通過diff子命令(6: [d]iff)可以比較索引庫中文件和原版本的差異。其操作和revert子命令類似。
5.5、status子命令
status子命令(1: [s]tatus)功能上和git add -i相似
5.6、quit子命令
quit子命令(7: [q]uit)用于退出git add -i命令系統
六、幫助
我們可以通過git add -h命令來看git add命令的幫助文檔。
git add -h
usage: git add [options] [--] <filepattern>...
-n, --dry-run dry run
-v, --verbose be verbose
-i, --interactive interactive picking
-p, --patch select hunks interactively
-e, --edit edit current diff and apply
-f, --force allow adding otherwise ignored files
-u, --update update tracked files
-N, --intent-to-add record only the fact that the path will be added later
-A, --all add changes from all tracked and untracked files
--refresh don't add, only refresh the index
--ignore-errors just skip files which cannot be added because of errors
--ignore-missing check if - even missing - files are ignored in dry run
2)分支(branch)操作相關命令
查看本地分支:$
git branch
查看遠程分支:$
git branch -r
創建本地分支:$
git branch [name] ----注意新分支創建后不會自動切換為當前分支
切換分支:$
git checkout [name]
創建新分支并立即切換到新分支:$
git checkout -b [name]
刪除分支:$
git branch -d [name] ---- -d選項只能刪除已經參與了合并的分支,對于未有合并的分支是無法刪除的。如果想強制刪除一個分支,可以使用-D選項
重命名分支:git branch -m <old_name> <new_name> 改名字 (如果有同名會失敗,改用 -M 可以強制覆蓋)
合并分支:$
git merge [name] ----將名稱為[name]的分支與當前分支合并
創建遠程分支(本地分支push到遠程):$git push origin [name]
刪除遠程分支:$
git push origin :heads/[name]
我從master分支創建了一個issue5560分支,做了一些修改后,使用git push origin master提交,但是顯示的結果卻是'Everything up-to-date',發生問題的原因是git push origin master 在沒有track遠程分支的本地分支中默認提交的master分支,因為master分支默認指向了origin
master 分支,這里要使用git push origin issue5560:master 就可以把issue5560推送到遠程的master分支了。
如果想把本地的某個分支test提交到遠程倉庫,并作為遠程倉庫的master分支,或者作為另外一個名叫test的分支,那么可以這么做。
$
git push origin test:master // 提交本地test分支作為遠程的master分支
$ git push origin test:test // 提交本地test分支作為遠程的test分支
如果想刪除遠程的分支呢?類似于上面,如果:左邊的分支為空,那么將刪除:右邊的遠程的分支。
$
git push origin :test // 剛提交到遠程的test將被刪除,但是本地還會保存的,不用擔心
3)版本(tag)操作相關命令
查看版本:$
git tag
創建版本:$
git tag [name]
刪除版本:$
git tag -d [name]
查看遠程版本:$
git tag -r
創建遠程版本(本地版本push到遠程):$git push origin [name]
刪除遠程版本:$
git push origin :refs/tags/[name]
4) 子模塊(submodule)相關操作命令
添加子模塊:$
git submodule add [url] [path]
如:$
git submodule add
git://github.com/soberh/ui-libs.git src/main/webapp/ui-libs
初始化子模塊:$
git submodule init ----只在首次檢出倉庫時運行一次就行
更新子模塊:$
git submodule update ----每次更新或切換分支后都需要運行一下
刪除子模塊:(分4步走哦)
1)$
git rm --cached [path]
2) 編輯“.gitmodules”文件,將子模塊的相關配置節點刪除掉
3) 編輯“.git/config”文件,將子模塊的相關配置節點刪除掉
4) 手動刪除子模塊殘留的目錄
5)忽略一些文件、文件夾不提交
在倉庫根目錄下創建名稱為“.gitignore”的文件,寫入不需要的文件夾名或文件,每個元素占一行即可,如
target
bin
*.db
關于git刪除遠程分支
git branch -r -d origin/branch-name
發現只是刪除的本地對該遠程分支的track,正確的方法應該是這樣:
git push origin :branch-name
冒號前面的空格不能少,原理是把一個空分支push到server上,相當于刪除該分支。
查看遠程倉庫:$
git remote -v
添加遠程倉庫:$
git remote add [name] [url]
刪除遠程倉庫:$
git remote rm [name]
修改遠程倉庫:$
git remote set-url --push[name][newUrl]
commit
提交修改的代碼(只是提交到本地的代碼庫,不會推送到服務器)
$ git commit -am '修改說明'
如果覺得剛提交的“修改說明”寫得不夠好,可輸入以下命令調整
$ git commit --amend
push
將自上次 push 以來的,本地歷次 commit,推送到服務器
結合我們的實際,應該這樣寫:
$ git push origin master:your-id
其中,master 是本地的分支名;your-id 填你在服務器上的 id,服務器的版本庫里會有以你的 id 為名稱的分支。
tag
在git中可以為任意其他對象添加tag,包括commit,tree,blob,甚至包括tag自身。git中都是用sha-1標識git對象,這是一個40個字符長度的字符串,不方便記憶,那么可為git對象添加一個tag便于標識不同對象。
添加tag
# git tag tag-name sha-1
$ git tag v1.0 bdc390c2
這樣便為bdc390c2的對象添加了一個tag,如果不指定sha-1,會為最近的一個commit對象添加tag
查看tag
使用git tag命令便能查看所有tag
$ git tag
當然可以篩選
$ git tag -l 'v1.*'
刪除tag
$ git tag -d <tag-name>
重命名tag
重命名tag有兩種方式:
刪除原tag,重新添加
git tag -f 強制替換已存在的tag后,再刪除原tag
$ git tag -f <new-tag> <old-tag>
$ git tag -d <old-tag>
tag的分類
輕量型標簽 輕量型標簽直接使用 $ git tag <tag-name> <git-object> 即可創建
標注型(annotated)標簽 標注型標簽可記錄更多的信息,使用 $ git tag -a <tag-name> <git-object> -m ‘tag message’即可創意一個標注性標簽
#git cherry-pick 321d76f
這個執行過程git已經執行了一個commit過程。
如果有的時候我們要直接提交怎么辦呢?
#git cherry-pick -n 321d76f
通過添加-n參數,git只會將變化提交到緩存中,沒有執行commit
待你修改完其它后可以一起commit了
#git commit
git branch -v命令將附加顯示最后一次提交相關信息的分支信息
$ git branch -v
# 查看已合并的分支
$ git branch --merge
# 查看未合并的分支
$ git branch --no-merged
ignore
在一個git版本倉庫中,有時候很多文件/目錄并不需要使用git進行版本維護,那么就可以將這些文件/目錄加入.gitignore文件中,
在.gitignore文件中可定義要排除在git版本管理之外的文件/目錄,git默認會讀取項目目錄下的.gitignore文件。
.gitignore使用標準的shell glob模式匹配,shell glob你可以簡單地理解為一種特特殊化的正則表達式,其實要比正則表達式簡單許多,語法如下:
- 允許使用空行,沒有實際語法作用
- # 開頭的行視作注釋
- ! 開頭的模式會覆蓋之前的定義,將匹配的對象重新加入跟蹤列表
- 以/結尾的模式,git會屏蔽掉該目錄及其所有子目錄及文件(只屏蔽目錄)
- 不以/結尾的模式,git屏蔽同名的文件名及目錄(屏蔽目錄和同名文件)
- 以/開頭的模式,git只會屏蔽項目根目錄下的匹配對象
示例:
#.gitignore example
.txt
.gitignore
!readme.txt
exclude/*.txt
該.gitignore中定義的屏蔽規則為:
屏蔽所有的txt文件,但是readme.txt例外;屏蔽所有的.gitignore文件;屏蔽exclude目錄下的所有txt文件(包括readme.txt)。
另外,還可以在配置項中通過core.excludesfile來指定ignore文件。
$ git config core.excludesfile
'_myignore'
git配置
git配置文件根據作用域的不同分為三種:
- 系統配置文件(git安裝目錄/gitconfig)
- 用戶配置文件(用戶主目錄/.gitconfig)
- 項目配置文件(.git/config)
git配置項都通過git config命令寫入,傳入不同參數寫入不同的配置文件
$ git config --system/--global/
- git config –system 寫入系統配置
- git config –global 寫入用戶配置
- git config 寫入項目配置
具體的配置項設置參考幫助文檔,$ git config –help
git中的對象
git對象
git中包含4類對象:
- commit 提交對象
- tree 目錄
- blob 文件
- tag 標記
git提交便產生一個commit對象,commit對象中包含一個tree對象,tree對象中又會包含其他的tree對象或是blob對
象,blob對象是最小的組成單元,即獨立的文件。每個對象都對應一個唯一的SHA-1值,只有當文件或目錄有修改時這個值才會重新計算發生改變。
- $ git log 可以查看所有commit對象
- $ git ls-tree <commit> 查看commit對象中的tree對象
- $ git show <blob> 查看blob的具體內容
git原理
究竟git是如何工作的?打開.git目錄便可一目了然。
- HEAD 指向當前分支
- config 項目配置文件
- description 供GitWeb程序使用
- hooks/ 客戶端與服務端鉤子腳本
- info/ 忽略模式
- index 暫存區域信息
- objects/ 所有數據內容
- refs/ 指向所有commit的指針
HEAD文件中是形如以下代碼的內容:
ref: refs/heads/dev
它指向refs/heads/dev,而dev文件中代碼指向當前分支最近的commit對象
objects目錄中保存有所有git對象,這些對象取sha-1值的前兩個字母為一個目錄,剩下的38個字符作為文件名保存,在上一節“git中
對象”中能查看到的所有git對象都保存在這個目錄中,可以使用git cat-file <sha-1>來獲取對象內容。
$ git cat-file -p 63a46849
不妨多使用cat-file命名多看看各種對象的內容,有助于理解git對象的結構。
refs目錄中保存了git中使用的所有引用或指針,因為不可能任何時候都是用sha-1值來指代對象,git對象也可以有“縮略名”。通常refs目錄會包含以下目錄:
- heads 保存所有分支的HEAD指針
- remotes 保存遠程倉庫信息
- tags 保存所有tag指針
逐一地查看這些文件內容,你就什么都明白了。使用 git update-ref 命令可以直接新建一個引用。
$ git update-ref refs/heads/test-branch c56dce
$ git update-ref refs/tags/test-tag c56dce
執行上述命令,這樣你的git版本庫中就多了一個test-branch分支和一個名為test-tag的tag。
其他的比如git還有些底層的命令,我在文中所列舉的,包括之前基礎篇的都是一些高級命令。可以使用這些底層命名直接對git庫進行一些操作,有關git底層命名的詳細內容,可以到網上去找找。