新建 Git 项目

  1. 本地新建好 Git 项目,然后关联远程仓库 ```git

    初始化一个Git仓库

    $ git init

新建一个目录,将其初始化为Git代码库

$ git init [project-name]

关联远程仓库

$ git remote add

例如

$ git remote add origin https://github.com/xxxxxx

  1. 2. 直接 clone 远程仓库
  2. ```git
  3. # 新建好远程仓库,然后 clone 到本地
  4. $ git clone <git-repo-url>
  5. # 将远程仓库下载到指定文件中,如果没有会自动生成
  6. $ git clone <git-repo-url> [project-name]

配置本地 SSH 密钥

  1. $ ssh-keygen -t rsa -f ~/.ssh/id_rsa -C "fcscanf@outlook.com"
  • -t rsa:表示用 rsa 算法进行加密。若不指定,则默认生成用于 SSH-2 的 RSA 密钥。
  • -f:指定生成的密钥路径,其中 id_rsa 为生成的文件名称。
  • -C:提供一个新注释,默认初始化为 user@host。

image.png

git config【全局配置】

  1. # 显示当前的Git配置
  2. $ git config --list
  3. # 配置全局用户
  4. $ git config --global user.name "Fcant"
  5. $ git config --global user.email fcscanf@outlook.com
  6. # 配置别名
  7. $ git config --global alias.co checkout
  8. $ git config --global alias.ss status
  9. $ git config --global alias.cm commit
  10. $ git config --global alias.br branch
  11. $ git config --global alias.rg reflog
  12. # 删除全局配置
  13. $ git config --global --unset alias.xxx
  14. $ git config --global --unset user.xxx
  15. # 颜色设置
  16. $ git config --global color.ui true # git status等命令自动着色
  17. $ git config --global color.status auto
  18. $ git config --global color.diff auto
  19. $ git config --global color.branch auto
  20. $ git config --global color.interactive auto
  21. $ git config --global --unset http.proxy # remove proxy configuration on git

git log【历史提交查看】

git 中 D 向下翻一行 F 向下翻页 B 向上翻页 Q 退出

  1. # 显示当前分支的版本历史
  2. $ git log
  3. # 显示demo.html文件的历史commit记录
  4. $ git log demo.html
  5. # 根据关键词搜索commit历史
  6. $ git log -S [keyword]
  7. # 将日志记录一行一行的显示
  8. $ git log --oneline
  9. # 查找日志记录中(commit提交时的注释)与关键字有关的记录
  10. $ git log --grep="关键字"
  11. # commit记录图形化显示
  12. $ git log --graph
  13. # 将所有记录都详细的显示出来
  14. $ git log --all
  15. # 查找这个作者提交的commit记录
  16. $ git log --author "username"
  17. # commit 提交记录顺序翻转
  18. $ git log --reverse
  19. # 查找规定的时间前后的记录
  20. $ git log --before="2019-06-06"
  21. $ git log --after="2019-06-06"
  22. # git log -10 显示最近10次提交
  23. $ git log -num
  24. # 显示commit历史,以及每次commit发生变更的文件,会列出具体文件列表
  25. $ git log --stat
  26. # 可以定制要显示的记录格式
  27. $ git log --pretty=format:"%an"
  28. # 显示每次提交所引入的差异
  29. $ git log -p
  30. # 显示指定文件是什么人在什么时间修改过
  31. $ 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【工作区和暂存区的状态查看】

  1. # 查看工作区和暂存区的状态
  2. $ git status
  3. # 以简短方式查看工作区和暂存区文件状态
  4. $ git status -s
  5. # 查看工作区和暂存区文件状态,包括被忽略的文件
  6. $ git status --ignored

git add【将工作区的文件添加到暂存区】

  1. # 添加指定文件到暂存区(追踪新增的指定文件)
  2. $ git add [file1] [file2] ...
  3. # 添加指定目录到暂存区,包括子目录
  4. $ git add [dir]
  5. # 添加当前目录的所有文件到暂存区(追踪所有新增的文件)
  6. $ git add .
  7. # 添加每个变化前,都会要求确认,对于同一个文件的多处变化,可以实现分次提交
  8. $ git add -p
  9. # 删除工作区/暂存区的文件
  10. $ git rm [file1] [file2] ...
  11. # 停止追踪指定文件,但该文件会保留在工作区
  12. $ git rm --cached [file]
  13. # 改名工作区/暂存区的文件
  14. $ git mv [file-original] [file-renamed]
  15. # -------------------------Git 2.0 以下版本--------------------------
  16. # 作用于文件的新增和修改
  17. $ git add .
  18. # 作用于文件的修改和删除
  19. $ gti add -u
  20. # 作用于文件的增删改
  21. $ 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 命令提示:
