- 新建 Git 项目
- 初始化一个Git仓库
- 新建一个目录,将其初始化为Git代码库
- 关联远程仓库
- 例如
- 配置本地 SSH 密钥
- git config【全局配置】
- git log【历史提交查看】
- git status【工作区和暂存区的状态查看】
- git add【将工作区的文件添加到暂存区】
- git commit【将暂存区的更改提交至本地仓库】
- git push、pull【拉取、推送】
- git branch【分支管理】
- 分支合并
- git stash【将未提交的修改保存至堆栈】
- git diff【工作区和暂存区的文件对比】
- git remote【远程仓库相关操作】
- git rm、mv
- git checkout【版本切换】
- git reset【版本重设】
- git revert【版本撤销】
新建 Git 项目
新建一个目录,将其初始化为Git代码库
$ git init [project-name]
关联远程仓库
$ git remote add
例如
$ git remote add origin https://github.com/xxxxxx
2. 直接 clone 远程仓库
```git
# 新建好远程仓库,然后 clone 到本地
$ git clone <git-repo-url>
# 将远程仓库下载到指定文件中,如果没有会自动生成
$ git clone <git-repo-url> [project-name]
配置本地 SSH 密钥
$ ssh-keygen -t rsa -f ~/.ssh/id_rsa -C "fcscanf@outlook.com"
- -t rsa:表示用 rsa 算法进行加密。若不指定,则默认生成用于 SSH-2 的 RSA 密钥。
- -f:指定生成的密钥路径,其中 id_rsa 为生成的文件名称。
- -C:提供一个新注释,默认初始化为 user@host。
git config【全局配置】
# 显示当前的Git配置
$ git config --list
# 配置全局用户
$ git config --global user.name "Fcant"
$ git config --global user.email fcscanf@outlook.com
# 配置别名
$ git config --global alias.co checkout
$ git config --global alias.ss status
$ git config --global alias.cm commit
$ git config --global alias.br branch
$ git config --global alias.rg reflog
# 删除全局配置
$ git config --global --unset alias.xxx
$ git config --global --unset user.xxx
# 颜色设置
$ git config --global color.ui true # git status等命令自动着色
$ git config --global color.status auto
$ git config --global color.diff auto
$ git config --global color.branch auto
$ git config --global color.interactive auto
$ git config --global --unset http.proxy # remove proxy configuration on git
git log【历史提交查看】
git 中 D 向下翻一行 F 向下翻页 B 向上翻页 Q 退出
# 显示当前分支的版本历史
$ git log
# 显示demo.html文件的历史commit记录
$ git log demo.html
# 根据关键词搜索commit历史
$ git log -S [keyword]
# 将日志记录一行一行的显示
$ git log --oneline
# 查找日志记录中(commit提交时的注释)与关键字有关的记录
$ git log --grep="关键字"
# commit记录图形化显示
$ git log --graph
# 将所有记录都详细的显示出来
$ git log --all
# 查找这个作者提交的commit记录
$ git log --author "username"
# commit 提交记录顺序翻转
$ git log --reverse
# 查找规定的时间前后的记录
$ git log --before="2019-06-06"
$ git log --after="2019-06-06"
# git log -10 显示最近10次提交
$ git log -num
# 显示commit历史,以及每次commit发生变更的文件,会列出具体文件列表
$ git log --stat
# 可以定制要显示的记录格式
$ git log --pretty=format:"%an"
# 显示每次提交所引入的差异
$ git log -p
# 显示指定文件是什么人在什么时间修改过
$ git blame [file]
Git 支持用各种 placeholder 来决定 commit 的显示内容,以格式化输出历史记录,常用的显示如下:
- %H:commit hash
- %h:缩短的 commit hash
- %T:tree hash
- %t:缩短的 tree hash
- %P:parent hashes
- %p:缩短的 parent hashes
- %an:作者名字
- %aN:mailmap 的作者名
- %ae:作者邮箱
- %ad:日期(—date= 制定的格式)
- %ar:日期,,相对格式(1 day ago)
- %cn:提交者名字
- %ce:提交者 email
- %cd:提交日期(—date= 制定的格式)
- %cr:提交日期,相对格式(1 day ago)
- %d:ref名称
- %s:commit信息标题
- %b:commit信息内容
- %n:换行
git status【工作区和暂存区的状态查看】
# 查看工作区和暂存区的状态
$ git status
# 以简短方式查看工作区和暂存区文件状态
$ git status -s
# 查看工作区和暂存区文件状态,包括被忽略的文件
$ git status --ignored
git add【将工作区的文件添加到暂存区】
# 添加指定文件到暂存区(追踪新增的指定文件)
$ 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 2.0 以下版本--------------------------
# 作用于文件的新增和修改
$ git add .
# 作用于文件的修改和删除
$ gti add -u
# 作用于文件的增删改
$ git add -A
git add . 操作的对象是当前目录的所有文件变更,”.” 表示当前目录。使用该命令会把工作区的所有变化提交到暂存区,包括文件内容修改(modified)以及新文件(new),但不包括被删除的文件。
git add -u 是 git add —update 的缩写,操作的对象是整个工作区已经跟踪的文件变更,无论当前位于哪个目录下。仅监控已经被 add 的文件,即 tracked file,不会提交新文件,它会将被修改的文件(包括文件删除)提交到暂存区。
git add -A 是 git add —all 的缩写,操作的对象是整个工作区所有文件的变更,无论当前位于哪个目录下。是上面两个功能的合集。
通过 git add -i 进入 Git 命令提示:
通过输入序列号或首字母可以选择相应的功能,具体的功能解释如下:
- status:功能上和 git add -i 相似
- update:即 git add -u
- revert:把已经添加到暂存区的文件从暂存区剔除,其操作方式和 update 类似
- add untracked:可以把新增的文件添加到暂存区,其操作方式和 update 类似
- patch:即 git add -p
- diff:比较暂存区文件和本地版本库的差异,其操作方式和 update 类似
- quit:退出 git add -i 命令系统
- help:查看帮助信息
【git add -p】
这是交互命令中最有用的模式,其操作方式和 update 类似,选择后 Git 会显示这些文件的当前内容与本地版本库中的差异,然后可以自己决定是否添加这些修改到暂存区,其中命令行提供的可操作方式解释如下:
具体解释如下:
git commit【将暂存区的更改提交至本地仓库】
# 将暂存区的文件提交到本地仓库并添加提交说明
$ git commit -m "本次提交的说明"
# 不打开编辑器,直接在命令行中输入多行提交原因
$ git commit -m '第一行提交原因' -m '第二行提交原因'
# 提交暂存区的指定文件到仓库区
$ git commit [file1] [file2] ... -m [message]
# 提交工作区自上次commit之后的变化,直接到仓库区
$ git commit -a
# 提交时显示所有diff信息
$ git commit -v
# add 和 commit 的合并,便捷写法,将add和commit合为一步
# 和 git add -u 命令一样,未跟踪的文件是无法提交上去的,将工作区修改或删除的文件提交到本地版本库,新增的文件不会被提交
$ git commit -am "本次提交的说明"
# 跳过验证继续提交
$ git commit --no-verify
$ git commit -n
# 编辑器会弹出上一次提交的信息,可以在这里修改提交信息
$ git commit --amend
# 修复提交,同时修改提交信息,修改最新一条提交记录的提交原因
$ git commit --amend -m "本次提交的说明"
# 加入 --no-edit 标记会修复提交但不修改提交信息,编辑器不会弹出上一次提交的信息
$ git commit --amend --no-edit
# 重做上一次commit,并包括指定文件的新变化
$ git commit --amend [file1] [file2] ...
# 将当前文件改动提交到 HEAD 或当前分支的历史ID
$ git commit -C HEAD
git commit —amend 既可以修改上次提交的文件内容,也可以修改上次提交的说明。会用一个新的 commit 更新并替换最近一次提交的 commit 。如果暂存区有内容,这个新的 commit 会把任何修改内容和上一个 commit 的内容结合起来。如果暂存区没有内容,那么这个操作就只会把上次的 commit 消息重写一遍。
git push、pull【拉取、推送】
分支推送顺序的写法是 <来源地>:<目的地>
# 将本地仓库的文件推送到远程分支
# 如果远程仓库没有这个分支,会新建一个同名的远程分支,如果省略远程分支名,则表示两者同名
$ git push <远程主机名> <本地分支名>:<远程分支名>
$ git push origin branchname
# 如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支
$ git push origin :master
# 等同于
$ git push origin --delete master
# 建立当前分支和远程分支的追踪关系
$ git push -u origin master
# 如果当前分支与远程分支之间存在追踪关系,则可以省略分支和 -u
$ git push
# 不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机
$ git push --all origin
# 拉取所有远程分支到本地镜像仓库中
$ git pull
# 拉取远程仓库分支变化,并与本地分支合并
$ git pull [remote] [branch]
# 等同于 fetch + merge
$ git fetch origin branchName
$ git merge origin/branchName
# 如果远程主机的版本比本地版本更新,推送时 Git 会报错,要求先在本地做 git pull 合并差异,
# 然后再推送到远程主机。这时,如果你一定要推送,可以使用 –-force 选项(尽量避免使用)
$ git push --force origin | git push -f origin
git branch【分支管理】
# 查看本地分支,列出所有本地分支
$ git branch | git branch -l
# 查看远程分支
$ git branch -r
# 查看所有分支(本地分支+远程分支)
$ git branch -a
# 查看所有分支并带上最新的提交信息
$ git branch -av
# 查看本地分支对应的远程分支
$ git branch -vv
# 新建分支,在别的分支下新建一个分支,新分支会复制当前分支的内容
# 注意:如果当前分支有修改,但是没有提交到仓库,此时修改的内容是不会被复制到新分支的
$ git branch branchname
# 修改当前分支名
$ git branch -m branchname
# 切换分支(切换分支时,本地工作区,仓库都会相应切换到对应分支的内容)
$ git checkout branchname
# 新建一个aaa分支,并切换到该分支(新建分支和切换分支的简写)
$ git checkout -b aaa
# 新建一个基于master分支的aaa分支,并切换到该分支
$ git checkout -b aaa master
# 新建一个分支,指向指定commit
$ git branch [branch] [commit]
# 新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]
# 建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream [branch] [remote-branch]
# 新建一条空分支
$ git checkout --orphan emptyBranchName
$ git rm -rf .
# 删除本地分支,会阻止删除包含未合并更改的分支
$ git brnach -d branchname
# 强制删除一个本地分支,即使包含未合并更改的分支
$ git branch -D branchname
# 删除远程分支,推送一个空分支到远程分支,其实就相当于删除远程分支
$ git push origin :远程分支名
# 或者
$ git push origin --delete 远程分支名
$ git branch -dr [remote/branch]
分支合并
1. git merge【合并】
# 默认fast-forward,HEAD指针直接指向被合并的分支
$ git merge
# 禁止快进式合并
$ git merge --no-ff
$ git merge --squash
- fast-forward:会在当前分支的提交历史中添加进被合并分支的提交历史。
- —no-ff:会生成一个新的提交,让当前分支的提交历史不会那么乱。
- —squash:不会生成新的提交,会将被合并分支多次提交的内容直接存到工作区和暂存区,由开发者手动去提交,这样当前分支最终只会多出一条提交记录,不会掺杂被合并分支的提交历史。
2. git rebase【重新定义分支的版本库状态】
$ git rebase branch_name
通过 rebase 合并分支跟 merge 很像,但还是有本质的区别,具体看下图:
git stash【将未提交的修改保存至堆栈】
git stash 能够将所有未提交的修改保存至堆栈中,用于后续恢复当前工作区内容。如果文件没有提交到暂存区的话,使用该命令会提示 No local changes to save,则无法将修改保存到堆栈中。
使用场景:
当接到一个修复紧急 bug 的任务时候,一般都是先创建一个新的 bug 分支来修复它,然后合并,最后删除。但如果当前正在开发功能中,短时间还无法完成,无法直接提交到仓库,这时候可以先把当前工作区的内容 git stash 一下,然后去修复 bug,修复后再 git stash pop,恢复之前的工作内容。
# 将所有未提交的修改(提交到暂存区)保存至堆栈中
$ git stash
# 给本次存储加个备注,以防时间久了忘了
$ git stash save "存储"
# 存储未追踪的文件
$ git stash -u
# 查看栈中保存的列表
$ git stash list
# 恢复后,stash 记录并不删除
$ git stash apply "stash@{index}"
# 从Git栈中检出其中一条记录,但不从栈中移除
$ git stash apply stash@{0}
# 恢复的同时把 stash 记录也删了
$ git stash pop "stash@{index}"
# 把当前栈中最近一次记录检出并创建一个新分支
$ git stash branch new_banch
# 从Git栈中检出最新保存的一条记录,并将它从栈中移除
$ git stash pop
# 删除 stash 记录
$ git stash drop "stash@{index}"
# 移除栈中其中一条记录
$ git stash drop stash@{0}
# 删除所有存储的进度
$ git stash clear
# 为当前修改或删除的文件创建一个自定义的栈并返回一个ID,此时并未真正存储到栈里
$ git stash create
# 将 create 方法里返回的ID放到 store 后面,此时在栈里真正创建了一个记录,但当前修改或删除的文件并未从工作区移除
$ git stash store xxxxxx
# 查看当前记录中修改了哪些文件
$ git stash show "stash@{index}"
# 显示栈中其中一条记录
$ git stash show stash@{0}
# 查看当前记录中修改了哪些文件的内容
$ git stash show -p "stash@{index}"
git diff【工作区和暂存区的文件对比】
# 查看工作区和暂存区单个文件的对比
$ git diff filename
# 查看工作区和暂存区所有文件的对比
$ git diff
# 查看工作区和暂存区所有文件的对比,并显示出所有有差异的文件列表
$ git diff --stat
# 注意:
# 1.你修改了某个文件,但是没有提交到暂存区,这时候会有对比的内容,一旦提交到暂存区,就不会有对比的内容(因为暂存区已经更新)
# 2.如果你新建了一个文件,但是没有提交到暂存区,这时候diff是没有结果的
# 查看暂存区与上次提交到本地仓库的快照(即最新提交到本地仓库的快照)的对比
$ git diff --cached/--staged
# 查看工作区与上次提交到本地仓库的快照(即最新提交到本地仓库的快照)的对比
$ git diff branchname
# 查看工作区与 HEAD 指向(默认当前分支最新的提交)的对比
$ git diff HEAD
# 显示两次提交之间的差异
$ git diff [first-branch]...[second-branch]
# 显示今天你写了多少行代码
$ git diff --shortstat "@{0 day ago}"
# 查看两个本地分支中某一个文件的对比
$ git diff branchname..branchname filename
# 查看两个本地分支所有的对比
$ git diff branchname..branchname
# 查看远程分支和本地分支的对比
$ git diff origin/branchname..branchname
# 查看远程分支和远程分支的对比
$ git diff origin/branchname..origin/branchname
# 查看两个 commit 的对比
$ git diff commit1..commit2
git remote【远程仓库相关操作】
# 查看所有远程主机
$ git remote
# 查看关联的远程仓库的详细信息
$ git remote -v
# 关联远程仓库
$ git remote add <name> <git-repo-url>
# 例如
$ git remote add origin https://github.com/xxxxxx
# 删除远程仓库的 “关联”
$ git remote rm projectname
# 设置远程仓库的 “关联”
$ git remote set-url origin <newurl>
# 下载远程仓库的所有变动
$ git fetch [remote]
# 显示某个远程仓库的信息
$ git remote show [remote]
git rm、mv
# 删除暂存区和工作区的文件
$ git rm filename
# 只删除暂存区的文件,不会删除工作区的文件
$ git rm --cached filename
# 将a.md重命名为b.md,同时添加变动到暂存区,加 -f 参数可以强制重命名
# 相比用 mv a.md b.md 命令省去了 git add 操作
$ git mv a.md b.md -f
如果在配置 .gitignore 文件之前就把某个文件上传到远程仓库了,这时候想把远程仓库中的该文件删除,此时配置 .gitignore 文件也没有用,因为该文件已经被追踪了,但又不想在本地删除该文件后再重新提交到远程仓库,这时候可以使用 git rm —cached filename 命令取消该文件的追踪,这样下次提交的时候,git 就不会再提交这个文件,从而远程仓库的该文件也会被删除。
git checkout【版本切换】
# 恢复暂存区的指定文件到工作区
$ git checkout <filename>
# 恢复暂存区的所有文件到工作区
$ git checkout .
# 回滚到最近的一次提交
# 如果修改某些文件后,没有提交到暂存区,此时的回滚是回滚到上一次提交
# 如果是已经将修改的文件提交到仓库了,这时再用这个命令回滚无效,因为回滚到的是之前自己修改后提交的版本
$ git checkout HEAD
$ git checkout HEAD -- filename
# 回滚到最近一次提交的上一个版本
$ git checkout HEAD^
# 回滚到最近一次提交的上2个版本
$ git checkout HEAD^^
# 切换分支,在这里也可以看做是回到项目「当前」状态的方式
$ git checkout <当前正在使用的分支>
# 切换到某个指定的 commit 版本
$ git checkout <commit_id>
# 切换指定 tag
$ git checkout <tag>
在开发的正常阶段,HEAD 一般指向 master 或其他的本地分支,但当使用 git checkout
切换到某一次提交后,可以查看文件,编译项目,运行测试,甚至编辑文件而不需要考虑是否会影响项目的当前状态,所做的一切都不会被保存到主栈的仓库中。当想要回到主线继续开发时,使用 git checkout branchName 回到项目初始的状态,这时候会提示是否需要新建一条分支用于保留刚才的修改。
git reset【版本重设】
git reset [—hard|soft|mixed|merge|keep] [
该命令用于将当前的分支重设到指定的
# 从暂存区撤销特定文件,但不改变工作区。它会取消这个文件的暂存,而不覆盖任何更改
$ git reset <fileName>
# 重置暂存区最近的一次提交,但工作区的文件不变
$ git reset
# 等价于
$ git reset HEAD (默认)
# 重置暂存区与工作区,回退到最近一次提交的版本内容
$ git reset --hard
# 重置暂存区与工作区,回退到最近一次提交的上一个版本
$ git reset --hard HEAD^
# 将当前分支的指针指向为指定 commit(该提交之后的提交都会被移除),同时重置暂存区,但工作区不变
$ git reset <commit>
# 等价于
$ git reset --mixed <commit>
# 将当前分支的指针指向为指定 commit(该提交之后的提交都会被移除),但保持暂存区和工作区不变
$ git reset --soft <commit>
# 将当前分支的指针指向为指定 commit(该提交之后的提交都会被移除),同时重置暂存区、工作区
$ git reset --hard <commit>
# 重置当前HEAD为指定commit,但保持暂存区和工作区不变
$ git reset --keep [commit]
git reset 有很多种用法,它可以被用来移除提交快照,尽管它通常被用来撤销暂存区和工作区的修改。不管是哪种情况,它应该只被用于本地修改——永远不应该重设和其他开发者共享的快照。
当用 reset 回滚到了某个版本后,那么在下一次 git 提交时,之前该版本后面的版本会被作为垃圾删掉。当回退到一个旧版本后,此时再用 git log 查看提交记录,会发现之前的新版本记录没有了。如果想恢复到新版本但又找不到新版本 commit_id 怎么办?
此时可以用 git reflog 查看历史命令,这样就可以看到之前新版本的 commit_id ,然后 git reset —hard commit_id 就可以回到之前的新版本代码。不过这种方式在别的电脑上是无法获取当前电脑上的历史命令的,所以这种方法不安全。万一电脑突然坏了,这时候就无法回到未来的版本。
git revert【版本撤销】
# 生成一个撤销最近的一次提交的新提交
$ git revert HEAD
# 生成一个撤销最近一次提交的上一次提交的新提交
$ git revert HEAD^
# 生成一个撤销最近一次提交的上两次提交的新提交
$ git revert HEAD^^
# 生成一个撤销最近一次提交的上n次提交的新提交
$ git revert HEAD~num
# 生成一个撤销指定提交版本的新提交
$ git revert <commit_id>
# 生成一个撤销指定提交版本的新提交,执行时不打开默认编辑器,直接使用 Git 自动生成的提交信息
$ git revert <commit_id> --no-edit
git revert 命令用来撤销某个已经提交的快照,和 reset 重置到某个指定版本不一样,它是在提交记录最后面加上一个撤销了更改的新提交,而不是从项目历史中移除这个提交,这避免了 Git 丢失项目历史。
撤销(revert)应该用在想要在项目历史中移除某个提交的时候。撤销(revert)被设计为撤销公共提交的安全方式,而重设(reset)被设计为重设本地更改。这两个命令的目的不同,它们的实现也不一样:重设完全地移除了一堆更改,而撤销保留了原来的更改,用一个新的提交来实现撤销。因此如果需要修复一个公共提交,最好是使用 git revert。