Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。官方文档链接:Git官方文档 。
本篇文章以GitHub为例,系统为Windows系统。不做特殊说明时,默认为在Git Bash命令行中进行操作,Git Bash软件的下载地址:下载链接 。
内容详细,包含各种初学者可能会遇到的问题和解决方案。既适合初学者,也适合有一定基础的用户。
全部内容包括:Git本地库和远程库的使用流程,IDE集成Git的使用流程,Git GUI使用流程;包括设置SSH key,设置多个SSH key,局域网内搭建Git远程仓库,合并冲突,减少冲突,撤销更改,版本回退,整理提交历史,设置忽略规则(配置.gitignore
文件),配置.gitattributes
文件,使用rebase合并分支,解决Git Bash命令行的中文乱码问题,解决换行符的替换问题,等等。
~
指根目录,即C:\Users\[username]\
。git config --global
)保存在根目录下的.gitconfig
文件中,可以使用笔记本进行查看和更改;进行的项目设置(git config
)保存在项目文件夹下的.git/config
文件中。/
,例如:D:\Work\Temp
在命令行中要写成 d/work/temp
。路径名和文件名不区分大小写,且可以用Tab
进行补全。options
,则可以添加-h
参数,查看帮助,如:git remote -h
。/
,众所周知,文件夹名称中不可能包含符号 /
,所以该符号表示该文件夹包含的子文件夹。page/images
的文件夹,代表page
文件夹下的images
文件夹。[filename]
都可以用 .
代替,代表当前目录所有文件。Windows系统下,Git Bash的中文乱码问题有很多种情况(下方有详细解释),其中一种是计算机内部资源中文乱码(情况1),还有一种是远程库资源乱码(情况2)。这2种乱码不能同时解决,只能选择其一,建议解决情况2,舍弃情况1,因为情况1的需求较小。
建议:
在整个项目中,项目的文件夹名称,文件名称,Commit Message,Merge Message,等等,尽量不要使用中文。全部用英文较好,否则可能会出现命令行乱码问题。(乱码问题对功能没有影响,但可能会影响项目成员对文件和提交历史的识别)
Windows系统本地的编码为GBK,而在Git Bash中,默认编码不是GBK,所以输出本地中文字符时会显示乱码。
例如:输入systeminfo
,会出现中文乱码,如下图:
解决方案:
命令行窗口右键Options -> Text
界面,Locale
改为zh_CN
,Character set
改为GBK
;点击Apply
和Save
。再输入命令就不是乱码了,如下图:
注意: 情况1和情况2只能解决1种,建议解决情况2。
非git命令
中文显示正常,如:ls
命令,等;但git命令
无法显示中文,如:git status -s
,等。如下图:
解决方案:
命令行窗口右键Options -> Text
界面,Locale
和Character set
为默认值(即空白);或Locale
改为zh_CN
,Character set
改为UTF-8
;点击Apply
和Save
。
并修改全局配置,在Git Bash中输入命令:
git config --global core.quotepath false
注意:
两种情况只能解决一种,建议解决情况2:远程库资源乱码,因为需求较大。
在Git GUI界面下可能出现中文乱码。
解决方案:
设置Git GUI的界面编码:
git config --global gui.encoding utf-8
若以上方案均无法解决乱码问题,则可以在Git Bash命令行中尝试以下设置:
git config --global i18n.commitencoding utf-8
git config --global i18n.logoutputencoding utf-8
export LESSCHARSET=utf-8
git checkout work
git pull
git commit -m
git checkout master
git pull
git merge work
git push
在分支解决冲突,可以避免主分支出现冲突问题而造成的代码混乱。
git checkout work
git pull
git commit -a
git checkout master
git pull
git checkout work
git merge master
git rebase master
(推荐)git checkout master
git merge work
git push
rebase操作可以把本地未push的分叉提交历史整理成直线;
rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
git rebase
git rebase -i HEAD~4
pick ccafe3b rename
pick 69683ef new
pick b733a55 temp
pick fca1d04 txt
# Rebase d7865be..fca1d04 onto d7865be (4 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop = remove commit
# l, label
要注意如下参数:# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop = remove commit
# l, label = label current HEAD with a name
# t, reset = reset HEAD to a label
# m, merge [-C | -c ] [# ]
按照以上参数修改提交记录:p ccafe3b rename
s 69683ef new
s b733a55 temp
s fca1d04 txt
git log
git merge
操作合并分支会让两个分支的每一次提交都按照提交时间(并不是push
时间)排序,并且会将两个分支的最新一次commit
点进行合并成一个新的commit
,最终的分支树呈现非整条线性直线的形式。
git rebase
操作实际上是将当前执行rebase
分支的所有基于原分支提交点之后的commit
打散成一个一个的patch
,并重新生成一个新的commit hash
值,再次基于原分支目前最新的commit
点上进行提交,并不根据两个分支上实际的每次提交的时间点排序,rebase
完成后,切到基分支进行合并另一个分支时也不会生成一个新的commit
点,可以保持整个分支树的完美线性。
先从 master 分支切出一个 feature1
分支,进行开发
git checkout -b feature
分支树如下图:
这时,你的同事完成了一次修改(hotfix
) ,并合并了 master
分支,此时 master
已经领先于你的 feature1
分支了:
此时,我们想要同步 master
分支的改动
方法一:merge方法
git(feature1): git merge master
若执行git log
命令,就会在记录里发现一些 merge
的信息,但我们想要保持一份干净的 commit
。这时候, git rebase
就派上用场了,详情见方法二。
方法二:rebase方法
git(feature1): git rebase master
从 commit
记录我们可以看出来, feature1
分支是基于 hotfix
合并后的 master
,自然而然的成为了最领先的分支,而且没有 merge
的 commit
记录,是不是感觉很舒服了。
补充一下rebase
的原理:
首先, git 会把 feature1
分支里面的每个 commit
取消掉;
其次,把上面的操作临时保存成 patch
文件,存在 .git/rebase
目录下;
然后,把 feature1
分支更新到最新的 master
分支;
最后,把上面保存的 patch
文件应用到 feature1
分支上;
在 rebase
的过程中,也许会出现冲突 conflict
。在这种情况, git 会停止 rebase
并会让你去解决冲突。在解决完冲突后,用 git add
命令去更新这些内容。
注意,你无需执行 git commit
,只要执行 continue
git rebase --continue
这样 git 会继续应用余下的 patch
补丁文件。
在任何时候,我们都可以用 --abort
参数来终止 rebase
的行动,并且分支会回到 rebase
开始前的状态。
git rebase --abort
在使用Git的过程中,我们喜欢有的文件比如日志,临时文件,项目配置文件,编译的中间文件等(如.idea
文件夹,config
文件等)不要提交到代码仓库,这时就要设置相应的忽略规则,来忽略这些文件的提交。
Git 忽略文件提交的方法有三种,忽略规则和语法会在后续提及,并详细介绍方法一,方式如下:
方法一(推荐): 在Git项目中定义 .gitignore 文件
这种方式通过在项目的某个文件夹下(通常在项目根目录下)定义 .gitignore
文件,在该文件中定义相应的忽略规则,来管理当前文件夹下的文件的Git提交行为。
.gitignore
文件是可以提交到共有仓库中的,这就为该项目下的所有开发者都共享一套定义好的忽略规则。
在 .gitignore
文件中,遵循相应的语法,在每一行指定一个忽略规则。
方法二: 在Git项目的设置中指定排除文件
这种方式只是临时指定该项目的行为,需要编辑当前项目下的 .git/info/exclude
文件,然后将需要忽略提交的文件写入其中。
需要注意的是,这种方式指定的忽略文件的根目录是项目根目录。
方法三: 定义Git全局的 .gitignore
文件
除了可以在项目中定义 .gitignore
文件外,还可以设置全局的 .gitignore
文件来管理所有Git项目的行为。这种方式在不同的项目开发者之间是不共享的,是属于项目之上Git应用级别的行为。
这种方式也需要创建相应的 .gitignore
文件,可以放在任意位置。然后在使用以下命令配置Git:
git config --global core.excludesfile ~/.gitignore
在项目根目录打开Git Bash命令行(即Git Bash Here)。
创建.gitignore
文件
touch .gitignore
编辑.gitignore
文件
vim .gitignore
示例内容:
# 忽略当前目录的bin文件夹
/bin/# 忽略当前目录的dir文件
/dir# 忽略所有的test.txt文件
test.txt# 忽略所有的html文件
*.html
保存.gitignore
文件
按Esc
键,然后输入:wq
即可。
官方文档链接:gitignore文档 。
#
开头表示注释,可以使用反斜杠进行转义;
/
开头表示当前目录,开头没有/
表示当前目录及子目录的所有匹配项;
/
结尾表示文件夹;
*
匹配多个字符;
**
匹配多级目录,可在开始,中间,结束;
?
匹配单个字符;
[]
包含单个字符的匹配列表;
!
表示追踪(不忽略,即添加)匹配到的文件或目录。
注意: git 对于 .gitignore
配置文件是按行从上到下进行规则匹配的。gitignore还可以指定要将哪些文件添加到版本管理中:唯一的区别就是规则开头多了一个感叹号,Git会将满足这类规则的文件添加到版本管理中;添加规则通常与其他忽略规则配合使用,以达到只添加一个文件夹中某一文件的效果。
在 .gitingore
文件中,每一行指定一个忽略规则,优先级按行从上到下;Git 检查忽略规则的时候有多个来源,它的优先级如下(由高到低):
从命令行中读取可用的忽略规则;
当前目录定义的规则;
父级目录定义的规则,依次地推;
$GIT_DIR/info/exclude
文件中定义的规则;
core.excludesfile
中定义的全局规则。
.gitignore
只能忽略那些原来没有被track
的文件,如果某些文件已经被纳入了版本管理中(即创建.gitignore
文件之前就push
了某一文件),那么即使你在.gitignore
文件中写入过滤该文件的规则,该规则也不会起作用,git仍然会对该文件进行版本管理。
解决方法就是先把本地缓存删除(改变成untrack
状态),然后再提交。(注意: 删除缓存后,合并分支时,本地文件可能会同步消失,所以在删除缓存前,建议先把要忽略的文件备份一下,防止文件丢失;若文件不重要,可有可无,则不必备份。)
删除本地缓存的命令如下:
删除所有文件
git rm -r --cached .
删除文件夹
git rm -r --cached [dirname]
删除某一文件
git rm --cached [filename]
提交命令如下:
git add .
git commit -m "update .gitignore"
说明
下文提到的当前目录
指:.gitignore
文件所在的目录。
常用规则
规则 | 作用 |
---|---|
/foo/ |
忽略当前目录的foo 文件夹 |
/foo/* |
忽略当前目录的foo 文件夹下的所有文件(包括子文件夹) |
*.zip !main.zip |
忽略所有.zip 文件但不忽略 main.zip 文件 |
/foo/do.c |
忽略某个具体文件 |
!/foo/one.txt |
追踪(不忽略,即添加)某个具体文件 若还有规则 /foo/ ,则该规则不生效 |
/foo/* !/foo/one.txt |
忽略foo 文件夹中所有内容但不忽略 /foo/one.txt |
/* !/foo /foo/* !/foo/bar |
忽略所有内容,除/foo/bar 文件夹 |
高级规则
规则 | 作用 |
---|---|
bin/ |
忽略所有路径下的bin文件夹,该文件夹下的所有内容都会被忽略,不忽略 bin 文件 |
/bin |
忽略当前目录下的bin文件或bin文件夹 (bin文件和bin文件夹在同一级目录下只能存在一个) |
/bin/ |
忽略当前目录下的bin文件夹 |
/bin/* |
忽略当前目录的bin文件夹下的所有文件 (包括子文件夹) |
/*.c |
忽略当前目录下所有的c文件,不忽略 build/cat.c |
debug/*.obj |
忽略所有的 debug/io.obj 不忽略 debug/common/io.obj 和 tools/debug/io.obj |
**/foo |
忽略/foo , a/foo , a/b/foo 等 |
a/**/b |
忽略a/b , a/x/b , a/x/y/b 等 |
!/bin/run.sh |
不忽略 bin 目录下的 run.sh 文件若还有规则 /bin/ ,则该规则不生效 |
/foo/* !/foo/one.txt |
忽略foo 文件夹中所有内容但不忽略 /foo/one.txt |
/* !/foo /foo/* !/foo/bar |
忽略所有内容,除/foo/bar 文件夹 |
*.log !change.log |
忽略所有 .log 文件但不忽略 change.log 文件 |
config.php |
忽略当前路径及子路径的 config.php 文件 |
注意
需要注意的是,gitignore还可以指定要将哪些文件添加到版本管理中:唯一的区别就是规则开头多了一个感叹号,Git会将满足这类规则的文件添加到版本管理中。
为什么要有两种规则呢?假设我们只需要管理/mtk/
目录中的one.txt
文件,这个目录中的其他文件都不需要管理。那么我们就需要使用:
/mtk/*
!/mtk/one.txt
值得一提的是,以下写法是错误的,添加规则会失效:
/mtk/
!/mtk/one.txt
如果我们只有过滤规则没有添加规则,那么我们就需要把/mtk/
目录下除one.txt
以外的所有文件都写出来,而此时,添加规则极大的方便了我们的需求。
Windows平台下使用git add
时,经常会出现如下提示:
warning: LF will be replaced by CRLF in [filename].
The file will have its original line endings in your working directory
解释: Windows系统上,默认换行符为CRLF,但使用Vim编辑器进行编辑的文件,其换行符为LF。当LF的文件添加为缓存时,由于Git默认开启了core.autocrlf
,所以缓存文件中的LF(Unix的换行符)将被CRLF(Windows的换行符)替换;但本地工作区的LF不会被CRLF替换。
补充: 在Notepad和Notepad++的底部状态栏可以分辨某一文件的换行符是LF还是CRLF。
在文本处理中,CR(CarriageReturn),LF(LineFeed),是不同操作系统上使用的换行符,具体如下:
回车符(\r
):回到一行的开头,用符号r表示,十进制ASCII代码是13,十六进制代码为0x0D
,回车(return);
换行符(\n
):另起一行,用n符号表示,ASCII代码是10,十六制为0x0A
, 换行(newline)。
所以我们在Windows系统编写文件的回车符应该确切来说叫做回车换行符(CRLF)。
应用情况
Dos和Windows平台: 使用回车(CR)和换行(LF)两个字符来结束一行,回车+换行(CR+LF,即CRLF),即\r\n
;
Mac 和 Linux平台(类Unix系统):只使用换行(LF)一个字符来结束一行,即\n
;(早期Mac每行结尾是回车CR 即\r
,后来Mac os x 也投奔了 Unix。)
许多 Windows 上的编辑器会悄悄把行尾的换行(LF)字符转换成回车(CR)和换行(LF),或在用户按下 Enter 键时,插入回车(CR)和换行(LF)两个字符。
影响
一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;
而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。
Linux保存的文件在windows上用记事本看的话会出现黑点。
由于编辑器的不同或者文件行尾的换行符在 Windows 下被替换了,一些细微的空格变化会不经意地混入提交,造成麻烦。虽然这是小问题,但它会极大地扰乱跨平台协作。
这些问题都可以通过一定方式进行转换统一,例如,在Linux下,命令unix2dos
是把Unix文件格式(LF)转换成Windows文件格式(CRLF),命令dos2unix
是把Windows格式(CRLF)转换成Unix文件格式(LF)。
工作原理
以下为配置项core.autocrlf
的工作原理:
file to commit -> repository -> checked out file
core.autocrlf | file to commit | repository | checked out file |
---|---|---|---|
true | x | LF | CRLF |
input | x | LF | LF |
false | x | x | x |
注意: x可以是LF或CRLF,但上表中,每一行的x是不变的。
Windows系统
1. 方法一:
Git 的 Windows 客户端基本都会默认设置 core.autocrlf=true
,只要保持工作区都是纯 CRLF 文件,编辑器用 CRLF 换行,就不会出现警告了(注意:Git Bash命令行中Vim命令编辑的文件为LF格式文件)。
此时,提交时转换为LF,检出时转换为CRLF。
设置方法:
git config --global core.autocrlf true
注意:--global
为全局配置,若只想为某一项目配置,省略--global
即可。
2. 方法二:
设置 core.autocrlf=false
取消此功能,把回车保留在版本库中,即本地库和远程库都是CRLF格式。若开发只在Windows上运行的项目,则可以考虑此方法。
也可以在本地库和远程库都使用LF格式(通过Notepad++可以实现LF和CRLF格式的转换,下文有详细介绍),在Windows系统也用LF换行。除了旧版的记事本(新版好像也支持LF),其他编辑器都可以正常编辑。
设置方法:
提交检出均不转换
git config --global core.autocrlf false
你也可以在文件提交时进行safecrlf
检查:
拒绝提交包含混合换行符的文件
git config --global core.safecrlf true
允许提交包含混合换行符的文件
git config --global core.safecrlf false
提交包含混合换行符的文件时给出警告
git config --global core.safecrlf warn
注意:Windows 上设置 core.autocrlf=false
,仓库里也没有配置 .gitattributes
,很容易引入 CRLF 或者混合换行符(Mixed Line Endings,一个文件里既有 LF 又有CRLF)到版本库,这样就可能产生各种奇怪的问题。
Unix系统
包括Linux,Mac等类Unix系统
如果使用以换行(LF)作为行结束符的类Unix系统,你不需要 Git 在检出文件时进行自动的转换。
然而当一个以CRLF作为行结束符的文件不小心被引入时,你肯定想让 Git 修正。 可以把 core.autocrlf
设置成 input
来告诉 Git 在提交时把CRLF转换成LF,检出时不转换:(这样在 Windows 上的检出文件中会保留CRLF,而在Unix系统上,以及版本库中会保留LF。)
设置方法:
提交时转换为LF,检出时不转换
git config --global core.autocrlf input
**注意:**Unix 最好不要设置 core.autocrlf
,因为这个配置算是为 Windows 平台特殊定制的;
该方案适用于各种系统(包括Windows和类Unix系统)
Git的.gitattributes
文件是一个文本文件,文件中的一行定义一个路径的若干属性。官方文档链接:gitattributes文档 。
格式
该文件以行为单位设置一个路径下所有文件的属性,格式如下:
要匹配的文件模式 属性1 属性2
模式匹配路径的规则与.gitignore
文件中的规则相同(详情请查看 1.5.3. 忽略规则配置语法 和 1.5.6. 忽略规则示例),少数例外情况除外:
path/
语法在属性文件中毫无意义;应改为使用path/**
。实例
*.txt text
# 对于.txt文件,标记为文本文件,并进行行尾规范化。
*.jpg -text
#对于`.jpg`文件,标记为非文本文件
*.vcproj text eol=crlf
#对于.vcproj文件,标记为文本文件,在文件入Git库时进行规范化,行尾转换为LF。在检测到出工作目录时,行尾自动转换为GRLF。
*.sh text eol=lf
#对于sh文件,标记为文本文件,在文件入Git库时进行规范化,即行尾为LF。在检出到工作目录时,行尾也不会转换为CRLF(即保持LF)。
*.py eol=lf
#对于py文件,只针对工作目录中的文件,行尾为LF。
属性
text
属性之外,还可以设置eol
属性或core.eol
配置变量。eol=lf
,入库时将行尾规范为LF,检出时禁止将行尾转换为CRLFeol=crlf
,入库时将行尾规范为LF,检出时将行尾转换为CRLF。hunk
头部显示的@@ -k,l +n,m @@
,告诉Git使用外部命令来生成差异,或者是在生成差异之前让Git将二进制文件转换为文本文件。优先级
/myproj/.git/info/attributes # git仓库中的属性
/myproj/my_path/.gitattributes # 当前目录(对于my_path中的文件)
/myproj/.gitattributes # 父目录(对于my_path中的文件)
统一设置
也可以为所有Git库设置统一的gitattributes文件:
git config --get core.attributesFile
git config --global --get core.attributesFile
Windows系统
1. 查看文件换行格式
在Notepad和Notepad++的底部状态栏可以分辨某一文件的换行符是LF还是CRLF。
2. 相互转换
需要先安装Notepad++软件,使用该软件打开文件,点击编辑 -> 文档格式转换 -> 转换为[CRLF/LF/CR]
。
Linux系统
在Linux下,命令unix2dos
是把Unix文件格式(LF)转换成Windows文件格式(CRLF),命令dos2unix
是把Windows格式(CRLF)转换成Unix文件格式(LF)。
使用Git大部分是多人协作的开发模式,所以一般远程库+本地库共同使用,先讲述一下远程库的使用流程,而远程库的流程自然包括本地库的使用流程。后面会单独介绍本地库的使用流程。
远程库使用流程包括新建远程仓库,配置开发者用户信息,设置SSH key,设置多个SSH key(可不设),检测是否成功配置SSH key,局域网内搭建Git远程仓库,将远程库克隆到本地,创建和切换分支,下拉代码,上传代码,合并分支,合并冲突,减少冲突,撤销更改,版本回退,整理提交历史,使用rebase合并分支,等等。具体流程如下:
基本流程指正常完成某一操作的最基本的流程。扩展流程指在某个特定条件下要执行的流程。
方式一(推荐): 借助网络平台建立远程仓库
通过Web端(如GitHub,DevCloud等)新建仓库与分支,方法请自行查询或探索。在网页端可以复制SSH地址或HTTPS地址。后续会使用该地址与远程库进行连接,详情见2.1.7. 连接远程仓库。
方式二: 局域网内搭建Git远程仓库
Windows环境下,在局域网开发有时不能连接到GitHub,因此需要建立一个公共的远程库供项目组使用。详情请见2.2.2. 局域网内搭建Git远程仓库。
git config --global user.name "username"
git config --global user.email "[email protected]"
以上为git全局的用户名和邮箱,不加--global
即配置当前仓库的信息。
HTTPS方式:适合初学者,操作简单,但使用较麻烦。
SSH方式(推荐):适合对电脑有一定基础的用户,配置较麻烦,但使用方便。
区别:使用https url克隆对初学者来说会比较方便,复制https url然后到git Bash里面直接用clone命令克隆到本地就好,但是每次pull
和push
代码都需要输入账号和密码,这也是https方式的麻烦之处。而使用SSH url克隆却需要在克隆之前先配置和添加好SSH key,配置好后,使用方便。
注意:若使用HTTPS方式,则可直接跳到2.1.7. 连接远程仓库,若使用SSH方式,则需要继续看2.1.4. 设置SSH key。
检查你电脑是否已经有 SSH key
cd ~/.ssh // 跳转到ssh文件夹
ls // 列出文件夹中的文件
若.ssh
文件夹不存在,则继续第2步创建SSH密钥;若存在 id_rsa.pub 或 id_dsa.pub 文件,则已存在SSH密钥,可以直接跳到第3步,或到第2步重置SSH密钥。
创建密钥
ssh-keygen -t rsa -C "yourEmail"
或
ssh-keygen -t rsa -C "yourEmail" -f ~/.ssh/[rsafilename]
-t
后接密钥类型,默认为rsa
,可省略;
-C
设置注释文字,比如邮箱。
-f
指定密钥文件存储文件名,可省略,省略后会在当前文件夹创建。
[rsafilename]
为rsa私钥文件的名称。
输入第1条命令后会提示输入文件名和密码,按3个回车即可,也可自定义文件名和密码;如果输入第2条命令,则直接提示输入密码,按2个回车或自定义密码即可。
复制SSH公钥
clip < ~/.ssh/id_rsa.pub
或
cat ~/.ssh/id_rsa.pub
将SSH公钥粘贴到 GitHub 对应的位置(以下2种)并点击确定。
GitHub最高权限的SSH:
右上角头像 -> Settings
-> SSH and GPG keys
-> New SSH key
;
仓库的SSH:
进入远程仓库 -> Settings
-> Deploy keys
-> Add deploy key
。
二者区别:
GitHub账户的SSH keys
,相当于这个账号的最高级key,只要是这个账号有的权限(任何项目),都能进行操作。
仓库的Deploy keys
,顾名思义就是这个仓库的专有key,用这个key,只能操作这个项目,其他项目都没有权限。
可只用默认的1个SSH key,不设多个,但当同时需要2个SSH的时候需要设置。因为GitHub的某一个SSH只允许一个账户或仓库使用,所以一个终端经常需要设置多个SSH。步骤如下:
创建另一个密钥
方法一:
ssh-keygen -t rsa -C "yourEmail" -f ~/.ssh/test_rsa
-f
直接指定文件路径及名称;之后的密码可以都是回车。
方法二:
ssh-keygen -t rsa -C "yourEmail"
不要一路回车,让你选择在哪里选择存放SSH key的时候写个名字,比如github_rsa
,之后的密码可以回车。
添加SSH密钥代理(临时)
该方式是临时性的,重启ssh-agent服务后需要重新输入;若要永久保存设置(推荐),则需要配置config
文件,详情见下一步,配置config文件,若配置了config
文件,则无需再添加SSH密钥代理。
添加SSH密钥代理步骤如下。
打开ssh-agent:
若为Windows系统,则命令为ssh-agent bash
若其他系统,命令为ssh-agent -s
或 eval $(ssh-agent -s)
添加私钥:
ssh-add ~/.ssh/test_rsa
配置config文件(推荐)
配置私钥对应的服务器,可永久保存配置,步骤如下。
创建文件:touch ~/.ssh/config
修改文件:vim ~/.ssh/config
插入:按字母“I
”,输入如下信息
# GitHub
Host github.com
HostName github.com
Preferredauthentications publickey
IdentityFile ~/.ssh/github_rsa
User NSJim
#TestRepository
Host test
HostName github.com
Preferredauthentications publickey
IdentityFile ~/.ssh/test_rsa
User NSJim
保存文件:按Esc
,然后输入":wq
";
或使用记事本修改。
变量说明:
Host
:可随意填写,方便自己记忆,是替换HostName
的变量,后续在添加remote(远程库)时还需要用到;
HostName
:远程库SSH地址的“git@
”与“:
”之间的域名(网站的或公司的,如GitHub的HostName
为github.com
);
IdentityFile
:填写对应的私钥文件及路径;
User
:用户名,可有可无,起标识作用。
配置完成后,在连接非默认帐号的github仓库时,远程库SSH地址要对应地做一些修改,把HostName
替换为Host
。例如:
git remote add orgin [email protected]:NSJim/test.git
要改为:
git remote add orgin git@test:NSJim/test.git
git clone [email protected]:NSJim/test.git
要改为:
git clone git@test:NSJim/test.git
复制SSH公钥
clip < ~/.ssh/id_rsa.pub
或
cat ~/.ssh/id_rsa.pub
将SSH公钥粘贴到GitHub对应的位置(2种,步骤3-4已提及)并点击确定
默认SSH key检测:
ssh -T [email protected]
然后输入yes
回车,若提示Hi, username!
则成功。
非默认SSH key检测(设有多个SSH key时):
ssh -T git@[Host]
Host
为 ~/.ssh/config
中的Host
,用来代替HostName
;若提示Hi, username!
则成功。
即本地库与远程库的连接,为后续进行代码的pull
和push
做准备。需要使用2.1.1. 新建远程仓库中的SSH地址或HTTPS地址。
方式一(推荐):将远程仓库clone到本地
git clone [url]
[url]
即远程库的SSH url
或HTTPS url
(地址),需从网页端的远程仓库复制。
方式二:本地仓库初始化并连接
该方式先进行本地仓库的初始化,然后再进行远程库连接,该方法略微麻烦,效果和方式一相同。优点是可以自定义本地仓库文件夹的名称,并可将仓库文件夹中的代码push
到远程库中。
(1) 移动到要初始化为仓库的文件目录中:cd [path]
(2) 本地仓库初始化(即将当前目录设置为git仓库):git init
(3) 添加远程仓库,命令如下:
git remote add [remotename] [url]
[remotename]
为自定义的远程库的名字,默认为origin
;[url]
为远程仓库的SSH地址或HTTPS地址。
(4) 设置上流分支
git branch -u [remotename]/[remotebranchname] [localbranchname]
或-u
的全称--set-upstream-to
:
git branch --set-upstream-to [remotename]/[remotebranchname] [localbranchname]
同
git branch --set-upstream-to=[remotename]/[remotebranchname] [localbranchname]
设置[remotename]
远程库的[remotebranchname]
分支作为本地当前分支[localbranchname]
的上游分支,一般情况下,[remotebranchname]
和[localbranchname]
相同。
若要执行push
操作,也可执行命令:
git push --set-upstream [remotename] [localbranchname]
将本地分支[localbranchname]
推送到[remotename]
远程库的[localbranchname]
分支。
(5) 示例:
cd /d/Work/Project
git init
git remote add origin [email protected]:WongJay/w3cschool.cn.git
git branch --set-upstream-to=origin/master master
git config user.name "username"
git config user.email "[email protected]"
以上为配置git仓库的用户名和邮箱,在与远程仓库交互时,会覆盖已配置的全局用户信息。若已经配置了全局的用户信息,也可不必配置仓库的用户信息,默认会调用全局用户信息。
cd [gitPath]
git branch
*
和高亮的为当前分支git branch [branchname]
git checkout [branchname]
git checkout -b [branchname]
git pull
即从服务器下载当前分支的最新版本到本地(只会下载有更新的文件,一般不会覆盖本地已修改的文件)。在开始工作时(进行更改前),上传代码前,合并分支前,都需要先进行git pull
。
若提示: 请指定要合并的分支,如下:
Please specify which branch you want to merge with.
解决方案:
有2个方案,在下方详细介绍。若是通过git init
新建的空仓库出现该提示,则需要先使用方案二(指定远程分支),之后在进行方案一(设置上游分支);其他情况直接使用方案一即可。
方案一(推荐): 设置上游分支
git branch -u [remotename]/[remotebranchname] [localbranchname]
或
git branch --set-upstream-to=[remotename]/[remotebranchname] [localbranchname]
[remotename]
为远程库名称,[remotebranchname]
为远程库分支,[localbranchname]
为本地分支,一般情况下,[remotebranchname]
和[localbranchname]
相同。
方案二: 指定远程分支
git pull [remotename] [branchname]
[remotename]
和[branchname]
的含义同上。
git status
查看项目当前的文件更新状态,也可以用git status -s
简洁显示,一般与git diff
命令配合使用,可省略。在任何时刻都可使用git status
或git status -s
命令查看状态。
git status -s的几种状态:
A (added)
:你本地新增的文件(服务器上没有)。
C (copied)
:文件的一个新拷贝。
D (deleted)
:你本地删除的文件(服务器上还在)。
M (modified)
:文件的内容或者mode被修改了,红色为修改过未被添加进暂存区的,绿色为已经添加进暂存区的。
R (renamed)
:文件名被修改了。
T (typed)
:文件的类型被修改了。
U (updated but unmerged)
:文件没有被合并(你需要完成合并才能进行提交)。
?
:未被git进行管理,可以使用git add file1把file1添加进git。
X
:未知状态(很可能是遇到了git的bug)
git add .
将所有文件添加到缓存,也可使用git add [file1] [file2]
单独添加文件。
注意:被add
的文件便可被git管理,没有被add
的文件不会被git管理。
git status -s
再次查看项目当前的文件更新状态,可省略。
git commit -m "[message]"
将缓存提交到本地仓库,[message]
为备注信息。若觉得每次都add
后才能commit
比较麻烦,可以使用git commit -am "[message]"
来跳过add
,但新文件和重命名文件不会被commit
。
注意:要提前配好git仓库的用户名和邮箱才能正常使用该命令。
git push
将本地库推送(即上传)到远程库
若提示: 没有上游分支,如下:
fatal: The current branch a has no upstream branch.
方案一(推荐): 设置上游分支
git push -u [remotename] [branchname]
或
git push --set-upstream [remotename] [branchname]
-u
为简写,--set-upstream
为全称。[remotename]
为远程库的别名,在6.1.1. 添加远程仓库中有详细解释。
将远程库[remotename]
的远程分支[branchname]
作为其上游分支;
方案二: 指定远程分支
git push [remotename] [branchname]
[remotename]
的含义同上。
指定推送到[remotename]
远程库的[branchname]
分支,但该方法下次还会出现fatal
提示。
git pull
git merge [branchname]
branchname
是要合并的分支名称,也可以在末尾添加-m "[message]"
参数。git push
由于该步骤比较常见,所以分类归到了基本流程当中,详情请查看2.1. 基本流程中的2.1.5. 设置多个SSH key。
可只用默认的1个SSH key,不设多个,但当同时需要2个SSH的时候需要设置。因为GitHub的某一个SSH只允许一个账户或仓库使用,所以一个终端经常需要设置多个SSH。
使用局域网开发有时不能连接到GitHub,因此需要建立一个公共的远程库供项目组使用。在Windows10系统环境下,步骤如下。
在公共服务器下创建远程仓库
公共服务器(局域网服务器)可以是局域网中任意一台电脑,当做Git的远程仓库来使用,创建的远程仓库为空仓库。可供其他电脑进行代码的pull
和push
。步骤如下。
(1) 创建一个文件夹,如public.git
mkdir public.git
(2) 进入该文件夹,建立裸仓库
git init --bare
设置网络访问权限
(1) 设置共享文件夹及共享权限
设置 public.git
为共享文件夹。右键文件夹 —> 属性 —> 共享 —> 高级共享;设置共享名,添加;设置权限,编辑组和用户名,默认为Everyone
,为Everyone
添加允许完全控制权限。
(2) 检测文件夹是否可访问
确认在本机文件管理器中通过共享文件夹路径 \\IP地址\共享文件夹名称
或 \\主机名称\共享文件夹名称
访问到,推荐使用IP地址,因为主机名可能出现重名冲突,而且速度更快,更精确。
IP地址
为本机(公共服务器)的IP地址,可通过Win10的 CMD命令提示符 的ipconfig
命令查看,对应的网络适配器的IPv4
地址即为本机的 IP地址。
主机名称
可以右键桌面的 此电脑 图标,点击属性可以查看。也可在Git bash
命令行中查看,@
前面的即为主机名。
注意: 共享文件夹名称可以与文件夹名称不同;共享文件夹路径的主机名称和共享文件夹名称不规范大小写;Git访问时,应该使用正斜杠 /
。
项目组成员连接局域网远程仓库
项目组成员在自己的机器(包括公共服务器本机)上,参照以下2种方法连接远程库,大家就可以通过Git一起工作了。 其他操作请参照 2. 远程库使用流程 。
注意:连接前要保证项目组都在同一局域网中,即项目组的机器与局域网公共服务器之间在 CMD命令提示符 中可以ping
通,命令为ping IP地址
;若无法ping通,则各机器不在同一局域网中,可通过 2.1.1. 新建远程仓库 中的 方式一:借助网络平台建立远程仓库 来搭建远程远程仓库。
方法一:添加远程库
(1) git remote add [remotename] [sharepath]
[remotename]
可以自定义,是远程库的别名,默认为 origin
[sharepath]
为共享文件夹路径,一般为//IP地址/共享文件夹名称
或//主机名称/共享文件夹名称
,推荐使用IP地址,因为主机名可能出现重名冲突,而且速度更快,更精确。
使用 git remote -v
命令查看一下设置远程库是否成功。
(2) 进入本地库,将本地代码push
到远程库
git push -u [remotename] master
-u
可以替换为全称--set-upstream
。[remotename]
的含义同上,但要注意2个命令中的[remotename]
要保持相同。该命令可同时设置好上游分支。
方法二:克隆远程库
通过克隆的方式将空的远程库克隆到本地,然后将项目文件拷贝到本地库,之后再将本地库push
到远程库。
git clone [sharepath]
[sharepath]
为共享文件夹路径,一般为//IP地址/共享文件夹名称
或//主机名称/共享文件夹名称
。推荐使用IP地址。
注意事项
(1) 密码保护
若共享设置中开启了密码保护,则项目组用户必须拥有公共服务器的用户账户(主机名)和密码(登录密码),才能访问共享文件夹。项目组成员在进行pull
和push
时需要填写用户账户和密码才能继续操作。
在控制面板\网络和 Internet\网络和共享中心\高级共享设置\所有网络\密码保护的共享
处,可以设置无密码保护的共享。
(2) 共享权限设置
共享文件夹的权限一定要设置好,方法请见上文的设置网络访问权限中的设置共享权限,否则项目组的其他用户没有写权限,则无法进行push
,会报如下错误。
error: remote unpack failed: unable to create temporary object directory
! [remote rejected] master -> master (unpacker error)
error: failed to push some refs
(3) 网络发现
若想更直观的看到网络中共享的文件夹,则可以开启网络发现功能,这样则可在文件资源管理器的网络中看到共享的主机。开启方法:控制面板\网络和 Internet\网络和共享中心\高级共享设置\相应的网络\
中,启用网络发现
,启用文件和打印机共享
。
若文件资源管理器中的网络没有其他计算机,则需要检查Windows功能Smb1.0
是否开启,开启方法:打开控制面板——程序与功能——启用或关闭windows功能——smb1.0/cifs 文件共享支持
,打上勾,并重启。
git branch -d [branchname]
git branch -D [branchname]
当git commit
时,若忘记填写-m
参数,命令行会提示
Please enter the commit message for your changes.
此时需要在vim编辑器中按 I
键填写message
,然后按Esc
键,输入:wq
,保存退出。
当git pull
或git merge
时,命令行可能会提示:
Please enter a commit message to explain why this merge is necessary.
此时,可以按 I
键编辑message
,也可以直接按Esc
键,输入:wq
,保存退出。
注意:git merge
可以有-m
参数,即:
git merge [branchname] -m "[message]"
当2人同时修改同一文件,并均已提交推送至不同的分支,进行分支合并时,会出现冲突。
需手动合并,打开冲突文件,显示格式如下:
<<<<<<< HEAD
123 789
456 123
789 456
=======
123 123
456 456
789 789
>>>>>>> [branchname]
HEAD
指当前所在分支,branchname
指要合并的分支名。
<<<<<<< HEAD
和 =======
之间为当前所在分支内容;=======
和 >>>>>>> [branchname]
之间为要合并的分支内容。
手动合并(即修改)结束后,要重新上传代码:
提交到缓存:git add .
提交到本地库:git commit -m “message”
推送到远程库:git push
合并冲突结束。
在使用git pull
或git merge
时,可能会出现如下错误:
error: Your local changes to the following files would be overwritten by merge:
[files]
Please, commit your changes or stash them before you can merge.
这种情况大多是由于修改了文件,然后没有及时提交到本地库或远程仓库中造成的冲突,工作中经常发生这种冲突。
解决方案有3种:
方案一(推荐):Stash方法
git stash
git pull
git stash pop
进行pop
操作后,可能会出现冲突,进行上一步骤的合并冲突操作即可。
说明:
git stash
:备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中。
git stash pop
:从Git栈中读取最近一次保存的内容,恢复工作区的相关内容。由于可能存在多个Stash的内容,所以用栈来管理,pop会从最近的一个stash中读取内容并恢复。
git stash list
:显示Git栈内的所有备份,可以利用这个列表来决定从那个地方恢复。
git stash clear
:清空Git栈。此时使用gitg等图形化工具会发现,原来stash的哪些节点都消失了。
方案二:放弃修改,直接覆盖
git reset --hard
git pull
方案三:手动备份
先备份好本地写好的代码,然后放弃本地修改,然后进行pull
或merge
,然后再把要修改的文件直接覆盖掉,然后再进行提交。
(1) 场景1:
当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时使用该命令:git checkout -- [file]
。
(2) 场景2:
当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改。分两步:第一步用命令git reset HEAD [file]
,就回到了场景1,第二步按场景1操作。
(3) 场景3:
已经提交了不合适的修改到版本库时,想要撤销本次提交,参考下一步骤,版本回退,不过前提是没有推送到远程库。
场景2示例:
所有文件取消添加缓存:git reset HEAD .
所有文件丢弃工作区修改:git checkout -- .
要注意命令后方有 .
,代表所有文件,也可单独列出某一文件。
Git允许我们在版本的历史之间穿梭,命令:git reset --hard commit_id
。
要回到过去,用git log
可以查看提交历史和commit_id
,以便确定回退版本。若要向下翻页,则按回车即可;要退出log
界面,按字母键Q
即可。
要重返未来,用git reflog
查看命令历史,以便确定要回到未来的哪个版本。
关于commit_id(版本号):
当前版本为HEAD
,上一个版本就是HEAD^
或HEAD~1
,上上一个版本就是HEAD^^
或HEAD~2
,当然往上100个版本写100个^
并不容易,所以可以写成HEAD~100
。
可以使用HEAD
或commit_id
进行版本回退。若记不清是上几个版本,可以使用git log
可以查看提交历史及对应的commit_id
,以便确定要回退到哪个版本。
版本号(commit_id
)没必要写全,前几位就可以了(一般四位就够了),Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。
示例:
返回当前版本(即撤销更改):git reset --hard
或git reset --hard HEAD
返回上一版本:git reset --hard HEAD^
返回特定版本:git reset --hard [commit_id]
Git也可仅适用本地库进行版本管理,不与远程库进行连接。本地库的版本管理不需要使用SSH key进行验证,也不需要进行clone,pull和push,即把远程库流程中的SSH key操作,clone,pull和push操作去掉即可变为本地库的流程。本地库使用流程如下:
本地仓库初始化(将当前目录设置为git仓库):git init
配置开发者的用户信息:
git config --global user.name "username"
git config --global user.email "[email protected]"
以上为git全局的用户名和邮箱,不加--global
即配置当前仓库的信息
创建和切换分支(初始化后默认为master分支):
(1) 查看已有分支():git branch
带*
和高亮的为当前分支
(2) 创建分支:git branch [branchname]
(3) 切换分支:git checkout [branchname]
切换前需先进行提交(commit)。
(4) 创建并切换分支:git checkout -b [branchname]
上传代码到本地库:
(1) git status
查看项目当前状态,也可以用git status -s
简洁显示,一般与git diff
命令配合使用,也可不查看状态直接进行git add
。可在任何时刻使用git status
或git status -s
命令查看状态。
(2) git add .
将所有文件添加到缓存,也可使用git add [file1] [file2]
单独添加文件。
注意:被add
的文件便可被git管理,没有被add
的文件不会被git管理。
(3) git commit -m "message"
将缓存提交到本地仓库,message
为备注信息。若觉得每次都add
后才能commit
比较麻烦,可以使用git commit -am "message"
来跳过add
,但新文件和重命名文件不会被commit
。
注意:要提前配好git仓库的用户名和邮箱才能正常使用该命令。
合并分支:
(1) 切换到主分支
(2) 合并分支:git merge [branchname]
branchname
是要合并的分支名称
合并冲突
在远程库的使用流程中也涉及,此处不再重复。
扩展流程同远程库的扩展流程,这里不再赘述,内容如下:
目前很多的IDE(Integrated Development Environment,集成开发环境)都已经集成了Git,如JetBrains IDEA,Visual Studio,微信开发者工具,等等。用户不需要想以前一样只能使用命令行进行代码的版本控制与合作,而是可以在IDE的图形化界面中操作。
当然,即使IDE集成了Git,我们也可以使用Git Bash命令行进行操作,二者互不影响,可以同时使用。下面我以JetBrains的IDEA为例,进行一些基础的讲解,其他软件的操作方法类似。更深入的操作和使用方法可以自行探索。
git config --global user.name "username"
git config --global user.email "[email protected]"
--global
即配置当前仓库的信息。File/Configure -> Settings -> Version Control -> Git
,在Path to Git executable中选择上一步Git Bash安装目录中的cmd文件夹下的git.exe
文件。点击右侧的Test,会弹出Git Executed Successfully
提示框。如下图:File -> Setting -> Version Control -> GibHub
中,Host
填写github.com
,点击Create API Token
,输入在GitHub中注册的用户名和密码,然后会自动生成Token
。点击Test,测试是否连接成功。如下图。使用时与远程仓库的使用流程大同小异,只是把命令行操作换成了图形化界面而已。其使用流程也分为2个方式,建立本地库和克隆远程库2种。
IDEA软件的工作目录中:
红色代表未被Git管理;
绿色代表以添加到缓存;
白色代表已提交至本地库;
蓝色代表已修改。
VCS -> Import into Version Control -> Create Git Repository
,然后选择相应的项目目录。之后工作目录的文件会变红。VCS -> Git -> Remote
,或右键项目Git -> Repository -> Remote
,点击右侧的加号,填写Name
和URL
,Name
默认为Origin
,URL
为远程仓库地址,可以是HTTPS
或SSH
方式。Git -> add
,或快捷键Ctrl+Alt+A
,将文件添加到Git缓存。Git -> Commit Directory
,或快捷键Ctrl+K
,或点击软件右上方的Commit按钮;输入Commit Message
,若想节省时间,可以取消勾选Porform code analysis
和Check TODO
。Commit
,或下拉箭头中的Commit and Push (Ctrl+Alt+K)
,即可完成提交或推送。如下图:Git -> Repository -> Pull
,选择相应的Remote
,Branch
,Strategy
,之后点击Pull
即可。Update Project (Ctrl+T)
,选择相应的Update Type
,点击OK
即可。Git:
后面会显示当前分支,点击此处,可以显示所有分支并进行切换(checkout
即为切换),也可进行创建新分支,删除分支等操作。如下图:Git -> Repository -> Merge Changes
。add
,commit
和push
。Git -> Repository -> Stash Changes
。Git -> Repository -> Unstash Changes
。Git -> Show History
,即可查看提交历史。Git -> Repository -> Reset HEAD
,在To commit
中填写HEAD^
或HEAD~1
进行版本回退,点击Validate
按钮可以查看回退的版本信息。HEAD
,上一个版本就是HEAD^
或HEAD~1
,上上一个版本就是HEAD^^
或HEAD~2
,当然往上100个版本写100个^
并不容易,所以可以写成HEAD~100
。从远程库克隆代码
在IDEA的Welcome界面,选择Check out from Version Control -> Git
,然后填写URL
和Directory
,URL
为远程库地址,可以是HTTPS
或SSH
方式。Directory
为项目路径,必须是空文件夹。点击Clone
即可克隆代码。
在IDEA的项目界面下,VCS -> Git -> Clone
或右键项目Git -> Repository -> Clone
,可同样进入Clone
界面。
其他操作
其他操作与上一方式(建立本地库方式)相同。
由于Git GUI的使用流程的原理与Git Bash相同,且操作方式与IDE集成的Git极其相似,因而在此不进行详细介绍,感兴趣的可以查看另一个博主的一篇博客:Git GUI的使用 。
打开Git GUI的方法:
在文件资源管理器中右键,点击Git GUI here
即可。
若使用SSH方式则需要先配置SSH key;若使用HTTPS方式则需要在后续使用时输入HTTPS凭据的账户和密码。以下为添加远程库命令。
git remote add [remotename] [url]
[remotename]
为自定义的远程库别名,默认为origin
;
[url]
为远程仓库的SSH地址或HTTPS地址。
示例:
git remote add origin [email protected]:WongJay/w3cschool.cn.git
git remote
git remote -v
执行时加上 -v 参数,你还可以看到每个别名的实际链接地址。
git fetch [remotename] [branch]
git merge [remotename] [branch]
git merge
远程分支到你所在的分支。在已经设置上流分支的情况下可省略 [remotename]
和 [branch]
。git pull [remotename] [branch]
git fetch
之后紧接着执行 git merge
远程分支到你所在的任意分支。在已经设置上流分支的情况下可省略 [remotename]
和 [branch]
。git push [remotename] [branch]
以上命令将你的 [branch]
分支推送成为 [remotename]
远程仓库上的 [branch]
分支。在已经设置上流分支的情况下可省略 [remotename]
和 [branch]
。
注意:同一分支才可push
,不同分支需要merge
,实例如下。
git push origin master
git remote rm [remotename]
git config -l
git config user.name
git status
git status -s
A (added)
:你本地新增的文件(服务器上没有)。C (copied)
:文件的一个新拷贝。D (deleted)
:你本地删除的文件(服务器上还在)。M (modified)
:文件的内容或者mode被修改了,红色为修改过未被添加进暂存区的,绿色为已经添加进暂存区的。R (renamed)
:文件名被修改了。T (typed)
:文件的类型被修改了。U (updated but unmerged)
:文件没有被合并(你需要完成合并才能进行提交)。?
:未被git进行管理,可以使用git add file1把file1添加进git。X
:未知状态(很可能是遇到了git的bug)git diff
执行 git diff
来查看执行 git status
的结果的详细信息。
git diff
命令显示已写入缓存与已修改但尚未写入缓存的改动的区别。
git diff
git diff --cached
git diff HEAD
git diff --stat
git branch -d [branchname]
git branch -D [branchname]
git add [filename] [filename2]
filename
为文件的路径及名称,可使用相对路径,文件夹符号使用“/
”。git checkout -- [filename]
git reset HEAD [filename]
git rm [filename]
git rm file
会将文件从缓存区和你的硬盘中(工作目录)删除。 如果要在工作目录中留着该文件,可以使用命令: git rm --cached [filename]
。git rm -r [dirname]
git log
git relog
git rebase
git rebase -i HEAD~4
git rebase master
git stash
:备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中。git stash pop
:从Git栈中读取最近一次保存的内容,恢复工作区的相关内容。由于可能存在多个Stash的内容,所以用栈来管理,pop会从最近的一个stash中读取内容并恢复。git stash list
:显示Git栈内的所有备份,可以利用这个列表来决定从那个地方恢复。git stash clear
:清空Git栈。此时使用gitg等图形化工具会发现,原来stash的哪些节点都消失了。