image.png
通过输入序列号或首字母可以选择相应的功能,具体的功能解释如下:

  • 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 会显示这些文件的当前内容与本地版本库中的差异,然后可以自己决定是否添加这些修改到暂存区,其中命令行提供的可操作方式解释如下:
image.png
具体解释如下:
image.png

git commit【将暂存区的更改提交至本地仓库】

  1. # 将暂存区的文件提交到本地仓库并添加提交说明
  2. $ git commit -m "本次提交的说明"
  3. # 不打开编辑器,直接在命令行中输入多行提交原因
  4. $ git commit -m '第一行提交原因' -m '第二行提交原因'
  5. # 提交暂存区的指定文件到仓库区
  6. $ git commit [file1] [file2] ... -m [message]
  7. # 提交工作区自上次commit之后的变化,直接到仓库区
  8. $ git commit -a
  9. # 提交时显示所有diff信息
  10. $ git commit -v
  11. # add 和 commit 的合并,便捷写法,将add和commit合为一步
  12. # 和 git add -u 命令一样,未跟踪的文件是无法提交上去的,将工作区修改或删除的文件提交到本地版本库,新增的文件不会被提交
  13. $ git commit -am "本次提交的说明"
  14. # 跳过验证继续提交
  15. $ git commit --no-verify
  16. $ git commit -n
  17. # 编辑器会弹出上一次提交的信息,可以在这里修改提交信息
  18. $ git commit --amend
  19. # 修复提交,同时修改提交信息,修改最新一条提交记录的提交原因
  20. $ git commit --amend -m "本次提交的说明"
  21. # 加入 --no-edit 标记会修复提交但不修改提交信息,编辑器不会弹出上一次提交的信息
  22. $ git commit --amend --no-edit
  23. # 重做上一次commit,并包括指定文件的新变化
  24. $ git commit --amend [file1] [file2] ...
  25. # 将当前文件改动提交到 HEAD 或当前分支的历史ID
  26. $ git commit -C HEAD

git commit —amend 既可以修改上次提交的文件内容,也可以修改上次提交的说明。会用一个新的 commit 更新并替换最近一次提交的 commit 。如果暂存区有内容,这个新的 commit 会把任何修改内容和上一个 commit 的内容结合起来。如果暂存区没有内容,那么这个操作就只会把上次的 commit 消息重写一遍。

git push、pull【拉取、推送】

分支推送顺序的写法是 <来源地>:<目的地>

  1. # 将本地仓库的文件推送到远程分支
  2. # 如果远程仓库没有这个分支,会新建一个同名的远程分支,如果省略远程分支名,则表示两者同名
  3. $ git push <远程主机名> <本地分支名>:<远程分支名>
  4. $ git push origin branchname
  5. # 如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支
  6. $ git push origin :master
  7. # 等同于
  8. $ git push origin --delete master
  9. # 建立当前分支和远程分支的追踪关系
  10. $ git push -u origin master
  11. # 如果当前分支与远程分支之间存在追踪关系,则可以省略分支和 -u
  12. $ git push
  13. # 不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机
  14. $ git push --all origin
  15. # 拉取所有远程分支到本地镜像仓库中
  16. $ git pull
  17. # 拉取远程仓库分支变化,并与本地分支合并
  18. $ git pull [remote] [branch]
  19. # 等同于 fetch + merge
  20. $ git fetch origin branchName
  21. $ git merge origin/branchName
  22. # 如果远程主机的版本比本地版本更新,推送时 Git 会报错,要求先在本地做 git pull 合并差异,
  23. # 然后再推送到远程主机。这时,如果你一定要推送,可以使用 –-force 选项(尽量避免使用)
  24. $ git push --force origin | git push -f origin

