git 删除tag_Git 基本应用
本文用來整理記錄日常工作中經常使用到的 Git 命令,方便日常查詢使用。關于 Git 誕生的歷史及相關內部原理本文暫不涉及。
基礎概念
首先通過下圖(圖片來源于網絡)了解日常工作中 Git 的操作流程
基于上圖介紹下 Git 的相關工作空間
常用操作
基礎配置
- 配置提交人標識和郵箱
$ git config --global user.name 'your_name'
$ git config --global user.email 'your_email@domain.com'
# 取消配置
git config --unset --global user.name
git config --unset --global user.email
config 的三個作用域
$ git config --local #local 只對某個倉庫有效
$ git config --global #global 對當前用戶所有倉庫有效
$ git config --system # system 對系統所有登錄的用戶有效
# local的優先級最高,即local的配置信息可以覆蓋global配置的信息
顯示 config 的配置
$ git config --list --local
$ git config --list --global
$ git config --list --system
刪除 config 中的配置項
git config --global --remove-section name # name為要刪除的配置項名稱
執行git config后相關的配置將保存到純文本文件中,對應生成文件位置如下:
所以 git config 命令其實只是一個提供便捷命令行的接口。
- 其他常用配置
$ git config --global alias.lg "log -10 --pretty=oneline --graph" # 別名設置
$ git config --system core.editor <editor>
$ git config --global --edit
倉庫初始化
- 本地有個項目代碼寫了一段時間了,但還沒有用 git 管理起來,現在想用 git 做版本管理
$ cd existing_floder
$ git init
$ git add .
$ git commit -m"Initial commit"
- 本地生成了一個 git 的倉庫,開發了一段時間,想把這個git倉庫提交到公司git服務器新建的項目中
$ cd existiong_repo
$ git remote add origin git@your_git_server:your_group/your_project.git
$ git push -u origin master
#如想推送所有分支和tag則按如下執行
$ git push -u origin --all
$ git push -u origin --tags
# 官方解釋:push 后增加 -u 的目的是對于每個最新的或成功 push 的分支,添加 upstream(跟蹤)引用。該引用由后續供無參數git-pull 和其他命令使用。
# 白話解釋:也就是加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在以后的推送或者拉取時就可以簡化命令。
- 倉庫已經在公司git服務器上創建,檢出倉庫到本地
$ git clone git@your_git_server:your_group/your_project.git
#克隆指定分支
$ git clone -b master git@your_git_server:your_group/your_project.git
Git支持多種協議,默認的git://使用ssh,但也可以使用https等其他協議。
使用https除了速度慢以外,還有個最大的麻煩是每次推送都必須輸入口令,但是在某些只開放http端口的公司內部就無法使用ssh協議而只能用https。
同時作為服務端存儲的 Git 倉庫都為裸倉庫,裸倉庫沒有工作區,因為服務器上的 Git 倉庫純粹是為了共享,所以不讓用戶直接登錄到服務器上去改工作區,并且服務器上的Git倉庫通常都以.git結尾
#在Github、GitLab等Git托管服務上創建的倉庫均為裸倉庫。如想手動創建可參考如下命令
#以下命令都可以生成裸倉庫
$ git clone --bare ...
$ git init --bare
本地倉庫變更
Git的版本庫里存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區,還有Git為我們自動創建的第一個分支master,以及指向master的一個指針叫HEAD。
- git status
查看工作目錄和暫存區的狀態
- git addgit add . 將工作區新增、修改和刪除(Git 2.x 才支持)的文件添加到暫存區,即對 Git 已跟蹤和未跟蹤的文件都進行處理。只對當前路徑及其子路徑文件有效git add -A 等同于 git add --all 將文件的修改、新增、刪除添加到暫存區。對整個倉庫下的文件都有效git add -u 將工作區內被修改和刪除的文件添加到暫存區(不包括未被 Git 跟蹤的新增文件)。好處是可以避免把工作區內還沒準備好的文件加到暫存區git add file1 file2 ... 一次可添加一個或多個文件及文件夾到暫存區git add -p file 交互式的選擇工作區及暫存區文件的相關補丁,并新增到暫存區
- git commitgit commit -m'xxx'提交暫存區的變更內容到版本歷史,生成 commit 節點git commit -am'xxx' 會將已經被Git跟蹤的變更內容,提交到暫存區并提交內容,生成 commit 節點。==不推薦此方式==,此方式將工作的文件直接添加到版本歷史中去了,跳過了人工進行暫存的處理。
忽略指定文件
可以配置 Git 忽略指定的文件或者是文件夾。這些配置都放在 .gitignore文件中。這個文件可以存在于不同的文件夾中,可以包含不同的文件匹配模式。
具體配置在此不做具體描述,下面介紹下使用中可能遇見的問題:
- 某文件已被提交到遠程倉庫后,想對其忽略
- 空文件夾無法被追蹤
因為 Git 是針對文件的變更做管理追蹤的故需要在文件夾下添加文件 .gitkeep ,這是一個約定俗成的文件名。
遞歸創建.gitkeep文件
find . -type d -empty -not -path"./.git/*" -exec touch {}/.gitkeep ;
文件重命名
- 常規方式mv readme readme.md
執行 git add readme.md 和 git rm readme
- 簡便方式git mv readme readme.md ,前提此文件已被 Git 所管理跟蹤
直接執行commit即可,無效執行add。
刪除文件
- 常規方式
$ rm <file> # 刪除工作區文件
$ git rm <file> # 加入暫存區
- 簡便方式
$ git rm <file> # 刪除文件并加入暫存區
差異對比
- 比較暫存區與 HEAD 所指向分支所含文件的差異
$ git diff --cached
$ git diff --staged
# 以上命令皆可
- 比較工作區與暫存區所含文件的差異
$ git diff #默認比較的是工作區與暫存區所有文件的差異
$ git diff -- file1 file2 #可以指定一個或多個具體文件名,在工作區與暫存區進行比較
- 比較工作區與 HEAD 所指向分支所含文件的差異
$ git diff HEAD
$ git diff HEAD -- file1 file2
# -- 為了讓git命令讀取命令參數的時候消除歧義用的,雙連字符后面的是路徑或文件
- 比較 COMMIT 間的文件差異
$ git diff 5d39588 56f6198
$ git diff HEAD HEAD~1
$ git diff HEAD HEAD^1
# 上述兩命令等價 HEAD 指向5d39588 commit,HEAD~1 指向 5d39588 的父 commit 56f6198
$ git diff HEAD HEAD^1 -- readme.md #后面的commit為比較基準
通過下圖來看下 diff 操作時 ~ 與 ^ 差異
G H I J
/ /
D E F
| /
| / |
|/ |
B C
/
/
A
A = = A^0
B = A^ = A^1 = A~1
C = A^2
D = A^^ = A^1^1 = A~2
E = B^2 = A^^2
F = B^3 = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2 = B^^2 = A^^^2 = A~2^2
I = F^ = B^3^ = A^^3^
J = F^2 = B^3^2 = A^^3^2
$ git log
* 29392c8 (HEAD -> master, tag: A) A
|
| * a1ef6fd (tag: C) C
| |
|
*-. 8ae20e9 (tag: B) B
|
| | |/
| | * 03160db (tag: F) F
| | |
| | | * 9df28cb (tag: J) J
| | * 2afd329 (tag: I) I
| * a77cb1f (tag: E) E
* cd75703 (tag: D) D
|
| * 3043d25 (tag: H) H
* 4ab0473 (tag: G) G
可以看出 ~ 與 ^ 都是指父節點,n個~ 與n個^ 或者^1與~1 都是等價的。它們都是以線性的形式來找其父節點。
區別在于 ~ 與 ^后跟數字的情形,~n 仍是以線性來找父節點,但^n會按其所有的父節點來計算查找
查看 commit 歷史
# 查看當前所在分支記錄 $ git log # 高版本命令行會進入交互界面,如不進入交互界面直接輸出日志按以下命令執行 $ git --no-page log #--no-page 禁用page分頁,git 很多命令默認都是page分頁的 # 日期格式 $ git log --date=format:%Y-%m-%d %H:%M:%S $ git log --date=iso $ git log --date=short # 以單行簡潔方式展示歷史 $ git log --oneline # 查看最近5條記錄 $ git log -n5 --oneline $ git log -n5 --oneline #"-<number>"同"-n<number>"。 # 查看具體分支記錄 $ git log temp # 查看所有分支log記錄 $ git log --all # 以圖形化展示記錄 $ git log --all --graph # 美化記錄 $ git log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit" # 查看某文件中某人何時修改了何處 $ git blame <file>重寫 commit 歷史
# 將本次暫存區的變更與上次commit的變更合并生成新的commit,并替換 message # 前提當前commit為最新的 $ git commit --amend # 此操作只可修改未被 push 到遠程倉庫的 commit 消息 # 修改舊commit的message信息、合并commit消息 $ git rebase -i <base> # 變基只用于本地管理未被push到遠程倉庫中代碼,如果push到遠程后又使用了rebase,則會影響團隊其他成員。撤銷變更
- checkout
checkout命令用于從歷史提交(或者暫存區域)中拷貝文件到工作目錄,也可用于切換分支。
當給定某個文件名(或者打開-p選項,或者文件名和-p選項同時打開)時,git會從指定的提交中拷貝文件到暫存區域和工作目錄。比如,git checkout HEAD~ foo.c會將提交節點HEAD~(即當前提交節點的父節點)中的foo.c復制到工作目錄并且加到暫存區域中。(如果命令中沒有指定提交節點,則會從暫存區域中拷貝內容。)注意當前分支不會發生變化。
# 工作區回退到暫存區的版本
# 指定文件
$ git checkout -- file
# 所有內容
$ git checkout *
# 指定提交中文件回退到暫存區和工作目錄
$ git checkout HEAD index.html
- reset(復位)
reset命令把當前分支指向另一個位置,并且有選擇的變動工作目錄和索引。也用來在從歷史倉庫中復制文件到索引,而不動工作目錄(即 git reset 命令既可以回退版本,也可以把暫存區的修改回退到工作區)。它應該只被用于 本地 修改,切記不應該在和其他開發者共享的分支執行 reset。
# 移動分支位置,并清空暫存區跟蹤文件
$ git reset <commit> # 默認為--mixed
# 移動分支位置,并清空工作區和暫存區跟蹤文件
$ git reset --hard <commit>
# 只移動分支位置
$ git reset --soft <commit>
# 分支位置不變,清空暫存區跟蹤文件
$ git reset # 分支默認為HEAD
# 分支位置不變,清空暫存區指定的跟蹤文件
$ git reset <file> # 分支默認為HEAD,把暫存區的修改撤銷掉(unstage),重新放回工作區
$ git reset # 撤銷所有暫存區域文件。
- revert(撤銷)
在遠程分支中可以通過撤銷某個提交引入的更改,revert操作方式是在最后加上一個撤銷了此更改的新提交,而不是從項目歷史中移除這個提交。這避免了Git丟失項目歷史,而且對于版本歷史和協作的可靠性來說是很重要的。git revert 用于在公共的分支上撤銷提交,git reset用于復位本地的歷史變更
因為兩個命令的目的不同,它們的實現也不一樣:reset完全地移除了一堆更改,revert保留了原來的更改,用一個新的提交來實現撤銷。
# 創建一個新的commit,此commit將要revert的commit記錄中的變更都撤銷
$ git revert <commit>
- cleangit clean命令將未被 Git 跟蹤的文件從工作目錄中移除。與rm作用一樣,只是提供了簡便方式。git clean 命令經常和 git reset --hard 一起使用,新增的文件沒有被加入暫存區,它們不會被git reset --hard影響,必須使用git clean刪除它們。==此操作請謹慎使用==。
# 告訴你哪些文件在命令執行后會被移除,而不是真的刪除它。
$ git clean -n
# 移除當前目錄下未被跟蹤的文件
$ git clean -f
# 移除未跟蹤的文件,但限制在某個路徑下。
$ git clean -f <path>
# 移除未跟蹤的文件,以及目錄。
$ git clean -df
- refloggit relog 在 HEAD 更新時(如切換分支、拉取新更改、重寫歷史或只是添加新的提交),引用日志都會添加一個新條目(操作記錄包括對應的commitId)。它的作用在于在執行某些撤銷變更、rebase等命令后某些commit記錄無法在log中查詢到,但又需要對其恢復則可使用此功能來找尋其對應的commit記錄。
分支與Tag
# 查詢本地已有分支 $ git branch # 查詢本地已有分支并輸出詳細信息 $ git branch -v # 查詢已存在的本地分支及遠程分支并輸出詳細信息 $ git branch -av # 創建分支 $ git branch <new-branch> # 默認以HEAD當前最終指向的Commit為基準 $ git branch <new-branch> <commitId/branch> # 已指定的Commit或分支為基準 # 刪除分支 $ git branch -d <branch> # 如果執行報錯(報此分支還沒有被完全merge,也就是還沒合并到上游分支或HEAD上,刪除會存在代碼丟失風險),如已確認刪除對當前工程無影響,則可改用 -D 強制刪除 # 切換分支 $ git checkout <branch> $ git switch <branch> # 新版本Git提供,此命令從字面上更容易理解,不易混淆 # 創建并切換分支 $ git checkout -b <new-branch> <commitId/branch> # 如不指定commitId或branch默認以HEAD當前最終指向的Commit為基準 $ git switch -c <new-branch> <commitId/branch> # 新版本Git提供,此命令從字面上更容易理解,不易混淆 # 以遠程分支為基準創建分支 $ git checkout --track origin/hack # 使用 Tag 標識當前commit $ git tag <tag-name>merge 與 rebase
如果期望提交歷史以線性結構展示則使用rebase,merge操作對合并要求更寬松但展示的歷史結構會復雜
$ git merge <branch> $ git rebase <branch> # 終止變基操作 $ git rebase --abort # 繼續變基操作 $ git rebase --continue # 使用配置的merge工具來解決沖突 $ git mergetool # 解決沖突后追蹤已解決的文件 $ git add <resolved-file> # 解決沖突后刪除已解決的文件 $ git rm <resolved-file>臨時緊急任務處理
工作只進行到一半,還沒法提交,預計完成還需1天時間。但是,必須在兩個小時內修復該bug,怎么辦?
幸好Git還提供了一個stash功能,可以把當前工作現場“儲藏”起來,等以后恢復現場后繼續工作:
# stash 是堆棧結構,執行pop后會將最上面也就是最新存儲的彈出來 ? Git_Learning git:(rebase) ? git stash Alias tip: g stash Saved working directory and index state WIP on rebase: 3fb18e1 add test ? Git_Learning git:(rebase) git stash list Alias tip: gstl ? Git_Learning git:(rebase) git --no-pager stash list Alias tip: g --no-pager stash list stash@{0}: WIP on rebase: 3fb18e1 add test ? Git_Learning git:(rebase) # git stash apply 只應用堆棧上最新的代碼但不將其從stash中刪除,即apply可多次執行 #pop即應用代碼又刪除 ? Git_Learning git:(rebase) git stash pop Alias tip: gstp On branch rebase Changes not staged for commit:(use "git add <file>..." to update what will be committed)(use "git restore <file>..." to discard changes in working directory)modified: index.htmlno changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash@{0} (fdee00b4363f4a3d718ee0aa0825a52bff036d1d)git stash list 命令顯示的最左一列顯示的是 stash 的序號,如stash@{2} 和 stash@{1},序號中數字大的代表的是較早的stash。我們pop的時候可以加具體的序號,不加序號的(缺省情況下)為 stash@{0}。用法:git stash pop stash@{2} git stash pop = git stash pop stash@{0}
注意 git stash不會保存工作區新增的文件(未被跟蹤的),需執行git stash push -u -m '指定stash名字'
cherry-pick
在master分支上修復了bug后,因為dev分支是從master分支分出來的,所以,這個bug在當前dev分支上也存在。
那怎么在dev分支上修復同樣的bug?重復操作一次,提交不就行了?
為了方便操作,Git專門提供了一個cherry-pick命令,讓我們能復制一個特定的提交到當前分支:
$ git cherry-pick 3fb18e1 [master b257a0d] fix bug1 file changed, 1 insertion(+), 1 deletion(-)Git自動給dev分支做了一次提交,注意這次提交的commit是b257a0d,它并不同于master的3fb18e1,因為這兩個commit只是改動相同,但確實是兩個不同的commit。用git cherry-pick,我們就不需要在dev分支上手動再把修bug的過程重復一遍。
遠程倉庫
# 顯示本地與遠程倉庫的連接 $ git remote # 顯示本地與遠程倉庫連接詳細信息 $ git remote -v # 創建一個新的遠程倉庫連接。執行clone操作時,會自頂創建與遠程倉庫的連接,名稱為origin $ git remote add <name> <url> # 移除名為 <name> 的遠程倉庫的連接。 $ git remote rm <name> # 重命名遠程連接 $ git remote rename <old-name> <new-name> # 將本地分支與遠程分支關聯 $ git branch --set-upstream <upstream> [<branchname>] # 將本地分支與遠程分支取消關聯 $ git branch --unset-upstream [<branchname>] # 拉取遠程倉庫指定分支的到本地,但不與本地當前分支合并。如不指定<branch>則拉取遠程倉庫的所有分支引用 $ git fetch <remote> <branch> # 拉取當前分支對應的遠程副本中的更改,并立即并入本地副本(前提本地分支與遠程分支已關聯upstream) $ git pull <remote> # 等價于 $ git fetch && git merge # 底層使用 rebase 合并遠程分支和本地分支,而不是使用 merge。--rebase 標記可以用來保證線性的項目歷史,防止合并提交(merge commits)的產生。很多項目組傾向于使用 rebase 而不是 merge,因為提交歷史更簡潔明了 $ git pull --rebase <remote> # 本地倉庫master分支推動到遠程倉庫的master分支 $ git push origin master:master # :前面的是本地分支名稱,:后面的是遠端分支的名稱。 # 本地倉庫master分支推送到遠端關聯分支 $ git push origin master # 后面沒帶遠端的master,那是因為git已經為本地的master分支和遠端的分支建立了所謂的 upstream 的關聯,它知道本地master對應遠端的master分支 # 將當前本地倉庫所在分支提交到遠程相同分支下 $ git push # origin 是缺省的 remote url; # 強制推送,集成分支不推薦使用 $ git push -f # 將本地所有分支推送到遠程倉庫 $ git push -all # 推送分支時,標簽不會被自動推送上去。`--tags` 將你所有的本地標簽推送到遠程倉庫中去。 $ git push --tagsGit集成使用禁忌
前面提到過在本地分支執行 git checkout/git reset時要謹慎,下面的命令在多人協作的集成環境下則完全禁止使用
- 禁止向集成分支執行 git push -f
- 禁止向集成分支執行變更 commit 歷史的操作,如reset、rebase
參考
Git官方教程
廖雪峰Git教程
圖解Git
文章持續更新,可以微信搜一搜「 Java夜校 」第一時間閱讀,若有錯誤或者不當之處,還請大家留言指正,一起學習交流!總結
以上是生活随笔為你收集整理的git 删除tag_Git 基本应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: deepin root密码_Deepin
- 下一篇: 逆向查找_CTFer成长之路--一道数独