Git-cli 文章教程知识点
git 追踪的只是修改,不是文件,只有将修改 add 到 stage 之后的内容才会被管理。
Git 相关图片
- git-cheatsheet
- git-command-graphical-1
- git-command-graphical-2
- git-command-graphical-3
- git-diff
- git-workflow
git-cli 相关书籍资料
- git-recipes : 作者自己整理个的 git 相关教程
- git 官方指南-zh : 官方指南
- book-pro git
- git-command-图形化展示 : 将主要的 git 命令通过更直观的方式表现出来
配置
核心配置
- 生成公钥私钥:
ssh-keygen -t rsa -C "youremail@example.com"
在.ssh 文件夹中会生成 id_rsa 和 id_rsa.pub 两个文件,其中 id_rsa.pub 是公钥,可以提供给别人,id_rsa 是私钥,要保持仅自己知道 - 初始化配置:
- 配置用户名:
git config --global user.name "xxx"
- 配置邮箱:
git config --global user.email "xxx@gmail.com"
- 配置用户名:
- 关闭追踪文件权限:
git config --global core.fileMode false
- 启动大小写敏感:
git config core.ignorecase false
- 显示中文文件名:
git config --global core.quotepath false
- 默认的编译器:
git config --global core.editor vim
- 保证 window 和*unix 中的换行符一致:
git config --global core.safecrlf true
- 设置 git push 的默认方式,对 git 2.X Git warning: push.default is unset; its implicit value is changing :
git config –global push.default simple
- 配置 github 使用 git 命令访问慢的情况:
git config --global http. https://github.com.proxy socks5://127.0.0.1:1086; git config --global https. https://github.com.proxy socks5://127.0.0.1:1086
,详见[这里][]
提高效率
- log 更全更好看:
git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative"
- reflog 个性化输出:
git config --global alias.rlg "reflog --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative"
- 开启给 git 输出着色:
git config --global color.ui true
git config credential.helper store
: 保存需要输入账户密码的链接,例如以 https 的方式链接的,设置了 credential.helper store 之后只要再输入一次账户密码就会记住了- windows 中文乱码解决办法: 中文乱码
- 访问 github 更加快:
git config --global https.proxy 'socks5://127.0.0.1:<PORT>'
config
- 查看全部配置:
git config --list
init
git init
: 新建一个 git 版本管理库git --bare init
: 新建一个 git 版本管理库裸库,用于提交 commit
clone
将远程库中的代码 clone 到本地,支持 HTTPS 协议和 SSH 协议,建议使用 ssh 协议,除了传输更快之外,ssh 协议还能保存用户账户密码信息,下次 pull push 可以不用输入
git clone
: 不会直接在本地生成除了 master 之外的分支,如需要 clone 后git branch -a
再git checkout -b dev origin/dev
生成本地的 dev 分支git clone -b mybranch --single-branch git://sub.domain.com/repo.git
: Clone only one branchgit clone --depth=1 <remote_repo_url>
: 只想获取最后一次 commit 的内容 Using git to get just the latest revisiongit clone https://username:password@github.com/username/repository.git
: git clone with username and password 通过直接在 url 中指定用户名和密码,这个有账户密码暴露的风险- 使用 https/http 方式且配置上用户名和密码的 clone,遇到特殊符号会报错,因为这种方式是用 url 的方式链接的,需要对特殊符号进行 url 编码,编码之后便不会报错,详见 Escape @ character in git proxy password
checkout
切换分支;撤销修改
git checkout <BRANCH>
: 切换到 BRANCH 分支git checkout -- <FIELNAME>
: 撤销 FILENAM 的修改,(--
很重要,如果没有就会变成切换分支),这里撤销修改有两个情况- FIELNAME 已经添加到暂存区(stage) 后,又作了修改,撤销修改就回到添加到暂存区(stage) 后的状态
- FIELNAME 一直没有被放到暂存区(stage),撤销修改就回到和版本库状态
- 撤销修改:
git checkout -- .
: 撤销当前目录的修改git checkout -- /specific/path
: 撤销指定目录的修改
fetch pull
- Git fetch 和 git pull 区别 : fetch 只拉取远程 commit 数据,改变了 remote 里面的 commit id,不会自动合并;pull 拉取最新 commit 并将其 merge,简单的讲
git pull = git fetch + git merge
- fork 项目开发,同步代码
git fetch upstream; git <merge|rebase> upstream/master; git push origin/master
: Git fork 项目后,上游项目更新了 同时更新自己的项目 - 将 origin/upstream 的 PR 远端拉到本地 review:
git fetch origin/upstream pull/ID/head:BRANCHNAME
branch
- 列出分支: 本地分支
git branch
及全部git branch -a
- 查看分支及对应的远程分支:
git branch -v
及git branch -vv
Find out which remote branch a local branch is tracking - 新建分支:
- 新建分支:
git branch <new_branch> <src_branch>
从 src_branch 创建一个新的分支 new_branch - 新建分支同时切换分支:
git checkout -b <new_branch> <src_branch>
- 新建分支:
- 删除分支:
- 删除本地分支:
git branch -d <branch>
- 强行删除没有合并的分支:
git branch -D <branch>
- 删除远程分支:
git push oririn :<branch>
或者git push --delete origin <brancbranchhName>
推荐使用后者(--delete
可改成-d
) - 如果一个分支合并到 master 后,正确的删除方式是:
- 远程分支仍存在:
git push origin --delete <branch>
然后git branch -D <branch>
- 远程分支合并后在 github/gitlab 的 PR 页面已经删除:
git fetch origin -p
然后git branch -D <branch>
- 远程分支仍存在:
- 删除本地的
remote/<origin|upstream>/branch
分支 git 命令行删除远程分支- 如果远程服务器已经没有该分支:
git fetch -p
或者git pull -p
- 如果远程服务器还有该分支,想在删除 track 的分支:
git branch --delete --remoets <remote|upstream>/<branch>
,或者缩写git branch -dr <remote>/<branch>
- 如果远程服务器已经没有该分支:
- 删除本地分支:
- 远程分支已删除但是本地还有
remote/[origin|upstream]/<branch>
暂存在本地的远程分支, 类似这个 :git pull -p
或者git fetch -p
,-p
是prune
的缩写,所以也可以直接使用git pull/fetch prune
add
将工作区(working tree) 中的文件加入到缓存区(staged index)
git add <FILENAME>
: 指定 FILENAME 文件加入 staged indexgit add .
: 将 working tree 所有的文件加入 staged indexgit add -f <FILENAME>
: 将 .gitignore 中忽略的 FILENAME 文件强行加入 staged index
commit
- 允许提交 commit 信息为空 Git commit with no commit message :
- 仅这次提交为空
git commit -a --allow-empty-message -m ''
- 设置全局别名
git config --global alias.nmcommit 'commit -a --allow-empty-message -m ""'
- 仅这次提交为空
- 修改上次提交的内容
- 修改上一次提交的作者信息 Change commit author at one specific commit :
git commit --amend --author="Author Name <email@address.com>"
- 增加文件到上一个 commit:
git add [file]; git commit --amend --no-edit
增加--no-edit
表示不修改上一次提交的 commit 信息
- 修改上一次提交的作者信息 Change commit author at one specific commit :
merge
用于合并分支,如果合并后出现冲突,会以 <<<<<<< ======= >>>>>>>
标记框出来
git merge <BRANCH>
: 将 BRANCH 分支合并到当前分支git merge --ff-only <BRANCH>
: 将 BRANCH 分支仅以fast-forward
的方式合并到当前分支git merge --allow-unrelated-histories <BRANCH>
: 允许将两个没有相关历史的分支进行合并--squash
的使用git checkout master
: 切换到 mastergit merge --squash bugfix
: merge 带上squash
标识符,会将多个 commit 合并成一个 commitgit commit
: 因为合并成一个 commit,所以要重新 commit 一下,此时的 commit 信息是可编辑的
- 合并遇到冲突时使用他们的分支内容, 详见这里 :
git merge --strategy-option theirs
rebase
git rebase <master|upstream/master>
: 当前的 bug 或者 featrue 分支完成开发,rebase 到 master|upstream/master 做好向远端提交的准备git rebase -i HEAD^
: 发现上一个提交错了,或者 review 了代码后需要修改,可以 rebase 上一个 commit,会保留之前的修改和 commite message.完成后使用git add.; git rebase --continue
.但是部分社区不喜欢 rebase,喜欢根据 review 新建一个 commit 或者 revert 提交到对 branch,从而避免重复 reviewgit rebase -i sha-1
modify pick to edit
git rebase --continue
: How to modify a specified commit in gitgit rebase --abort
: 放弃当前的 rebasegit rebase --skip
: rebase 多步解决冲突的过程中,conflict 发现和上一个 rebase 内容一样(即完全舍弃了来自 conflict 分支的内容),这时使用git rebase --skip
进去下一步git rebase -i --root
: Change first commit of project with Git? [duplicate]
remote
- 查看 remote:
git remote
,git remote -v
- 增加远程仓库:
git remote add origin git@server-name:path/repo-name.git
origin 为默认远程仓库名,可以自定义,多个远程仓库类似 github 上 fork 了原仓库同时要追踪原仓库的变化时,可以增加一个upstream
分支,定期更新该分支并合并origin
对应的分支, github Collaborating - Configuring a remote for a fork - 删除 remote:
git remote remove <your_remote_name>
- 修改 remote 名称:
git remote rename <old> <new>
- 修改分支对应的地址 How to change remote origin from Git :
git remote set-url origin git://<new.url.here>
- 同步 upstream 内容到 origin github Collaborating - Syncing a fork 用于 fork 开源项目并对其进行二次开发的同步更新
- 从 upstream 中更新:
git fetch upstream
- 将 master rebase 在 upstream/master 上:
git checkout master; git rebase upstream/master
- merge to master:
git checkout master; git merge upstream/master
,这个操作会将 fork/master 内容同步成 upstream/master 的情况, 且会将本地的提交放到最 git log 的最前
- 从 upstream 中更新:
log
- Git 基础 - 查看提交历史 :
git log
: 简单的查看日志命令git show sha-1
: 查看指定哈希值的日志git log -n 3
: 查看近三条日志记录,可以是本地的,可以是远程的git log -p -2 <filename>
: 查看某个文件(可选) 的近两次提交git log --stat
: 查看日志同时查看每个 commit 修改了什么内容和改变了多少行git log --graph --oneline --abbrev-commit
: 查看 git 日志,每个 commit 一行,且显示图,--abbrev-commit
显示简短 commit 哈希值
- 个性化你的 Git Log 的输出格式
git log --pretty=format:"%h %ci %cn %ce %s"
参数分别是: 哈希 日期 名称 邮箱 概述 git shortlog -nes
: 查看短 log 参数为: 短 log name + email + summary
reflog
reflog 是数据回复工具,在使用 Git 的过程中,有时会不小心丢失 commit 信息,这时可以使用 reflog 进行数据恢复
git reflog
git reflog --format='%C(auto)%h %<|(17)%gd %C(blue)%ci%C(reset) %s <%an %ae>'
格式化 reflog 的输出
push
将本地的分支更新的内容和远程分支关联起来,一般适用于需要多人合作的时候
git push --set-upstream origin <your_branch_name>
或者简写成git -u origin master
(推荐): 创建远程分支,将当前分支代码提交到远程分支,并将本地的 branch 关联到 remotegit push -f origin
: 强力提交代码,会覆盖掉远程代码,例如 git 回滚到任意版本git reset -hard <commit_id>; git push -f origin
(仅作为例子,不推荐使用,更应该使用 revert )
diff
diff 显示两个版本之间的差异
git diff [filename]
: 比较工作目录(Working tree) 和暂存区(staged index) 文件的区别git diff --cached [filename]
: 比较暂存区(staged index) 和上次提交(HEAD) 快照的区别git diff HEAD
: 比较工作目录(Working tree) 和上次提交(HEAD)git diff HEAD^ HEAD
: 查看上次和上上次提交的差别git diff origin/branch-1 [filename]
: 比较 branch-1 本地分支和远端分支的区别git diff <commit_hash1> <commit_hash2>
: 比较同一分支上两个 commit 的 diffgit diff <commit_hash1> <commit_hash2> <filename>
: 比较两个 commit 某个文件的差别git diff --name-only <commit_hash1> <commit_hash2>
: 仅显示两个 commit 不同文件的名称git diff <branch1>..<branch2>
: 比较两个分支上最新的提交的 diffgit diff --stat <COMMIT> <COMMIT>
: diff 统计结果,显示每个文件增减的数量,最后显示这个 patch 的总增减量- 查看两个分支的不同:
- 查看修改了什么文件 :
git diff --name-status <BRANCH_ONE>..<BRANCH_TWO>
,如果是当前分支和 mastergit diff --name-status master
- 查看具体修改的文件内容 :
git diff <BRANCH_ONE>..<BRANCH_TWO>
- 查看修改了什么文件 :
git diff --no-index filename_1 filename_2
: 通过 git 比较 linux 文件的差异,不用两个文件在 git 的仓库中git diff --check
: 检查 git 中是否存在结尾的空格, How to not leave trailing whitespace (using your editor or Git) ,或者使用 git 的 pre-commit 钩子
stash
使用场景是:
- 如果发现在上次提交中忘记了某些内容,并且已经开始在同一分支中处理下一个提交了
- 在别的分支中工作时,接到非常紧急的需求需要快速完成
stash 将在工作目录(Working tree) 和暂存区(staged index) 的文件暂存起来.stash 的存储方式是 stack,所以最新的暂存信息会存储在最上面, stash@{<stash_num>}
的值越小
git stash
: 当前分支所有没有 commit 的代码先暂存起来git stash save <stash_name>
: 将当前的修改暂存起来 并将暂存重命名为<stash_name>
git stash list
: 查看当前 branch 的 stash 记录git stash apply stash@{N}
: 恢复暂存了了 stash 信息git stash drop
: 删除上一条 stashgit stash drop stash@{N}
: 删除指定的 git stashgit stash pop
: 恢复并删除(不建议使用,这个操作不可逆,建议使用git stash apply; git stash drop
代替)git stash clear
: 清空 stash- 在从 stash 恢复前查看 stash 里面和本地的不同 See what's in a stash without applying it : 显示最新 stash 内容的区别
git stash show -p
显示指定 stash 内容的区别git stash show -p stash@{2}
(这个建议在 ide 中进行查看方便对比和删除 stash) git stash apply stash^{/<regex>}
: find the stash by name using git's regular expression syntax bystash^{/<regex>}
and apply stash How to name and retrieve a stash by name in git
reset
- 上一个 commit 部分有错误想要修改上一个错误 How to undo the most recent commits in Git :
git reset --soft HEAD~1
soft 会保持当前 commit 的内容没有变 reset 用 soft 和 hard 的区别 .这个方式适用于 commit 还没有提交到远程,如果提交到远程更好的方式是使用 revert
tag
tag 是将一个 git 的 commit 和标签关联,更容易记住的有意义的名字,能在检查和回退的时候更加便捷.Git 使用两种主要类型的标签:
- 轻量标签 (lightweight): 轻量标签很像一个不会改变的分支 - 它只是一个特定提交的引用
- 附注标签 (annotated): 附注标签是存储在 Git 数据库中的一个完整对象。它们是可以被校验的;其中包含打标签者的名字、电子邮件地址、日期时间;还有一个标签信息;并且可以使用 GNU Privacy Guard (GPG)签名与验证。 通常建议 创建附注标签,这样你可以拥有以上所有信息;但是如果你只是想用一个临时的标签,或者因为某些原因不想要保存那些信息,轻量标签也是可用的
- 查看所有 tag:
git tag
- 为当前 commit 打上 tag:
git tag v1.1
- 为指定 commit(一般为过去的) 打上 tag:
git tag v1.1 <commit_hash>
- 打 tag 的同时为 tag 增加说明:
git tag -a v1.1 -m "my tag message of tag 1.1"
- 查看某个 tag 对应的 commit id:
git show v1.1
- 删除本地的 tag:
git tag -d <tagName>
- 删除远端的 tag:
git push --delete origin <tagName>
- 将本地其中的标签推动到远端:
git push origin v1.1.0
- 将本地所有的 tag 推送到远端:
git push origin --tags
- 删除类似的 tag,如
2.0.0-*
样式的 tag:git tag --list '2.0.0-*' | xargs -I % echo "git tag -d %; git push --delete origin %" | sh
- checkout 到指定标签: 在 Git 中你并不能真的 checkout 指定的 tag,因为 checkout 只对 branch 有效,可以使用
git checkout -b <branchname> <tagname>
在指定标签上创建一个新分支然后进行 checkout
clean
清除某些内容
git clean -n
: 查看有什么内容会删除但是不会进行实际的删除操作git clean -fdx
: 强行删除 untracked 的文件及文件夹,包括 ignore 的文件/文件夹git clean -fdxi
: 与上面类似但是进入交互性命令行进行删除
-q, --quiet do not print names of files removed
-n, --dry-run dry run
-f, --force force
-i, --interactive interactive cleaning
-d remove whole directories
-e, --exclude <pattern> add <pattern> to ignore rules
-x remove ignored files, too
-X remove only ignored files
revert
生成一个新的 commit 来撤销某次 commit 的内容. revert 和 reset 的区别
git revert HEAD
: 撤销上一次 commitgit revert HEAD^
: 撤销上上次 commitgit revert <commit_hash>
: 撤销指定的 commit
cherry-pick
Apply the changes introduced by some existing commits
git cherry-pick [--edit] [-n] [-m parent-number] [-s] [-x] [--ff]
[-S[<keyid>]] <commit>…
git cherry-pick --continue
git cherry-pick --quit
git cherry-pick --abort
-x
: 保留原来的 commit hash(仅仅在 commit 信息里面保存),可以使得 cherry-pick 之后的 hash 码保持和原来分支中的一样,对于开源项目来说很重要方便检查整体 cherry-pick 情况,对公共分支来说非常重要, 参考
rev-parse
Pick out and massage parameters
git rev-parse --short HEAD
: 获取 HEAD 的短 hash 值git rev-parse --abbrev-ref HEAD
: 获取 HEAD 所属的分支名
rm
删除文件,会同时在本地文件系统和 git 中删除
git rm file
: 不再追踪文件,并在文件系统删除文件,删除后还要提交git commit
file1git rm --cached file
: 不再追踪文件,但是不会在文件系统删除文件,之后git commit
gitignore
.gitignore 可以忽略放在 git 目录里,但是不需要追踪和提交的文件
git check-ignore -v <file_name.ext>
: 查看 gitignore 文件中那一行将file_name.ext
过滤掉, 廖雪峰-git 忽略特殊文件 .想要将某个文件加入 stage index 但是一直失败,有可能是 gitignore 文件配置将其过滤了,导致文件不能被追踪.gitignore
可以忽略自己本身改变,不用去编辑.git/info/exclude
文件 .gitignore gitignore itself- A collection of useful .gitignore templates : github 中为常用的 gitignore 文件添加了模板
- gitignore 的写法
符号 含义 /
目录 开头表示根目录 *
多个通配符 ?
单个通配符 []
单个字符匹配列表 !
不忽略追踪的文件或目录
ls-files
git ls-files -d | xargs echo -e | xargs git checkout --
: git 恢复所有 被删除 的文件git ls-files -m | xargs echo -e | xargs git checkout --
: git 回复所有 被修改 的文件
update-index
git-update-index: Register file contents in the working tree to the index
根据 Do git update-index --assume-unchanged rules propagate to clients on pull 知道 update-index
仅对当前的本地库有效,因为 index 仅仅是存在本地中
git update-index [--skip-worktree | --assume-unchanged] <FILE_NAME>
: 将文件保留在 git 中但是不追踪他的改变.因为在 gitignore 中的文件将不会在 git 中,如果要保持文件在 git 中,但是不追踪文件的改变可以使用update-index
.根据 Keep file in a Git repo, but don't track changes ,应该使用--skip-worktree
更好,如果想要恢复改变可以使用--no-skip-worktree/--no-assume-unchanged
。一般可以对配项目的配置文件进行设置,防止其被误操作提交到 git 中git update-index --chmod=+x path/to/file
: 修改文件path/to/file
变成可执行文件, 想要将文件从可执行变成不可执行使用git update-index --chmod=-x path/to/file
FAQ
git-cli 每次要求输入用户名密码
根据 这里
- 使用 SSH 而非 HTTPS: 使用 https 会导致默认使用账户名密码,
git remote -v
查看是否使用的协议,通过git remote set-url origin git@github.com:username/repo.git
将 HTTPS 修改成 SSH - 配置凭证存储机制:
git config --global credential.helper store
配置凭证存储,仅需下次再输入一次帐号密码就能记住密码
merge 和 rebase 的区别
- merge : 合并两个 git 分支时,会按照 commit 的顺序排序进行合并
- rebase : 会将当前分支的 commit 合并到 rebase 分支 HEAD 后面,
git checkout patch; git rebase master
会将 master 和 patch 分支合并,且将仅在 patch 分支中有的 commit 合到 master 的 HEAD 后面
revert 和 reset 的区别
- revert 是用一次新的 commit 来回滚之前的 commit,reset 是直接删除指定的 commit
- reset 是把 HEAD 向后移动了一下,而 revert 是 HEAD 继续前进,新的 commit 的内容和要 revert 的内容正好相反,能够抵消要被 revert 的内容
github 或者 gitlab 合并 PR 过来的分支的时候
- gitlab 在分支 merge 的时候会显示各个 merge 的基本信息 gitlab 设置分支 merge 时合并所有 commit 保持历史干净 ,一般通过 web 页面的 squash 按键解决
重命名追踪的文件
- 一般直接修改文件名就能使得 git 追踪到重命名
- 也可以通过 cli 进行修改,重命名 git 追踪的文件
git mv <folder|file> <folder|file>
如果是更改大小写但是平台是不区分大小写的话要引入中间变量git mv src_file tmp; git mv tmp dest_file
In a Git repository, how to properly rename a directory
怎么写好 commit message
获取当前的分支名
git branch | grep \* | cut -d ' ' -f2
git rev-parse --abbrev-ref HEAD
fork branch clone 的区别
- fork: 对存储仓库(repository)进行的远程的、服务器端的拷贝,从源头上就有所区别。复刻实际上不是 Git 的范畴。它更像是个政治/社会概念
- clone: 是个对某个远程仓库的本地拷贝。克隆时,实际上是拷贝整个源存储仓库,包括所有历史记录和分支
- branch: 是 git 的一种机制,处理单一存储仓库中的变更,并最终目的是用于与其他部分代码合并
找回已经删除的分支
- 先通过
reflog
找到对应的 SHA1 值 - 然后通过
git checkout [sha]
切换到这个 SHA1 都应的 commit, 再使用git checkout -b [branchname]
切换成对应的分支名.或者直接使用git checkout -b <branch> <sha>
一步到位将对应的 SHA1 值切换成对应的分支
合到 release 或者 hotfix 分支的合并规则
为了保持原有的规则,一般是使用 git checkout release|hotfix; git merge master
的方式合并的
调整 commit 的顺序
Reordering of commits : 使用 git rebase -i <HASH>
,然后调整顺序,善用 ddkP
以及 ddp
命令能有效完成部分操作
git 是否保持文件权限
根据 Does git store the read, write, execute permissions for files , So git stores only the content in the file and the execute bit. ,即仅保持文件的内容和文件是否可执行的状态
如果需要修改已经在 git 仓库中文件的可执行属性,可以使用 update-index 中的 --chmod=+x
或者 --chmod=-x
仅获取当前分支名
这里 git rev-parse --abbrev-ref HEAD
git 提示不在 git 目录下 但是目录存在
- HEAD 文件的问题,详见 这里 或者 这里 。只需要将
.git/HEAD
文件删除,然后 bash 运行echo 'ref: refs/heads/master' > .git/HEAD
就行了
仅本地忽略部分文但是不共享到别的用户
编辑 .git/info/exclude
文件,这个文件和 .gitignore
一样的格式。这个的好处是仅仅在你本地忽略了这部分文件,别人对其是不可感知的,如果这部分文件是已经在 git 中管理的,则要使用 git update-index --assume-unchanged <file-list>
让 git 不要追踪他
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Redis 文档教程知识点
下一篇: MyBatis 介绍和使用
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论