git branch【分支管理】

  1. # 查看本地分支,列出所有本地分支
  2. $ git branch | git branch -l
  3. # 查看远程分支
  4. $ git branch -r
  5. # 查看所有分支(本地分支+远程分支)
  6. $ git branch -a
  7. # 查看所有分支并带上最新的提交信息
  8. $ git branch -av
  9. # 查看本地分支对应的远程分支
  10. $ git branch -vv
  11. # 新建分支,在别的分支下新建一个分支,新分支会复制当前分支的内容
  12. # 注意:如果当前分支有修改,但是没有提交到仓库,此时修改的内容是不会被复制到新分支的
  13. $ git branch branchname
  14. # 修改当前分支名
  15. $ git branch -m branchname
  16. # 切换分支(切换分支时,本地工作区,仓库都会相应切换到对应分支的内容)
  17. $ git checkout branchname
  18. # 新建一个aaa分支,并切换到该分支(新建分支和切换分支的简写)
  19. $ git checkout -b aaa
  20. # 新建一个基于master分支的aaa分支,并切换到该分支
  21. $ git checkout -b aaa master
  22. # 新建一个分支,指向指定commit
  23. $ git branch [branch] [commit]
  24. # 新建一个分支,与指定的远程分支建立追踪关系
  25. $ git branch --track [branch] [remote-branch]
  26. # 建立追踪关系,在现有分支与指定的远程分支之间
  27. $ git branch --set-upstream [branch] [remote-branch]
  28. # 新建一条空分支
  29. $ git checkout --orphan emptyBranchName
  30. $ git rm -rf .
  31. # 删除本地分支,会阻止删除包含未合并更改的分支
  32. $ git brnach -d branchname
  33. # 强制删除一个本地分支,即使包含未合并更改的分支
  34. $ git branch -D branchname
  35. # 删除远程分支,推送一个空分支到远程分支,其实就相当于删除远程分支
  36. $ git push origin :远程分支名
  37. # 或者
  38. $ git push origin --delete 远程分支名
  39. $ git branch -dr [remote/branch]

分支合并

1. git merge【合并】

  1. # 默认fast-forward,HEAD指针直接指向被合并的分支
  2. $ git merge
  3. # 禁止快进式合并
  4. $ git merge --no-ff
  5. $ git merge --squash
  • fast-forward:会在当前分支的提交历史中添加进被合并分支的提交历史。
  • —no-ff:会生成一个新的提交,让当前分支的提交历史不会那么乱。
  • —squash:不会生成新的提交,会将被合并分支多次提交的内容直接存到工作区和暂存区,由开发者手动去提交,这样当前分支最终只会多出一条提交记录,不会掺杂被合并分支的提交历史。

2. git rebase【重新定义分支的版本库状态】

  1. $ git rebase branch_name

通过 rebase 合并分支跟 merge 很像,但还是有本质的区别,具体看下图:
image.png

git stash【将未提交的修改保存至堆栈】

git stash 能够将所有未提交的修改保存至堆栈中,用于后续恢复当前工作区内容。如果文件没有提交到暂存区的话,使用该命令会提示 No local changes to save,则无法将修改保存到堆栈中。

使用场景:
当接到一个修复紧急 bug 的任务时候,一般都是先创建一个新的 bug 分支来修复它,然后合并,最后删除。但如果当前正在开发功能中,短时间还无法完成,无法直接提交到仓库,这时候可以先把当前工作区的内容 git stash 一下,然后去修复 bug,修复后再 git stash pop,恢复之前的工作内容。

  1. # 将所有未提交的修改(提交到暂存区)保存至堆栈中
  2. $ git stash
  3. # 给本次存储加个备注,以防时间久了忘了
  4. $ git stash save "存储"
  5. # 存储未追踪的文件
  6. $ git stash -u
  7. # 查看栈中保存的列表
  8. $ git stash list
  9. # 恢复后,stash 记录并不删除
  10. $ git stash apply "stash@{index}"
  11. # 从Git栈中检出其中一条记录,但不从栈中移除
  12. $ git stash apply stash@{0}
  13. # 恢复的同时把 stash 记录也删了
  14. $ git stash pop "stash@{index}"
  15. # 把当前栈中最近一次记录检出并创建一个新分支
  16. $ git stash branch new_banch
  17. # 从Git栈中检出最新保存的一条记录,并将它从栈中移除
  18. $ git stash pop
  19. # 删除 stash 记录
  20. $ git stash drop "stash@{index}"
  21. # 移除栈中其中一条记录
  22. $ git stash drop stash@{0}
  23. # 删除所有存储的进度
  24. $ git stash clear
  25. # 为当前修改或删除的文件创建一个自定义的栈并返回一个ID,此时并未真正存储到栈里
  26. $ git stash create
  27. # 将 create 方法里返回的ID放到 store 后面,此时在栈里真正创建了一个记录,但当前修改或删除的文件并未从工作区移除
  28. $ git stash store xxxxxx
  29. # 查看当前记录中修改了哪些文件
  30. $ git stash show "stash@{index}"
  31. # 显示栈中其中一条记录
  32. $ git stash show stash@{0}
  33. # 查看当前记录中修改了哪些文件的内容
  34. $ git stash show -p "stash@{index}"

