在开始前,让我们先来讲几个概念,这将更好的让我们理解接下来的内容:
工作区 我们正在编辑的内容就是在工作区,上图中的 workspace。
暂存区 我们将工作区的内容通过git add
命令就提交到了暂存区。 上图中的 index
本地仓库 我们将暂存区的内容通过git commit
就提交到了本地仓库。内容的修改从工作区 ==> 暂存区 ==> 本地仓库是顺序执行的。上图中的 repository
远程仓库 Git 是一个分布式管理工具,所以当我们将修改的内容提交到本地仓库后,就可以通过git push
命令推送到远程仓库与他人协作完成项目。
分支 分支可以理解为像树枝一样来管理我们的代码,分支很好的解决了多人协作的问题。当我们需要开发一个新的功能时,从稳定分支(通常是 master 或者 release)新建分支开发,当开发完成并测试通过后,再通过git merge
合并入稳定分支发布。
FAQ Git 配置 我们可以通过git config
命令来配置 Git,配置文件可以存放在以下三个不同的地方:
/etc/gitconfig
文件:系统中对所有用户都普遍适用的配置。若使用 git config
时用 --system
选项,读写的就是这个文件。
~/.gitconfig
文件:用户目录下的配置文件只适用于该用户。若使用 git config
时用 --global
选项,读写的就是这个文件。
当前仓库的 Git 目录中的配置文件(也就是工作目录中的 .git/config
文件):这里的配置仅仅针对当前仓库有效。每一个级别的配置都会覆盖上层的相同配置,所以 .git/config
里的配置会覆盖 /etc/gitconfig
中的同名变量。
在 Windows 系统上,Git 会找寻用户主目录下的 .gitconfig
文件。主目录即 $HOME
变量指定的目录,一般都是 C:\Documents and Settings\$USER
。此外,Git 还会尝试找寻 /etc/gitconfig
文件,只不过看当初 Git 装在什么目录,就以此作为根目录来定位。
用户信息配置 1 2 $ git config [--global] user.name "John Doe" $ git config [--global] user.email [email protected]
文本编辑器配置
查看配置信息 1 2 3 4 5 6 7 $ git config --list user.name =Scott Chacon user.email [email protected] color.status =auto color.branch =auto color.interactive =auto color.diff =auto
有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig 和~/.gitconfig),不过最终 Git 实际采用的是最后一个。
也可以通过git config user.name
方式直接查阅某个环境变量的设定。
工作区 怎样将工作区中的内容提交到暂存区?
我在工作区修改了一些文件用于调试,完成后想丢弃所有修改
我想丢弃某个文件的修改
我想暂存这些调试的代码
我想看看有哪些暂存的内容
我想将某个暂存的内容复制到工作区 1 $ git stash apply stash@ {n}
我想将某个暂存的内容剪切到工作区 1 $ git stash pop stash@{n}
我想删除某个暂存 1 $ git stash drop stash@ {n}
我想删除所有暂存内容
我想将 git 中的某个文件取消跟踪,并保留本地文件 1 $ git rm --cached [filename ]
已跟踪的文件也要每次 add 后 commit 吗? 不需要,可以使用 git commit -am 'msg'
合并两个命令
我回退到了某个提交,如何再重新回到最新的提交? git reflog
命令记录了你的操作记录,在这里你可以找到最新的提交,使用git reset [commit-id]
即可回到未来。
暂存区 我想将暂存区的文件还原到工作区
在git reset
中,有--mixed
(默认), --soft
,--hard
三个可选参数,它们间有什么区别呢?其实是他们的修改作用域不同,具体可看下表。需要注意的是,请谨慎使用--hard
,这会使你工作区的内容被覆盖!
工作区
暂存区
本地仓库
--soft
❌
❌
✅
--mixed
❌
✅
✅
--hard
✅
✅
✅
我想对比工作区域暂存区的某个文件差异
我想对比暂存区与仓库某个文件的差异 1 $ git diff --cached [filename]
我想比较工作区与本地仓库的差异
我想比较当前提价与某个历史提交的差异
本地仓库 怎么将远程仓库克隆到本地,并命名为proj? 1 $ git clone [repo_url ] [proj]
怎么更新本地仓库? 1 $ git fetch && git merge
子模块功能怎么用? 添加子模块
1 $ git submodule add url repo_name
初始化子模块
更新子模块
标签 我想查看所有的标签
我想列出1.8.5系列的标签
我要查看某个标签信息
怎么创建一个标签? 1 $ git tag -a [tagname] -m "message"
该形式是附注标签,包含了创建标签者姓名、email、时间以及标签信息。另外有一种轻量标签git tag [tagname]
,该标签类型由于包含了较少的信息,所以不被推荐。
怎么推送标签到远程仓库? 默认情况下,git push
命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到共享服务器上。
推送单个标签:
1 $ git push origin [tagname]
将所有不在远程仓库的标签全部推送:
怎么删除标签?
注意:该命令并不会从任何远程仓库中移除这个标签,你必须使用 git push [remote] :refs/tags/[tagname]
来更新你的远程仓库。
变基 变基的命令:git rebase -i [要修改 commit 的上一个 commit]
请注意!变基是一把利剑,合理的使用会让你的分支更加简洁和灵活,滥用则会导致分支的混乱。请谨慎使用 rebase,尤其是团队合作项目,因为它会修改历史信息,导致信息冲突 在危险操作前可以先在副本分支进行操作,确认结果是预期后再行操作。
变基的概念可能难以理解,你可以到这里 学习一下。
当我们使用git rebase -i 5f2452b2 8f33126c
调出了变基窗口时,会看到以下内容,请注意其中的 Commands 部分,每个命令后都有说明,我们只需要按照说明操作即可。如果不明白其实际动作和结果,请创建一个测试仓库演练一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 pick cacc52da add: qrcode pick f072ef48 update: indexeddb hack pick 4e84901a feat: add indexedDB floder pick 8f33126c feat: add test2.js
我想修改某次提交信息 r
我想将多个提交合并 s
我想删除某次提交 d
我想将 A 分支变基到 B 分支上(移花接木)
我想从每个commit移除一个文件 这经常发生。 有人粗心地通过 git add .
提交了一个巨大的二进制文件,你想要从所有地方删除它。 可能偶然地提交了一个包括一个密码的文件,然而你想要开源项目。 filter-branch
是一个可能会用来擦洗整个提交历史的工具。 为了从整个提交历史中移除一个叫做 passwords.txt
的文件,可以使用 --tree-filter
选项给 filter-branch
:
1 $ git filter -branch --tree-filter 'rm -f passwords.txt' HEAD
--tree-filter
选项在检出仓库的每一个提交后运行指定的命令然后重新提交结果。在本例中,你从每一个快照中移除了一个叫作 passwords.txt
的文件,无论它是否存在。通常一个好的想法是在一个测试分支中做这件事,然后当你决定最终结果是真正想要的,可以硬重置 master 分支。 为了让 filter-branch
在所有分支上运行,可以给命令传递 --all
选项。
我更换了邮箱,想修改历史提交的邮箱 1 2 3 4 5 6 7 8 9 $ git filter - branch if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ]; then GIT_AUTHOR_NAME= "Scott Chacon"; GIT_AUTHOR_EMAIL= "[email protected] "; git commit - tree "$@"; else git commit - tree "$@"; fi' HEAD
我想在所有分支删除某个文件,如 password.txt 1 git filter -branch --all --tree-filter 'rm -f passwords.txt' HEAD
变基冲突解决后我该做什么?
变基过程中我想放弃变基
分支 怎么切换分支? 1 $ git checkout [branch name ]
怎么切换到上一个分支?
我当前在test
分支,并想将ver1.0
合并到test
分支
我想取消合并
怎么查看已经合并的分支?
怎么查看还未合并的分支? 1 $ git branch --no -merged
我想新建一个分支 1 $ git branch [branch name]
我想新建并切换到新分支 1 $ git branch -b [branch name]
我想删除已合并的分支 1 $ git branch -d [branch name]
我想强制删除未合并的分支 1 $ git branch -D [brnach name]
我想将另一个分支的某次提交应用到当前分支 1 $ git cherry-pick [commit-id ]
怎么修改分支名? 1 $ git branch -m [old name ] [new name ]
怎么将本地分支与远程分支建立跟踪关系?
怎么查看远程分支?
我本地没有别人新推送的远程分支 请使用git fetch
命令更新一下
远程仓库名为origin,怎么将本地的 A 分支推送到远程并建立同名分支? 1 $ git push -u origin A:B
远程仓库名为origin,我想删除origin的分支B
我将 5 个提交推送到了远程仓库,但发现第3个提交需要撤回,我该如何操作? 此时,你应该使用git revert [commit-id]
,无论这个提交在log的哪个位置,都不会影响上下的提交,而且它会将撤销的作为一个新的提交,因此revert
命令主要用于推送到远程仓库的修改。
如果你使用了git reset
会有什么不同呢?
如果一个提交在log的中间位置,那么reset这个提交之后的提交有可能都会消失掉!尤其在多人协作中,你将后两个提交删除,并推送到远程,而别人本地还是 5 个提交,这将导致分支的混乱,请清楚你的每一步操作与后果,谨慎使用每个命令。
远程仓库 怎么查看所有关联的远程仓库名称
我想查看远程仓库的地址
我想将本地已有仓库与远程仓库关联 1 $ git remote add 本地远程仓库名 url|path
我想取消远程仓库的关联
我想重命名远程仓库 1 $ git remote rename [old name ] [new name ]
检索 我想在项目中查找某个关键词,并输出所在行号
我想查看搜索结果所属方法或函数
日志 git log
中有很多参数能够帮助我们增强筛选,常用的选项如下表
选项
说明
-p
按补丁格式显示每个更新之间的差异。
--stat
显示每次更新的文件修改统计信息。
--shortstat
只显示 –stat 中最后的行数修改添加移除统计。
--name-only
仅在提交信息后显示已修改的文件清单。
--name-status
显示新增、修改、删除的文件清单。
--abbrev-commit
仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。
--relative-date
使用较短的相对时间显示(比如,“2 weeks ago”)。
--graph
显示 ASCII 图形表示的分支合并历史。
--pretty
使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。
git log --pretty=format
常用的选项如下表:
选项
说明
%H
提交对象(commit)的完整哈希字串
%h
提交对象的简短哈希字串
%T
树对象(tree)的完整哈希字串
%t
树对象的简短哈希字串
%P
父对象(parent)的完整哈希字串
%p
父对象的简短哈希字串
%an
作者(author)的名字
%ae
作者的电子邮件地址
%ad
作者修订日期(可以用 –date= 选项定制格式)
%ar
作者修订日期,按多久以前的方式显示
%cn
提交者(committer)的名字
%ce
提交者的电子邮件地址
%cd
提交日期
%cr
提交日期,按多久以前的方式显示
%s
提交说明
限制 git log
输出的选项
选项
说明
-(n)
仅显示最近的 n 条提交
--since, --after
仅显示指定时间之后的提交。
--until, --before
仅显示指定时间之前的提交。
--author
仅显示指定作者相关的提交。
--committer
仅显示指定提交者相关的提交。
--grep
仅显示含指定关键字的提交
-S
仅显示添加或移除了某个关键字的提交
我想查看某次提交信息
我想查看某次提交修改的文件列表 1 $ git show --pretty ="" --name-only [commit-id]
查看某次提交的变更内容 1 $ git show --pretty ="" [commit-id]
我想查看某个文件的所有提交信息
我想查看最近两次的提交信息
我想查看某个文件的所有变动及统计信息 1 $ git whatchanged --stat [filename]
我想修改最近一次提交信息
某行代码有问题,我想查看谁最后修改了这里 1 $ git blame [-L start -line , end -line ] filename
我想查看某个用户在某个时间段内的所有提交,并仅输出简短hash与提交说明 1 $ git log --pretty ="%h - %s" --author =Rock --since ="2008-10-01" --before ="2008-11-01"
我想用图形的方式查看分支的变化
.gitignore
**/*.go
忽略所有目录中的扩展名为go的文件
*/*/temp*
忽略二级目录下以temp开头的所有文件
temp?
忽略以temp开头的文件名,如tempa
和tempb
!README.md
感叹号(!
)表示不忽略该文件
版本控制最佳实践 鼓励频繁提交 频繁提交,而不要等到代码没有问题了再一次性提交。对于可能损坏主干原则的代码,不要直接提交到主干,而是创建一个分支,在分支中频繁提交。
定义主干原则,并且坚守它 “主干的代码必须是可以发布并且不会产生bug的”,如果不能保证新增或修改的代码符合这一原则,就在分支提交代码。
不要把逻辑的修改和代码格式化操作混在一起 如果你做了一些代码格式化的操作,就单独提交这次修改,然后再做一些逻辑的修改后提交,这样可以在出现问题时容易追溯。
不相干的代码分开提交 也就是说不要在一次提交里修复两个bug
相关阅读
Git 常用命令总结