Git cli - zhongjiajie/zhongjiajie.github.com GitHub Wiki
- git追踪的只是修改,不是文件,只有将修改add到stage之后的内容才会被管理
- git-recipes: 作者自己整理个的git相关教程
- git官方指南-zh: 官方指南
- book-pro git
- git-command-图形化展示: 将主要的git命令通过更直观的方式表现出来
- 生成公钥私钥:
ssh-keygen -t rsa -C "[email protected]"
在.ssh文件夹中会生成id_rsa和id_rsa.pub两个文件,其中id_rsa.pub是公钥,可以提供给别人,id_rsa是私钥,要保持仅自己知道 - 初始化配置:
- 配置用户名:
git config --global user.name "xxx"
- 配置邮箱:
git config --global user.email "[email protected]"
- 配置用户名:
- 关闭追踪文件权限:
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.XGit 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>'
- 查看全部配置:
git config --list
-
git init
: 新建一个git版本管理库 -
git --bare init
: 新建一个git版本管理库裸库,用于提交commit
将远程库中的代码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 branch -
git clone --depth=1 <remote_repo_url>
: 只想获取最后一次commit的内容Using git to get just the latest revision -
git clone https://username:[email protected]/username/repository.git
: git clone with username and password通过直接在url中指定用户名和密码,这个有账户密码暴露的风险 - 使用https/http方式且配置上用户名和密码的clone,遇到特殊符号会报错,因为这种方式是用url的方式链接的,需要对特殊符号进行url编码,编码之后便不会报错,详见Escape @ character in git proxy password
切换分支;撤销修改
-
git checkout <BRANCH>
: 切换到BRANCH分支 -
git checkout -- <FIELNAME>
: 撤销FILENAM的修改,(--
很重要,如果没有就会变成切换分支),这里撤销修改有两个情况- FIELNAME已经添加到暂存区(stage)后,又作了修改,撤销修改就回到添加到暂存区(stage)后的状态
- FIELNAME一直没有被放到暂存区(stage),撤销修改就回到和版本库状态
- 撤销修改:
-
git checkout -- .
: 撤销当前目录的修改 -
git checkout -- /specific/path
: 撤销指定目录的修改
-
-
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
- 列出分支: 本地分支
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
将工作区(working tree)中的文件加入到缓存区(staged index)
-
git add <FILENAME>
: 指定FILENAME文件加入staged index -
git add .
: 将working tree所有的文件加入staged index -
git add -f <FILENAME>
: 将.gitignore中忽略的FILENAME文件强行加入staged index
- 允许提交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 protected]>"
- 增加文件到上一个commit:
git add [file]; git commit --amend --no-edit
增加--no-edit
表示不修改上一次提交的commit信息
- 修改上一次提交的作者信息Change commit author at one specific commit:
用于合并分支,如果合并后出现冲突,会以<<<<<<< ======= >>>>>>>
标记框出来
-
git merge <BRANCH>
: 将BRANCH分支合并到当前分支 -
git merge --ff-only <BRANCH>
: 将BRANCH分支仅以fast-forward
的方式合并到当前分支 -
git merge --allow-unrelated-histories <BRANCH>
: 允许将两个没有相关历史的分支进行合并 -
--squash
的使用-
git checkout master
: 切换到master -
git merge --squash bugfix
: merge带上squash
标识符,会将多个commit合并成一个commit -
git commit
: 因为合并成一个commit,所以要重新commit一下,此时的commit信息是可编辑的
-
- 合并遇到冲突时使用他们的分支内容,详见这里:
git merge --strategy-option theirs
-
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,从而避免重复review -
git rebase -i sha-1
modify pick to edit
git rebase --continue
: How to modify a specified commit in git -
git rebase --abort
: 放弃当前的rebase -
git rebase --skip
: rebase多步解决冲突的过程中,conflict发现和上一个rebase内容一样(即完全舍弃了来自conflict分支的内容),这时使用git rebase --skip
进去下一步 -
git rebase -i --root
: Change first commit of project with Git? [duplicate]
- 查看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内容到origingithub 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中更新:
-
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是数据回复工具,在使用Git的过程中,有时会不小心丢失commit信息,这时可以使用reflog进行数据恢复
git reflog
-
git reflog --format='%C(auto)%h %<|(17)%gd %C(blue)%ci%C(reset) %s <%an %ae>'
格式化reflog的输出
将本地的分支更新的内容和远程分支关联起来,一般适用于需要多人合作的时候
-
git push --set-upstream origin <your_branch_name>
或者简写成git -u origin master
(推荐): 创建远程分支,将当前分支代码提交到远程分支,并将本地的branch关联到remote -
git push -f origin
: 强力提交代码,会覆盖掉远程代码,例如git回滚到任意版本git reset -hard <commit_id>; git push -f origin
(仅作为例子,不推荐使用,更应该使用revert)
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的diff -
git diff <commit_hash1> <commit_hash2> <filename>
: 比较两个commit某个文件的差别 -
git diff --name-only <commit_hash1> <commit_hash2>
: 仅显示两个commit不同文件的名称 -
git diff <branch1>..<branch2>
: 比较两个分支上最新的提交的diff -
git 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将在工作目录(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
: 删除上一条stash -
git stash drop stash@{N}
: 删除指定的git stash -
git 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
- 上一个commit部分有错误想要修改上一个错误How to undo the most recent commits in Git:
git reset --soft HEAD~1
soft会保持当前commit的内容没有变reset用soft和hard的区别.这个方式适用于commit还没有提交到远程,如果提交到远程更好的方式是使用revert
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
清除某些内容
-
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
生成一个新的commit来撤销某次commit的内容.revert和reset的区别
-
git revert HEAD
: 撤销上一次commit -
git revert HEAD^
: 撤销上上次commit -
git revert <commit_hash>
: 撤销指定的commit
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情况,对公共分支来说非常重要,参考
Pick out and massage parameters
-
git rev-parse --short HEAD
: 获取HEAD的短hash值 -
git rev-parse --abbrev-ref HEAD
: 获取HEAD所属的分支名
删除文件,会同时在本地文件系统和git中删除
-
git rm file
: 不再追踪文件,并在文件系统删除文件,删除后还要提交git commit
-
file1git rm --cached file
: 不再追踪文件,但是不会在文件系统删除文件,之后git commit
.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的写法
符号 含义 /
目录 开头表示根目录 *
多个通配符 ?
单个通配符 []
单个字符匹配列表 !
不忽略追踪的文件或目录
-
git ls-files -d | xargs echo -e | xargs git checkout --
: git恢复所有被删除的文件 -
git ls-files -m | xargs echo -e | xargs git checkout --
: git回复所有被修改的文件
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
根据这里
- 使用SSH而非HTTPS: 使用https会导致默认使用账户名密码,
git remote -v
查看是否使用的协议,通过git remote set-url origin [email protected]:username/repo.git
将HTTPS修改成SSH - 配置凭证存储机制:
git config --global credential.helper store
配置凭证存储,仅需下次再输入一次帐号密码就能记住密码
- merge: 合并两个git分支时,会按照commit的顺序排序进行合并
-
rebase: 会将当前分支的commit合并到rebase分支HEAD后面,
git checkout patch; git rebase master
会将master和patch分支合并,且将仅在patch分支中有的commit合到master的HEAD后面
- revert是用一次新的commit来回滚之前的commit,reset是直接删除指定的commit
- reset是把HEAD向后移动了一下,而revert是HEAD继续前进,新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容
- 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
git branch | grep \* | cut -d ' ' -f2
git rev-parse --abbrev-ref HEAD
- fork: 对存储仓库(repository)进行的远程的、服务器端的拷贝,从源头上就有所区别。复刻实际上不是 Git 的范畴。它更像是个政治/社会概念
- clone: 是个对某个远程仓库的本地拷贝。克隆时,实际上是拷贝整个源存储仓库,包括所有历史记录和分支
- branch: 是git的一种机制,处理单一存储仓库中的变更,并最终目的是用于与其他部分代码合并
- 先通过
reflog
找到对应的SHA1值 - 然后通过
git checkout [sha]
切换到这个SHA1都应的commit, 再使用git checkout -b [branchname]
切换成对应的分支名.或者直接使用git checkout -b <branch> <sha>
一步到位将对应的SHA1值切换成对应的分支
为了保持原有的规则,一般是使用git checkout release|hotfix; git merge master
的方式合并的
Reordering of commits: 使用git rebase -i <HASH>
,然后调整顺序,善用ddkP
以及ddp
命令能有效完成部分操作
根据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/info/exclude
文件,这个文件和.gitignore
一样的格式。这个的好处是仅仅在你本地忽略了这部分文件,别人对其是不可感知的,如果这部分文件是已经在git中管理的,则要使用git update-index --assume-unchanged <file-list>
让git不要追踪他