git diff【工作区和暂存区的文件对比】

  1. # 查看工作区和暂存区单个文件的对比
  2. $ git diff filename
  3. # 查看工作区和暂存区所有文件的对比
  4. $ git diff
  5. # 查看工作区和暂存区所有文件的对比,并显示出所有有差异的文件列表
  6. $ git diff --stat
  7. # 注意:
  8. # 1.你修改了某个文件,但是没有提交到暂存区,这时候会有对比的内容,一旦提交到暂存区,就不会有对比的内容(因为暂存区已经更新)
  9. # 2.如果你新建了一个文件,但是没有提交到暂存区,这时候diff是没有结果的
  10. # 查看暂存区与上次提交到本地仓库的快照(即最新提交到本地仓库的快照)的对比
  11. $ git diff --cached/--staged
  12. # 查看工作区与上次提交到本地仓库的快照(即最新提交到本地仓库的快照)的对比
  13. $ git diff branchname
  14. # 查看工作区与 HEAD 指向(默认当前分支最新的提交)的对比
  15. $ git diff HEAD
  16. # 显示两次提交之间的差异
  17. $ git diff [first-branch]...[second-branch]
  18. # 显示今天你写了多少行代码
  19. $ git diff --shortstat "@{0 day ago}"
  20. # 查看两个本地分支中某一个文件的对比
  21. $ git diff branchname..branchname filename
  22. # 查看两个本地分支所有的对比
  23. $ git diff branchname..branchname
  24. # 查看远程分支和本地分支的对比
  25. $ git diff origin/branchname..branchname
  26. # 查看远程分支和远程分支的对比
  27. $ git diff origin/branchname..origin/branchname
  28. # 查看两个 commit 的对比
  29. $ git diff commit1..commit2

git remote【远程仓库相关操作】

  1. # 查看所有远程主机
  2. $ git remote
  3. # 查看关联的远程仓库的详细信息
  4. $ git remote -v
  5. # 关联远程仓库
  6. $ git remote add <name> <git-repo-url>
  7. # 例如
  8. $ git remote add origin https://github.com/xxxxxx
  9. # 删除远程仓库的 “关联”
  10. $ git remote rm projectname
  11. # 设置远程仓库的 “关联”
  12. $ git remote set-url origin <newurl>
  13. # 下载远程仓库的所有变动
  14. $ git fetch [remote]
  15. # 显示某个远程仓库的信息
  16. $ git remote show [remote]

git rm、mv

  1. # 删除暂存区和工作区的文件
  2. $ git rm filename
  3. # 只删除暂存区的文件,不会删除工作区的文件
  4. $ git rm --cached filename
  5. # 将a.md重命名为b.md,同时添加变动到暂存区,加 -f 参数可以强制重命名
  6. # 相比用 mv a.md b.md 命令省去了 git add 操作
  7. $ git mv a.md b.md -f

如果在配置 .gitignore 文件之前就把某个文件上传到远程仓库了,这时候想把远程仓库中的该文件删除,此时配置 .gitignore 文件也没有用,因为该文件已经被追踪了,但又不想在本地删除该文件后再重新提交到远程仓库,这时候可以使用 git rm —cached filename 命令取消该文件的追踪,这样下次提交的时候,git 就不会再提交这个文件,从而远程仓库的该文件也会被删除。

git checkout【版本切换】

  1. # 恢复暂存区的指定文件到工作区
  2. $ git checkout <filename>
  3. # 恢复暂存区的所有文件到工作区
  4. $ git checkout .
  5. # 回滚到最近的一次提交
  6. # 如果修改某些文件后,没有提交到暂存区,此时的回滚是回滚到上一次提交
  7. # 如果是已经将修改的文件提交到仓库了,这时再用这个命令回滚无效,因为回滚到的是之前自己修改后提交的版本
  8. $ git checkout HEAD
  9. $ git checkout HEAD -- filename
  10. # 回滚到最近一次提交的上一个版本
  11. $ git checkout HEAD^
  12. # 回滚到最近一次提交的上2个版本
  13. $ git checkout HEAD^^
  14. # 切换分支,在这里也可以看做是回到项目「当前」状态的方式
  15. $ git checkout <当前正在使用的分支>
  16. # 切换到某个指定的 commit 版本
  17. $ git checkout <commit_id>
  18. # 切换指定 tag
  19. $ git checkout <tag>

