- 新建 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。
