前言
以前寫個一個git小結,但是實際上並不夠用。於是結合實際工作上碰到的一些情況,參考了一些資料,重新總結了一下。目標是在日常工作中不用再去查閱其他的資料了,如果有什么遺漏或者錯誤的地方,請評論指出!
基本概念
Workspace:工作區
Index / Stage:暫存區
Repository:倉庫區(或本地倉庫)
Remote:遠程倉庫
文件幾種狀態
- untracked:git未跟蹤的文件,新增的文件未 git add 就會處於這種狀態
- not staged:被索引過又被修改了的文件
- staged:通過 git add后即將被提交的文件
創建新倉庫
# 在當前目錄
git init
配置
# 顯示當前的Git配置
git config –list
# 編輯Git配置文件
git config -e [–global]
# 設置提交代碼時的用戶信息
git config [–global] user.name "example"
git config [–global] user.email "example@gmail.com"
# 配置自動換行,提交到git時自動將換行符轉換為lf
git config --global core.autocrlf input
# 配置密鑰
ssh-keygen -t rsa -C example@gmail.com # 生成密鑰
ssh -T git@github.com # 測試是否成功
# 配置別名,--global 表示全局配置
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
檢出倉庫
# 創建一個本地倉庫的克隆版本:
git clone /path/to/repository
# 如果是遠端服務器上的倉庫:
git clone username@host:/path/to/repository
# 克隆到自定義文件夾:
git clone username@host:/path/to/repository my-cloned-repo
新建倉庫常見流程
# 初始化
git init
# 獲取狀態
git status
git add README.md
git commit -m "message"
# 連接遠程倉庫
git remote add origin git@github.com:example/test.git
# 推送內容到遠程倉庫的同時設置默認跟蹤分支
git push -u origin master
gitignore
vim .gitignore
!為模式取反
*.a
!lib.a
添加、刪除
# 添加指定文件到暫存區
git add [file1] [file2] ...
# 添加指定目錄到暫存區,包括子目錄
git add [dir]
# 添加當前目錄的所有文件到暫存區,.或*代表全部添加
git add .
# 添加每個變化前,都會要求確認
# 對於同一個文件的多處變化,可以實現分次提交
git add -p
# 刪除工作區文件,並且將這次刪除放入暫存區
git rm [file1] [file2] ...
# 停止追蹤指定文件,但該文件會保留在工作區
git rm --cached [file]
# 文件重命名,並加入暫存區
git mv [file-original] [file-renamed]
# 通配符批量移動
git mv *.html src/
提交
git commit -m "message"
# 補提交文件,提交時漏掉了某些文件時不應該再單獨提交一次
git commit --amend
# 覆蓋提交日期,不知道有啥實際用途
git commit -m "message" --date "2017-01-01 00:00:00"
branch
# 列出所有本地分支
git branch
# 新建一個分支,但依然停留在當前分支
git branch [branch-name]
# 新建一個分支,並切換到該分支
git checkout -b [branch]
# 切換到指定分支,並更新工作區
git checkout [branch-name]
# 切換到上一個分支
git checkout -
# 建立追蹤關系,在現有分支與指定的遠程分支之間
git branch --set-upstream [branch] [remote-branch]
# 根據一個特定的提交創建新分支,忘記開新的分支就修改並提交了代碼時的處理
git branch test-branch HEAD~1
# 刪除分支
git branch -d [branch-name]
# 重命名分支
git branch -m oldBranch newBranch
# 推送分支到遠程倉庫
git push origin [branch-name]
# 刪除遠程分支
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]
tag
# 列出所有tag
git tag
# 顯示 tag list 和注解
git tag -n
# 在當前commit新建一個輕標簽
git tag [tagname]
# 在指定commit新建一個tag
git tag [tagname] [commit]
# 添加注解標簽
git tag -a [tagname]
# 添加注解標簽並添加注解
git tag -am "message" [tagname]
# 刪除本地tag
git tag -d [tagname]
# 刪除遠程tag
git push origin :refs/tags/[tagName]
# 推送所有tag
git push --tags
# 新建一個分支,指向某個tag
git checkout -b [branch] [tagname]
# 切換到tag
git checkout [tagname]
# tag和分支同名時,顯示指定切換到tag
git checkout tags/[tagname]
遠程倉庫和合並分支
git remote
# 查看遠程倉庫的 URL
git remote -v
# 添加遠程倉庫
git remote add origin git@github.com:example/test.git
# 刪除遠程倉庫
git remote rm origin
# 修改遠程倉庫地址
git remote set-url origin [url]
# 將本地的遠端和遠端進行同步
git fetch origin
# 將本地的遠端合並到本地分支
git merge origin/master
# 拉取遠程倉庫,這相當於上面兩條命令
git pull origin master
# 使用rebase可以使提交的歷史記錄顯得更簡潔
git rebase mater
# 也可以指定分支:
git pull origin remote:local
# 推送:
git push origin local:remote
改寫提交
# 摘出某個提交
git cherry-pick [hash]
# 交互式提交,當涉及提交修改時使用,如 squash、調整 commit 順序等
git rebase -i
git rebase -i HEAD~4
# 將 upstream 后的 commit 節點嫁接到 newbase,如果有 branch ,會先 checkout 到這個 branch,再 rebase
git rebase --onto <newbase> <upstream> <branch>
# 刪除 topicA~3、topicA~4 這兩個 commit
git rebase --onto topicA~5 topicA~3 topicA
# 中途要停止rebase操作
git rebase --abort
# 復原到rebase之前的狀態
git reset --hard ORIG_HEAD
1)squash合並多個提交:
在編輯 commit message 時 hash 值前的p(pick)表示 use commit,s(squash)表示 use commit, but meld into privious commit
所以我們可以在 push 到遠程倉庫之前,把多個 commit 合並成一個。
2)edit使提交成退出狀態
除了p、s,常用的還有e(edit)表示 use commit, but stop for amending。保存退出后,修改過的提交呈現退出狀態。用 git commit --amend 保存修改,然后 git rebase --continue 。這時,有可能其他提交會發生沖突, 請修改沖突部分后再執行 git add 和 git rebase --continue 。這時不需要提交。
3)merge squash:
# 在 merge 特性分支時,把所有的新提交合並成一個
git merge feature-branch --squash
暫存
# 暫時將未提交的變化移除,稍后再移入
git stash
# 查看所有被隱藏的文件列表
git stash list
# 恢復暫存的文件,不從list中刪除
git stash appl
# 從list中刪除
git stash drop
# 恢復暫存的文件,並從list中刪除
git stash pop
撤銷
# 遺棄提交
git reset
# 把當前的 HEAD 重置到前一個,丟棄最新commit
git reset HEAD~1
# 撤銷上一次提交,並且變更還保持在 staging area
git reset HEAD~1 --soft
--soft 只取消提交,將上一次的修改放入 staging area,不修改索引和工作樹
--mixed 默認模式,復原修改過的索引的狀態,將上一次的修改放入 working directory,修改索引,不修改工作樹
--hard 徹底取消最近的提交,直接將上一次的修改拋棄,修改索引和工作樹
三種都會修改HEAD位置
# 拋棄某一次的修改,使用上次提交的版本
git checkout
# 安全地取消過去發布的提交
git revert
git revert HEAD~2
1)git reset與checkout區別:
git reset 使用倉庫中的版本覆蓋 staging area 中的,如果 working directory 該文件沒有其他修改,則 staging area 中的修改將應用到 working directory 中。反之working directory 中的版本將被保留,丟棄 staging area 中的修改。
git checkout 則是使用 staging area 的中的版本覆蓋 working directory。
2)git revert與reset區別:
與 reset 不同的是,revert 只會撤銷當前的 commit,而之后的 commit 操作的修改還會保留,但是 reset 還會將之后的所有 commit 操作的修改全部退回 staging area 或丟棄。
3)撤消合並:
假如還沒推送到遠端,可以reset掉
git reset --hard HEAD~
如果已經推動到遠端,可以用revert
git revert -m 1 HEAD
diff
# 顯示暫存區和工作區的差異
git diff
# 顯示暫存區和上一個commit的差異
git diff --cached [file]
# 顯示工作區與當前分支最新commit之間的差異
git diff HEAD
# 顯示兩次提交之間的差異
git diff [first-branch]...[second-branch]
# 顯示今天你寫了多少行代碼
git diff --shortstat "@{0 day ago}"
log
# 以圖形展示
git log –graph
# 可以顯示包含標簽資料的歷史記錄
git log --decorate
# 單行顯示過去5次提交
git log -5 --pretty --oneline
# 顯示第一個父commit節點,而不顯示merge的commit節點,這樣會有一個更清晰的視圖
git log –first-parent
# 顯示全部分支
git log –all
# 更清晰地顯示
git log --graph --decorate --pretty=oneline --abbrev-commit --all
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
# 優化git倉庫,git repack 將版本庫未打包的松散對象打包
git repack -d
# 條件搜索及正則表達式搜索
git grep
git grep "TODO"
# 二分法查找快速定位到bug位置
git bisect
git bisect HEAD origin
git bisect run make test
git bisect reset
# 可以列出所有的操作記錄,通過reflog找到 commit 的hash,然后 cherry-pick 找回
git reflog
# 獲取命令的幫助信息
git help [命令]
git [命令] --help
# 獲取當前的狀態,git會提示接下來的能做的操作
git status
# Git 組織大型項目的一種方式
git submodule
git內部
Git倉庫下有一個.git目錄,一般包括下面的內容:
- config
- index
- HEAD
- hooks/
- info/
- logs/
- objects/
- refs/
1)config
倉庫的配置文件
2)index
索引,index文件保存暫存區信息
3)HEAD
HEAD文件指示目前被檢出的分支
4)objects
你提交到一個Git代碼倉庫中的所有文件,包括每個提交的說明信息(the commit info)都在目錄 .git/objects/中存儲為實體。
一個實體以一個40字符長度的字符串(該實體內容的SHA1哈希值)來標識。
實體有4類:
- blob - 存儲文件內容
- tree - 存儲目錄結構和文件名
- commit - 存儲提交的說明,組成Git的提交圖譜
- tag - 存儲帶注解的標簽(tag)
5)refs
Git中,一個分支(branch)、遠程分支(remote branch)或一個標簽(tag)(也稱為輕量標簽)僅是指向一個實體的一個指針,這里的實體通常是一個commit實體。
這些引用以文本文件的形式存儲在目錄.git/refs/中。
- refs/heads/xxx 本地分支
- refs/remotes/origin/xxx 遠端分支
- refs/tags/xxx 本地tag
git提交規范
feat: 添加了xx功能
xx功能描述
阮一峰Commit message 和 Change log 編寫指南
三種工作流程
1)Git flow:項目存在兩個長期分支,主分支 master 和開發分支 develop。這個模式是基於"版本發布"的,而補是"持續發布"
2)Github flow:只有一個長期分支,就是 master,"持續發布"
3)Gitlab flow:Gitlab flow 的最大原則叫做"上游優先"(upsteam first),即只存在一個主分支 master,它是所有其他分支的"上游"。只有上游分支采納的代碼變化,才能應用到其他分支。
阮一峰Git 工作流程
命令行
常用命令行
pwd 顯示當前工作目錄 process working directory
cd 切換目錄 change directory
mkdir 創建目錄 make directory
mkdir -p 遞歸創建多個目錄 --parents no error if existing, make parent directories as needed
ls 列出目錄內容 list
ls -a 可以顯示.開頭的文件 all
ls -l 列出文件的詳細信息 long listing format
touch 創建文件
rm/rmdir 刪除文件/目錄 remove
rm -r 刪除目錄 --recursively
mv 文件或目錄的移動或更名 move
cp 將文件拷貝至另一文件 copy
echo 輸出到文件 like echo 1 > test.txt
cat 顯示文件內容和合並多個文件 like cat test.txt,also like cat file1 file2 > file
less 按頁顯示文件
clear 清屏(ctrl + l)
history 查看最近用過的命令
du 統計目錄/文件所占磁盤空間的大小 disk usage
du -sh 以易讀的方式顯示總共大小 --summarize --human-readable
ps 報告程序狀況 process status
head 顯示開頭某個數量的文字區塊 like head -n 3 test.txt
tail 顯示結尾某個數量的文字區塊
ping 網絡管理常用的3個命令
ipconfig
netstat
xxx -h 至少可以通過以下三種中的一種獲取命令的幫助信息
xxx --help
man xxx
快捷鍵
Ctrl + A :光標移動到行首
Ctrl + E :光標移動到行尾
Ctrl + U :刪除光標所在位置之前的所有字符(不含當前位置字符)
Ctrl + K :刪除光標所在位置之后的所有字符(含當前位置字符)
Ctrl + W :刪除光標所在位置之前的一個單詞
Ctrl + R :根據輸入搜索以往使用過的命令
小技巧
Alt + . 使用上一次命令的最后一個參數
!! 上一次命令
↑ 顯示上一次命令
. 當前目錄
.. 上一層目錄
~ 根目錄
- 上一次目錄
| 管道(pipe),前一個命令的輸出為后一個命令的輸入,like cat test.txt | less
多個命令之間可以用;或&&分隔,前者命令錯誤不中斷