在开发的正常阶段,HEAD 一般指向 master 或其他的本地分支,但当使用 git checkout 切换到指定的某一次提交的时候,HEAD 就不再指向一个分支了——它直接指向一个提交,HEAD 就会处于 detached 状态(游离状态)。

切换到某一次提交后,可以查看文件,编译项目,运行测试,甚至编辑文件而不需要考虑是否会影响项目的当前状态,所做的一切都不会被保存到主栈的仓库中。当想要回到主线继续开发时,使用 git checkout branchName 回到项目初始的状态,这时候会提示是否需要新建一条分支用于保留刚才的修改。

git reset【版本重设】

git reset [—hard|soft|mixed|merge|keep] [ 或 HEAD]
该命令用于将当前的分支重设到指定的 或 HEAD(如果不显示指定 ,默认是 HEAD ,即最新的一次提交),并且根据 [mode] 有可能更新索引和工作目录。

  1. # 从暂存区撤销特定文件,但不改变工作区。它会取消这个文件的暂存,而不覆盖任何更改
  2. $ git reset <fileName>
  3. # 重置暂存区最近的一次提交,但工作区的文件不变
  4. $ git reset
  5. # 等价于
  6. $ git reset HEAD (默认)
  7. # 重置暂存区与工作区,回退到最近一次提交的版本内容
  8. $ git reset --hard
  9. # 重置暂存区与工作区,回退到最近一次提交的上一个版本
  10. $ git reset --hard HEAD^
  11. # 将当前分支的指针指向为指定 commit(该提交之后的提交都会被移除),同时重置暂存区,但工作区不变
  12. $ git reset <commit>
  13. # 等价于
  14. $ git reset --mixed <commit>
  15. # 将当前分支的指针指向为指定 commit(该提交之后的提交都会被移除),但保持暂存区和工作区不变
  16. $ git reset --soft <commit>
  17. # 将当前分支的指针指向为指定 commit(该提交之后的提交都会被移除),同时重置暂存区、工作区
  18. $ git reset --hard <commit>
  19. # 重置当前HEAD为指定commit,但保持暂存区和工作区不变
  20. $ git reset --keep [commit]

git reset 有很多种用法,它可以被用来移除提交快照,尽管它通常被用来撤销暂存区和工作区的修改。不管是哪种情况,它应该只被用于本地修改——永远不应该重设和其他开发者共享的快照。

当用 reset 回滚到了某个版本后,那么在下一次 git 提交时,之前该版本后面的版本会被作为垃圾删掉。当回退到一个旧版本后,此时再用 git log 查看提交记录,会发现之前的新版本记录没有了。如果想恢复到新版本但又找不到新版本 commit_id 怎么办?

此时可以用 git reflog 查看历史命令,这样就可以看到之前新版本的 commit_id ,然后 git reset —hard commit_id 就可以回到之前的新版本代码。不过这种方式在别的电脑上是无法获取当前电脑上的历史命令的,所以这种方法不安全。万一电脑突然坏了,这时候就无法回到未来的版本。

git revert【版本撤销】

  1. # 生成一个撤销最近的一次提交的新提交
  2. $ git revert HEAD
  3. # 生成一个撤销最近一次提交的上一次提交的新提交
  4. $ git revert HEAD^
  5. # 生成一个撤销最近一次提交的上两次提交的新提交
  6. $ git revert HEAD^^
  7. # 生成一个撤销最近一次提交的上n次提交的新提交
  8. $ git revert HEAD~num
  9. # 生成一个撤销指定提交版本的新提交
  10. $ git revert <commit_id>
  11. # 生成一个撤销指定提交版本的新提交,执行时不打开默认编辑器,直接使用 Git 自动生成的提交信息
  12. $ git revert <commit_id> --no-edit

git revert 命令用来撤销某个已经提交的快照,和 reset 重置到某个指定版本不一样,它是在提交记录最后面加上一个撤销了更改的新提交,而不是从项目历史中移除这个提交,这避免了 Git 丢失项目历史。

撤销(revert)应该用在想要在项目历史中移除某个提交的时候。撤销(revert)被设计为撤销公共提交的安全方式,而重设(reset)被设计为重设本地更改。这两个命令的目的不同,它们的实现也不一样:重设完全地移除了一堆更改,而撤销保留了原来的更改,用一个新的提交来实现撤销。因此如果需要修复一个公共提交,最好是使用 git revert。