admin管理员组文章数量:1571773
Git使用流程及技巧 - 详细教程
- 前言
- 1. 技巧汇总
- 1.1. 基础技巧
- 1.2. 提升SSH传输速度
- 1.3. 解决Git Bash命令行的中文乱码问题
- 情况1:内部资源乱码
- 情况2:远程库资源乱码(推荐解决)
- 情况3:GUI界面乱码
- 其他情况:包括Linux
- 1.4. 解决冲突的方式和流程(减少冲突)
- 主分支解决冲突
- 分支解决冲突(推荐)
- 1.5. 使用rebase整理提交历史
- 拉取代码
- 直线变基
- 合并提交
- 修改提交
- 删除提交
- 合并分支
- 1.6. 设置忽略规则
- 三种忽略方法
- gitignore使用流程
- 忽略规则配置语法
- 忽略规则优先级
- 忽略规则不生效
- 忽略规则示例
- 解决忽略冲突
- 1.7. git lfs管理大文件
- 安装
- 配置
- 拉取文件
- 追踪文件
- 使用流程
- 1.8. 解决换行符的替换问题
- 问题
- 分析
- 解决方案
- 配置 .gitattributes文件
- LF与CRLF格式相互转换
- 1.9. git提示host key不匹配
- 1.10. add时提示does not have a commit checked out
- 1.11. git报错可疑所有权
- 1.12. 局域网内搭建Git远程仓库
- 2. 远程库使用流程
- 2.1. 基本流程
- 新建远程仓库
- 配置Git
- 连接远程仓库的方式
- 设置SSH key(默认只设1个)
- 设置多个SSH key(可省略)
- 检测是否成功配置SSH key
- 连接远程仓库
- 配置开发者的仓库用户信息
- 分支操作
- 下拉代码
- 推送代码
- 合并分支
- 2.2. 扩展流程
- 设置多个SSH key
- 删除分支
- 输入信息
- 查看提交记录
- 修改提交
- 删除提交
- 转移提交
- 提交造成合并冲突
- 本地修改未提交造成合并冲突
- 暂存代码
- 取消暂存区/取消add
- 撤销更改
- 版本回退
- 标签操作/tag
- 切换操作/switch
- 子模块/submodule
- 3. 本地库使用流程
- 3.1. 基本流程
- 3.2. 扩展流程
- 4. IDE集成Git使用流程
- 4.1 介绍
- 4.2 IDE与Git连接
- 4.3. 集成Git使用流程(图形化操作)
- 工作目录的状态
- 建立本地库方式
- 克隆远程库方式
- 5. Git GUI使用流程
- 6. 常用命令
- 6.1. 远程仓库命令
- 添加远程库
- 查看当前的远程仓库
- 提取远程仓库
- 推送到远程仓库
- 删除远程仓库
- 6.2. 其他命令
- 查看用户配置信息
- 状态
- 显示改动
- 分支
- 缓存
- 提交记录
- 重定基底(rebase)
- Git栈(stash)
- 7. 团队开发流程
- 私有仓库开发流程
- 说明
- 分支命名规则
- 开发流程
- 开源仓库开发流程
- 说明
- 开发流程
- 更新派生仓库
- 远程仓库从上游仓库切换为派生仓库
前言
Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。官方文档链接:Git官方文档 。
本篇文章以GitHub为例,系统为Windows系统。不做特殊说明时,默认为在Git Bash命令行中进行操作,Git Bash软件的下载地址:下载链接 。
内容详细,包含各种初学者可能会遇到的问题和解决方案。既适合初学者,也适合有一定基础的用户。
全部内容包括:Git本地库和远程库的使用流程,IDE集成Git的使用流程,Git GUI使用流程;包括设置SSH key,设置多个SSH key,局域网内搭建Git远程仓库,合并冲突,减少冲突,撤销更改,版本回退,整理提交历史,设置忽略规则(配置.gitignore
文件),配置.gitattributes
文件,使用rebase合并分支,提升SSH传输速度,解决Git Bash命令行的中文乱码问题,解决换行符的替换问题,等等。
1. 技巧汇总
1.1. 基础技巧
- 打开Git命令行:Git Bash的快捷方式或在文件资源管理器中右键Git Bash Here。
- 命令行中的基础操作同Linux命令行,如创建文件夹,Vim命令等。关于Linux的命令行基础命令和用法,详情请参见W3CSchool的教程网站:Linux教程。
- 命令行中的
~
指根目录,即C:\Users\[username]\
。 - 在命令行中进行的全局设置(
git config --global
)保存在根目录下的.gitconfig
文件中,可以使用笔记本进行查看和更改;进行的项目设置(git config
)保存在项目文件夹下的.git/config
文件中。 - 命令行中的文件目录使用符号
/
,例如:D:\Work\Temp
在命令行中要写成d/work/temp
。路径名和文件名不区分大小写,且可以用Tab
进行补全。 - 命令行中,单引号可以代替双引号,但一定要左右匹配,且为英文标点符号。
- 命令行中,若忘记命令的使用方法或
options
,则可以添加-h
参数,查看帮助,如:git remote -h
。 - Git连接远程库有2种方式:HTTPS和SSH(推荐),正文有详细介绍。
- 在整个项目中,项目的文件夹名称,文件名称,Commit Message,Merge Message,等等,尽量不要使用中文。全部用英文较好,否则可能会出现命令行乱码问题。(乱码问题对功能没有影响,但可能会影响项目成员对文件和提交历史的识别)
- 当GitHub仓库的上传文件接口不起作用时,可能是浏览器的兼容问题,可以试试谷歌或火狐浏览器。
- 在GitHub平台的项目仓库中,文件夹名称中可能会出现斜杠符号
/
,众所周知,文件夹名称中不可能包含符号/
,所以该符号表示该文件夹包含的子文件夹。
举一个例子:名称为page/images
的文件夹,代表page
文件夹下的images
文件夹。 - 本篇文章中,所有的
[filename]
都可以用.
代替,代表当前目录所有文件。
1.2. 提升SSH传输速度
在使用 SSH 方式在GitHub上进行代码托管时,一般速度会很慢,可以修改Git软件的配置,即关闭GSS API校验来提升速度,解决方案如下。
解决方案
以Windows 10系统为例:
- 找到Git软件的安装目录,例如:
D:\Program Files\Git
。 - 进入
etc\ssh
目录,找到ssh_config
文件,使用Notepad打开。 - 将
GSSAPIAuthentication no
前面的注释#
删掉,或新增一行GSSAPIAuthentication no
,保存文件。 - 再次使用ssh命令操作GitHub项目,可以体验到速度的提升,本人从
100k/s
变为5M/s
,速度提升50倍。
若无法找到Git软件安装目录,可以右键快捷方式,选择打开文件位置
。
也可以使用vim
命令编辑ssh_config
文件,方法如下:
- 右键文件资源管理器点击
Git Bash here
,打开git命令行。 - 编辑
ssh_config
文件:vim /etc/ssh/ssh_config
。 - 找到
GSSAPIAuthentication no
配置项。 - 配置方法同上。
1.3. 解决Git Bash命令行的中文乱码问题
Windows系统下,Git Bash的中文乱码问题有很多种情况(下方有详细解释),其中一种是计算机内部资源中文乱码(情况1),还有一种是远程库资源乱码(情况2)。这2种乱码不能同时解决,只能选择其一,建议解决情况2,舍弃情况1,因为情况1的需求较小。
建议:
在整个项目中,项目的文件夹名称,文件名称,Commit Message,Merge Message,等等,尽量不要使用中文。全部用英文较好,否则可能会出现命令行乱码问题。(乱码问题对功能没有影响,但可能会影响项目成员对文件和提交历史的识别)
情况1:内部资源乱码
Windows系统本地的编码为GBK,而在Git Bash中,默认编码不是GBK,所以输出本地中文字符时会显示乱码。
例如:输入systeminfo
,会出现中文乱码,如下图:
解决方案:
命令行窗口右键Options -> Text
界面,Locale
改为zh_CN
,Character set
改为GBK
;点击Apply
和Save
。再输入命令就不是乱码了,如下图:
注意: 情况1和情况2只能解决1种,建议解决情况2。
情况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:远程库资源乱码,因为需求较大。
情况3:GUI界面乱码
在Git GUI界面下可能出现中文乱码。
解决方案:
设置Git GUI的界面编码:
git config --global gui.encoding utf-8
其他情况:包括Linux
若以上方案均无法解决乱码问题,则可以在Git Bash命令行中尝试以下设置:
git config --global i18nmitencoding utf-8
git config --global i18n.logoutputencoding utf-8
export LESSCHARSET=utf-8
1.4. 解决冲突的方式和流程(减少冲突)
详情请见2.2 修改已提交造成合并冲突章节和2.2 本地修改未提交造成合并冲突章节。
主分支解决冲突
- 去自己的工作分支
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
1.5. 使用rebase整理提交历史
拉取代码
rebase
用于本地拉取代码时,和git pull
的作用类似。
git pull
将从远程仓库拉取最新的更改并将其merge
到当前分支。git rebase
会将当前分支的提交按照指定的基底重新应用在另一个分支上,从而产生一个线性的提交历史。相对于merge
,rebase
产生的历史更加清晰,没有多余的合并提交。
使用rebase
拉取代码的用法如下:
git fetch
git rebase
# 强制变基
git rebase -f
若想拉取所有仓库的所有分支,可使用--all
参数:
git fetch --all
若没有建立上游分支,则需要指定远程分支名称,用法如下:
git fetch [remote_name remote_branch]
git rebase [remote_name/remote_branch]
其中,remote_name
为远程仓库名称,默认为origin
;[remote_branch]
为远程分支名称,默认为master
。
若有以下不能变基提示,则先commit
再rebase
即可。
不能变基:您有未暂存的变更
直线变基
rebase操作可以把本地未push的分叉提交历史整理成直线,目的是使得我们在查看历史提交的变化时更容易。
将提交历史整理成一条直线:
git rebase
合并提交
首先查看提交记录:
git log --oneline
合并提交:
# 合并到指定版本,不包含此版本
git rebase -i [commit_id]
# 从HEAD版本开始往过去数[num]个版本
git rebase -i HEAD~[num]
合并示例
# 查看提交记录
$ git log --oneline
ccafe3b edit
69683ef new
b733a55 temp
fca1d04 txt
6b6d3fc init
# 合并最近的4条提交,即合并 edit - txt
# 通过commit_id合并时,要指定合并提交之前的一个提交,即合并提交不包含指定提交
$ git rebase -i 6b6d
# or
$ git rebase -i HEAD~4
此时会自动进入 vim 编辑模式:
pick ccafe3b edit
pick 69683ef new
pick b733a55 temp
pick fca1d04 txt
# Rebase d7865be..fca1d04 onto d7865be (4 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
按照注释内容修改提交记录,将要合并提交的pick
修改为s
:
p ccafe3b edit
s 69683ef new
s b733a55 temp
s fca1d04 txt
修改后进行保存,会自动进入提交信息编辑页面。
输入提交信息并保存,会自动变基合并提交。
合并提交后可查看结果:
git log --oneline
补充:常见的rebase指令如下:
# 合并
s
# 删除
d
# 修改
e
修改提交
操作步骤同合并提交,首先查看提交记录:
git log [--oneline]
修改提交:
# 修改指定提交,commit_id为指定提交的前一个提交
git rebase -i [commit_id]
# 将指定提交的pick修改为e,保存退出
# 可修改代码
git add .
git status -s
# 重新提交,可修改提交信息
git commit --amend
# 继续变基
git rebase --continue
删除提交
操作步骤同合并提交:
# 查看提交记录
git log [--oneline]
# 删除指定提交,commit_id为指定提交的前一个提交
git rebase -i [commit_id]
# 将指定提交的pick修改为d,保存退出
# 保存退出后会自动变基删除指定提交
合并分支
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
1.6. 设置忽略规则
在使用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
gitignore使用流程
-
在项目根目录打开Git Bash命令行(即Git Bash Here)。
-
创建
.gitignore
文件touch .gitignore
-
编辑
.gitignore
文件vim .gitignore
示例内容:
# 忽略当前目录的dir文件夹 /dir/ # 忽略所有目录的dir文件夹 dir/ # 忽略当前目录的file文件 /file # 忽略所有目录的file文件 file # 忽略所有目录的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
以外的所有文件都写出来,而此时,添加规则极大的方便了我们的需求。
解决忽略冲突
Git的本地忽略设置,即.gitignore
文件,必须保证Git的远程仓库分支上没有要忽略的文件,若远程分支上存在要忽略的文件,则本地忽略无效,即便在.gitignore
里设置了忽略规则也不会生效。
解决方案1(推荐)
该方案无需在Git远程仓库平台online删除源码文件,步骤如下:
- 先将要忽略的文件在本地备份
- 在本地删除要忽略的文件
- 通过Git Bash推送(push)本地代码到远程仓库
- 创建
.gitignore
文件并写入忽略规则 - 拷贝本地备份的忽略文件到本地原位置
- 打开IDE查看git操作是否正常,下次commit便不会提交忽略文件了
解决方案2
由于Git远端仓库平台,如github、gitee、等等,它们都支持online删除源码文件。因此也可使用如下步骤:
- 先将要忽略的文件在本地备份
- 在远程仓库分支上删除要忽略的文件
- 通过Git Bash拉取(pull)远程库的代码
- 创建
.gitignore
文件并写入忽略规则 - 拷贝本地备份的忽略文件到本地原位置
- 打开IDE查看git操作是否正常,下次commit便不会提交忽略文件了
1.7. git lfs管理大文件
安装
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
sudo apt install git-lfs
配置
# LFS全局配置
git lfs install
# 取消LFS全局配置
git lfs uninstall
拉取文件
# 全部拉取
git lfs pull --include "*" --exclude ""
# 单文件拉取
git lfs pull --include "dir/file" --exclude ""
# 多文件拉取
git lfs pull --include "*.onnx,*.jpg,*.JPEG,*.npz" --exclude ""
追踪文件
# 查看追踪文件,git add file后才能查看
git lfs ls-files
# 追踪单独文件
git lfs track "dir/file"
# 追踪多个文件
git lfs track "*.png"
# 解除追踪文件
git lfs untrack "dir/file"
补充:git add file
后才能查看追踪文件。
使用流程
git lfs install
git lfs track files
git add .gitattributes
其中,git lfs install
为全局配置,只需执行一次,其它仓库无需再次执行。
1.8. 解决换行符的替换问题
问题
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 平台特殊定制的;
配置 .gitattributes文件
该方案适用于各种系统(包括Windows和类Unix系统)
Git的.gitattributes
文件是一个文本文件,文件中的一行定义一个路径的若干属性。官方文档链接:gitattributes文档 。
格式
该文件以行为单位设置一个路径下所有文件的属性,格式如下:
要匹配的文件模式 属性1 属性2
模式匹配路径的规则与.gitignore
文件中的规则相同(详情请查看 1.5.3. 忽略规则配置语法 和 1.5.6. 忽略规则示例),少数例外情况除外:
- 禁止负型
- 匹配目录的模式不会递归匹配该目录中的路径,因此使用尾随斜杠
path/
语法在属性文件中毫无意义;应改为使用path/**
。
实例
* text=auto
# 文件的行尾自动转换。如果是文本文件,则在文件入Git库时,行尾自动转换为LF。如果已经在入Git库中的文件的行尾是GRLF,则文件在入Git库时,不再转换为LF。
*.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
控制行尾的规范性。如果一个文本文件是规范的,则Git库汇总该文件的行尾总是LF。对于工作目录,除了text
属性之外,还可以设置eol
属性或core.eol
配置变量。 - eol
设置行末字符。
eol=lf
,入库时将行尾规范为LF,检出时禁止将行尾转换为CRLF
eol=crlf
,入库时将行尾规范为LF,检出时将行尾转换为CRLF。 - diff
diff属性影响Git对特殊文件生成差异的方式。它可以告诉Git是否为路径生成文本补丁还是将路径视为二进制文件。它也可以影响在hunk
头部显示的@@ -k,l +n,m @@
,告诉Git使用外部命令来生成差异,或者是在生成差异之前让Git将二进制文件转换为文本文件。 - 其他属性即详情在这里不再介绍,请参照官方文档:gitattributes文档 。
优先级
- 同一个gitattributes文件中,按照行的先后顺序,优先级从上到下;如果一个文件的某个属性被多次设置,则后序的设置优先。
- 在一个Git库中可以有多个gitattributes文件,不同gitattributes文件中,属性设置的优先级如下(从高到低):
/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
LF与CRLF格式相互转换
Windows系统
1. 查看文件换行格式
在Notepad和Notepad++的底部状态栏可以分辨某一文件的换行符是LF还是CRLF。
2. 相互转换
需要先安装Notepad++软件,使用该软件打开文件,点击编辑 -> 文档格式转换 -> 转换为[CRLF/LF/CR]
。
Linux系统
在Linux下,命令unix2dos
是把Unix文件格式(LF)转换成Windows文件格式(CRLF),命令dos2unix
是把Windows格式(CRLF)转换成Unix文件格式(LF)。
1.9. git提示host key不匹配
问题
git拉取代码时报错:
Unable to negotiate with 10.132.3.76 port 29418: no matching host key type found. Their offer: ssh-rsa
fatal: 无法读取远程仓库。
原因
新版的 openssh 的 ssh 客户端默认禁用了 ssh-rsa 算法,但是对方服务器只支持 ssh-rsa。
当不能自己升级远程服务器的 openssh 版本或修改配置让它使用更安全的算法时,可以在本地 ssh 针对这些旧的ssh server重新启用 ssh-rsa 。
解决方案
# 创建文件:~/.ssh/config
cd ~/.ssh
touch config
# 编辑文件
vim config
# 写入文件
Host *
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa
1.10. add时提示does not have a commit checked out
原因
在此Git项目子文件夹中已存在Git仓库。
解决方案
在文件管理器中勾选查看隐藏文件
。
将此Git项目子文件夹中存在的.git
文件夹删除。
再次进行git add .
操作。
1.11. git报错可疑所有权
当拷贝Git仓库后再进行Git操作时,有如下报错:
fatal: detected dubious ownership in repository at '/path/to/project'
'/path/to/project' is owned by:
(inconvertible) (S-1-5-21-4252685605-3490785942-2905406964-1001)
but the current user is:
computer/user (S-1-5-21-1432075603-2827112676-3747148635-1001)
原因:
新版的Git出于安全考虑,增加了对仓库目录所有权的检查,由于项目的所有者与现用户不一致,导致报错。
解决方案:
将仓库目录添加为例外,命令如下:
git config --global --add safe.directory "/path/to/project"
示例:
# Windows
git config --global --add safe.directory "E:/Code/Project"
# Linux
git config --global --add safe.directory "/home/user/Code/Project"
1.12. 局域网内搭建Git远程仓库
使用局域网开发有时不能连接到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 文件共享支持
,打上勾,并重启。
2. 远程库使用流程
使用Git大部分是多人协作的开发模式,所以一般远程库+本地库共同使用,先讲述一下远程库的使用流程,而远程库的流程自然包括本地库的使用流程。后面会单独介绍本地库的使用流程。
远程库使用流程包括新建远程仓库,配置开发者用户信息,设置SSH key,设置多个SSH key(可不设),检测是否成功配置SSH key,局域网内搭建Git远程仓库,将远程库克隆到本地,创建和切换分支,下拉代码,上传代码,合并分支,合并冲突,减少冲突,撤销更改,版本回退,整理提交历史,使用rebase合并分支,等等。具体流程如下:
2.1. 基本流程
基本流程指正常完成某一操作的最基本的流程。扩展流程指在某个特定条件下要执行的流程。
新建远程仓库
方式一(推荐): 借助网络平台建立远程仓库
通过Web端(如GitHub,DevCloud等)新建仓库与分支,方法请自行查询或探索。在网页端可以复制SSH地址或HTTPS地址。后续会使用该地址与远程库进行连接,详情见2.1 连接远程仓库。
方式二: 局域网内搭建Git远程仓库
Windows环境下,在局域网开发有时不能连接到GitHub,因此需要建立一个公共的远程库供项目组使用。详情请见2.2 局域网内搭建Git远程仓库。
配置Git
配置全局用户信息:
不加--global
即配置当前仓库的信息,只有配置好用户名和邮箱后才可以使用接下来的功能。
# 全局用户名
git config --global user.name "userName"
# 全局邮箱
git config --global user.email "userEmail"
可选配置:
# 设置Git默认编辑器为vim
git config --global core.editor vim
# 防止证书无效,解决SSL certificate problem: self signed certificate
git config --global http.sslVerify "false"
# 明文保存用户名和密码到硬盘,以免每次都要输入密码
git config --global credential.helper store
配置缩写:
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
查看配置信息:
git config --list
查看全局配置信息:
git config --global --list
删除指定全局配置:
git config --global --unset [config_name]
连接远程仓库的方式
HTTPS方式:适合初学者,操作简单,但使用较麻烦。
SSH方式(推荐):适合对电脑有一定基础的用户,配置较麻烦,但使用方便。
区别:使用https url克隆对初学者来说会比较方便,复制https url然后到git Bash里面直接用clone命令克隆到本地就好,但是每次pull
和push
代码都需要输入账号和密码,这也是https方式的麻烦之处。而使用SSH url克隆却需要在克隆之前先配置和添加好SSH key,配置好后,使用方便。
注意:若使用HTTPS方式,则可直接跳到2.1 连接远程仓库,若使用SSH方式,则需要继续看2.1 设置SSH key。
设置SSH key(默认只设1个)
检查是否已经有 SSH key
cd ~/.ssh // 跳转到ssh文件夹
ls // 列出文件夹中的文件
若.ssh
文件夹不存在,则继续第2步创建SSH密钥;若存在 id_rsa.pub 或 id_dsa.pub 文件,则已存在SSH密钥,可以直接跳到第3步,或到第2步重置SSH密钥。
创建SSH密钥
ssh-keygen -t rsa -C "yourEmail"
# or
ssh-keygen -t rsa -C "yourEmail" -f ~/.ssh/[rsafilename]
-t
后接密钥类型,默认为rsa
,可省略;
-C
设置注释文字,比如邮箱。
-f
指定密钥文件存储文件名,可省略,省略后会在当前文件夹创建。
yourEmail
为用户邮箱,也可以是其它备注信息。
[rsafilename]
为rsa私钥文件的名称。
输入第1条命令后会提示输入文件名和密码,按3个回车即可,也可自定义文件名和密码;如果输入第2条命令,则直接提示输入密码,按2个回车或自定义密码即可。
复制SSH公钥
cat ~/.ssh/id_rsa.pub
# or
clip < ~/.ssh/id_rsa.pub
粘贴SSH公钥
将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只能配置在1个GitHub账户或仓库上,因此推荐将SSH key配置在账户的最高权限上。
设置多个SSH key(可省略)
可只用默认的1个SSH key,不设多个,但当同时需要2个SSH的时候需要设置。因为一个SSH key只能对应一个host,若想同时使用GitHub和Gitee进行代码托管,则需要使用不同的SSH key,所以一个终端经常需要设置多个SSH。以连接GitHub为例,步骤如下:
创建另一个密钥
ssh-keygen -t rsa -C "yourEmail" -f ~/.ssh/[rsafilename]
# 示例
ssh-keygen -t rsa -C "yourEmail" -f ~/.ssh/github_rsa
-f
直接指定文件路径及名称,注意文件名不能与第一个SSH key相同;之后的密码可以都是回车。
添加SSH密钥代理(临时)
该方式是临时性的,重启ssh-agent服务后需要重新输入;若要永久保存设置(推荐),则需要配置config
文件,详情见下一步,配置config文件,若配置了config
文件,则无需再添加SSH密钥代理。
添加SSH密钥代理步骤如下。
打开ssh-agent:
若为Windows系统,则命令为ssh-agent bash
若其他系统,命令为ssh-agent -s
或 eval $(ssh-agent -s)
添加私钥:
ssh-add ~/.ssh/github_rsa
配置config文件(推荐)
配置私钥对应的服务器,可永久保存配置,步骤如下。
创建文件:touch ~/.ssh/config
修改文件:vim ~/.ssh/config
插入:按字母“I
”,输入如下信息
# GitHub
Host github
HostName github
Preferredauthentications publickey
IdentityFile ~/.ssh/github_rsa
User NSJim
# TestRepository
Host test
HostName github
Preferredauthentications publickey
IdentityFile ~/.ssh/test_rsa
User NSJim
保存文件:按Esc
,然后输入":wq
"。或者使用记事本修改,文件位置如下:
C:\Users\[username]\.ssh\config
变量说明:
Host
:可随意填写,方便自己记忆,是替换HostName
的变量,后续在添加remote(远程库)时还需要用到;
HostName
:远程库SSH地址的“git@
”与“:
”之间的域名(网站的或公司的,如GitHub的HostName
为github
);
IdentityFile
:填写对应的私钥文件及路径;
User
:用户名,可有可无,起标识作用。
配置完成后,在连接非默认帐号的github仓库时,远程库SSH地址要对应地做一些修改,把HostName
替换为Host
。
示例1:
git remote add orgin git@github:NSJim/test.git
# 更改为
git remote add orgin git@[Host]:NSJim/test.git
示例2:
git clone git@github:NSJim/test.git
# 更改为
git clone git@[Host]:NSJim/test.git
复制SSH公钥
cat ~/.ssh/id_rsa.pub
# or
clip < ~/.ssh/id_rsa.pub
粘贴SSH公钥
与上文同理,将SSH公钥粘贴到GitHub对应的位置并点击确定。
检测是否成功配置SSH key
默认SSH key检测:
ssh -T git@github
然后输入yes
回车,若提示Hi, username!
则成功。
设有多个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
(地址),需从网页端的远程仓库复制。
若不需要参与整个项目的开发工作,且想加快克隆的速度,可限制clone的深度:
git clone --depth=1 [url]
此命令限制 clone 的深度,不会下载 Git 协作的历史记录,可以加快克隆的速度,depth用于指定克隆深度,为1即表示只克隆最近一次commit。
方式二:本地仓库初始化并连接
该方式先进行本地仓库的初始化,然后再进行远程库连接,该方法略微麻烦,效果和方式一相同。优点是可以自定义本地仓库文件夹的名称,并可将仓库文件夹中的代码push
到远程库中,步骤如下。
(1) 移动到要初始化为仓库的文件目录中:cd [path]
(2) 本地仓库初始化(即将当前目录设置为git仓库):git init
(3) 添加远程仓库,命令如下:
git remote add [remote_name] [url]
[remote_name]
为自定义的远程库的名字,默认为origin
;[url]
为远程仓库的SSH地址或HTTPS地址。
(4) 设置上游分支/创建跟踪信息
若本地分支没有与远程分支创建跟踪信息,则需要设置上游分支:
git branch -u [remote_name/remote_branch] [local_branch]
# 或-u的全称--set-upstream-to
git branch --set-upstream-to [remote_name/remote_branch] [local_branch]
设置[remote_name]
远程库的[remote_branch]
分支作为本地当前分支[local_branch]
的上游分支,一般情况下,[remote_branch]
和[local_branch]
同名。
也可在推送时创建跟踪信息:
git push -u [remote_name] [same_branch] # 本地分支和远程分支同名
git push -u [remote_name] [local_branch:remote_branch] # 本地分支和远程分支不同名
# or
git push --set-upstream [remote_name] [same_branch]
git push --set-upstream [remote_name] [local_branch:remote_branch]
将本地分支[local_branch]
推送到[remote_name]
远程库的[remote_branch]
分支,同时创建跟踪信息。
步骤示例:
cd /d/Work/Project
git init
git remote add origin git@github:WongJay/w3cschool.git
# 创建跟踪信息
git branch -u origin/master master
# push时创建跟踪信息,本地分支和远程分支同名
git push -u origin master
remote命令补充
# 列出远程仓库
git remote
# 列出远程仓库并显示URL
git remote -v
# 添加新的远程仓库
git remote add [remote_name] [remote_url]
# 修改远程仓库的URL
git remote set-url [remote_name] [new_url]
# 删除指定远程仓库
git remote remove [remote_name]
# 远程仓库重命名
git remote rename [old_name] [new_name]
# 显示指定远程仓库的详细信息,包括URL和跟踪分支
git remote show [remote_name]
配置开发者的仓库用户信息
git config user.name "userName"
git config user.email "userEmail"
以上为配置git仓库的用户名和邮箱,在与远程仓库交互时,会覆盖已配置的全局用户信息。若已经配置了全局的用户信息,也可不必配置仓库的用户信息,默认会调用全局用户信息。
分支操作
首先移动到本地git仓库:
cd [gitPath]
分支命令
# 查看本地分支
git branch
# 查看远程分支
git branch -r
# 查看全部分支
git branch -a
# 创建分支
git branch [branch_name]
# 创建并切换分支
git checkout -b [branch_name]
# 切换分支
git checkout [branch_name]
# 切换到上一个分支
git checkout -
# 切换到指定提交/标签,处于分离HEAD状态,不位于任何分支上;可基于当前提交新建分支进行新任务
git checkout [commit_id]
git checkout [tag_name]
git checkout tags/[tag_name]
# 不同的远程仓库中有相同的分支时,要切换某仓库的指定分支
git checkout --track [remote_name/branch_name]
# 删除本地分支
git branch -d [branch_name]
# 强制删除本地分支
git branch -D [branch_name]
# 删除远程分支
git push -d [remote_name] [branch_name]
# 重命名当前分支
git branch -m [new_name]
# 重命名指定分支
git branch -m [old_name] [new_name]
补充
查看分支时,带 *
和高亮的为当前分支。
切换分支前需先进行提交(commit)。
若没有合并分支,则不能删除此分支,但可以进行强制删除。
拉取远程分支到本地
克隆时拉取:
git clone -b [branch_name] [url]
其中,branch_name
为远程分支的名称,url
可以是ssh_url
或http_url
。此方法仅在克隆时使用有效,而且拉取的本地分支自动和远程同名分支建立追踪关系。
克隆后拉取:
(1)git fetch方法
# 将远程仓库的所有分支拷贝到本地仓库
git fetch [--all]
# 切换到我们想要拉取的远程分支
git checkout [branch_name]
(2)git checkout -b方法
# 创建本地分支,并与远程分支建立追踪,并切换到此本地分支
git checkout -b [branch_name] origin/[branch_name]
# 拉取远程分支的最新代码
git pull origin [branch_name]
补充:
拉取的本地分支默认与远程分支名称相同;
将远程分支拉取到本地后,可继续基于此分支创建新的本地分支,新分支的名称可与远程分支名称不同。
切换分支整体流程
# 创建分支2
git branch [branchname2]
# 切换分支2
git checkout [branchname2]
# 修改代码
# 暂存或提交
git stash
or
git commit -m [message]
# 切换分支1
git checkout [branchname1]
# 修改代码
# 提交
git commit -m [message]
# 切换分支2
git checkout [branchname2]
# 读取修改
git stash pop
# 提交
git commit -m [message]
# 合并分支2
# 删除分支2
下拉代码
即从服务器下载当前分支的最新版本到本地(只会下载有更新的文件,一般不会覆盖本地已修改的文件)。在开始工作时(进行更改前),上传代码前,合并分支前,都需要先进行git pull
。
# 默认下拉
git pull
# 强制下拉
git pull -f
# 指定分支下拉
git pull [remote_name] [remote_branch:local_branch]
其中,remote_name
为远程仓库名称,默认为origin
;[remote_branch]
为远程分支名称,默认为master
;[local_branch]
为本地分支名称。一般情况下,[remote_branch]
和[local_branch]
相同。
推荐
推荐使用git fetch
和git rebase
下拉代码,用法如下:
git fetch
git rebase
# 强制变基
git rebase -f
若想拉取所有仓库的所有分支,可使用--all
参数:
git fetch --all
若没有建立上游分支,则需要指定远程分支名称,用法如下:
git fetch [remote_name remote_branch]
git rebase [remote_name/remote_branch]
其中,remote_name
为远程仓库名称,默认为origin
;[remote_branch]
为远程分支名称,默认为master
。
报错
若提示:请指定要合并的分支,如下:
Please specify which branch you want to merge with.
解决方案:
有2个方案,在下方详细介绍。若是通过git init
新建的空仓库出现该提示,则需要先使用方案二(指定远程分支),之后在进行方案一(设置上游分支);其他情况直接使用方案一即可。
方案1(推荐):设置上游分支
git branch -u [remote_name/remote_branch] [local_branch]
# 同
git branch --set-upstream-to=[remote_name/remote_branch] [local_branch]
方案2:临时指定远程分支
git pull [remote_name] [remote_branch:local_branch]
推送代码
整体流程:
git status
git add .
git status -s
git commit -m "[message]"
git push
分步解析:
(1) 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)
(2) git add .
将所有文件添加到缓存,也可使用git add [file1] [file2]
单独添加文件。
注意:被add
的文件便可被git管理,没有被add
的文件不会被git管理。
(3) git status -s
再次查看项目当前的文件更新状态,可省略。
(4)git commit -m “[message]”
将缓存提交到本地仓库,[message]
为备注信息。若觉得每次都add
后才能commit
比较麻烦,可以使用git commit -am "[message]"
来跳过add
,但新文件和重命名文件不会被commit
。
注意:要提前配好git仓库的用户名和邮箱才能正常使用该命令。
(5) git push
将本地库推送(即上传)到远程库:
# 默认推送
git push
# 强制推送
git push -f
git push --force
# 推送指定分支/推送新分支
git push [remote_name] [same_branch] # 本地分支和远程分支同名
git push [remote_name] [local_branch:remote_branch] # 本地分支和远程分支不同名
若提示没有上游分支,报错如下:
fatal: The current branch a has no upstream branch.
解决方案:
方案1(推荐):设置上游分支
git push -u [remotename] [remote_branch]
# 同
git push --set-upstream [remote_name] [remote_branch]
-u
为简写,--set-upstream
为全称;[remote_name]
为远程库名称;
将远程库[remote_name]
的远程分支[remote_branch]
作为其上游分支。
方案2:临时指定远程分支
git push [remote_name] [local_branch:remote_branch]
合并分支
方法1:线上合并
网页上新建分支请求、接受合并请求。
方法2:命令行合并
- 切换到要合并的分支:
git checkout [branchname]
- 下拉刷新:
git pull
- 合并分支:
git merge [branchname]
或git merge [branchname] -m "[message]"
branchname
是要合并的分支名称。
合并分支时需要填写合并信息,也可以写在[message]
参数中。 - 上传合并分支:
git push
2.2. 扩展流程
设置多个SSH key
由于该步骤比较常见,所以分类归到了基本流程当中,详情请查看2.1. 基本流程中的2.1.5. 设置多个SSH key。
可只用默认的1个SSH key,不设多个,但当同时需要2个SSH的时候需要设置。因为GitHub的某一个SSH只允许一个账户或仓库使用,所以一个终端经常需要设置多个SSH。
删除分支
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]"
查看提交记录
前言
提交记录也可称为版本记录。
查看仓库提交记录
# 显示作者、时间等详情
git log
# 以简洁的一行格式显示提交信息,仅显示commit_id和备注
git log --oneline
注意:此命令只可以查看到HEAD
指针及其之前的版本记录,若要查看全部历史版本,则可使用git reflog
命令。
查看全部历史版本
git reflog
使用git log
命令只可以查看到HEAD
指针及其之前的版本记录,若进行过版本回退操作,则HEAD指针之后的历史提交版本便无法通过git log
命令看到;这时可以使用git reflog
命令,能够查看到所有历史版本记录,从中找到所需的commit_id
,可使用git reset --hard [commit_id]
恢复版本,详情可参考后文的版本回退章节。
查看文件提交记录
查看文件提交记录,可获取修改者、修改时间等信息:
git blame [fileName]
查看文件指定行数的提交记录:
# 显示从起始行到结束行的数据
git blame -L [startLine], [endLine] [fileName]
# 显示从起始行到文件最后一行的数据
git blame -L [startLine], [fileName]
# 显示从文件开始到结束行的数据
git blame -L , [endLine] [fileName]
其中,[startLine]
为起始行,[endLine]
为结束行。
修改提交
修改最近一次提交
git commit --amend
整体流程:
git commit -m "first commit"
# 修改内容
git status
git add .
git status -s
git commit --amend
修改历史提交信息
可使用rebase
命令修改历史提交信息:
git rebase -i [commit_id]
详情可参考 技巧汇总/rebase 的 修改提交 章节。
删除提交
详情可参考 技巧汇总/rebase 的 删除提交 章节。
转移提交
可使用cherry-pick
命令将提交应用于其它分支,即转移提交,用法如下。
转移单独提交
# 查看指定提交的commit_id
git log [--oneline]
# 切换到指定分支
git checkout [branch_name]
# 将指定提交应用于当前分支
git cherry-pick [commit_id]
# 或将指定分支的最后一笔提交应用于当前分支
git cherry-pick [branch_name]
转移多个提交
# 转移A和B两个提交
git cherry-pick [commit_A] [commit_B]
# 转移A到B的所有提交,但不包含A
git cherry-pick A..B
# 转移A到B的所有提交,包含A
git cherry-pick A^..B
注意:提交 A 必须早于提交 B,否则命令将失败,但不会报错。
合并冲突
若提示合并冲突,提示如下:
自动合并 xxx
冲突(内容):合并冲突于 xxx
error: 不能应用 commit_id... message
提示:解决所有冲突之后,用 "git add/rm <dir/file>" 标记它们,然后执行 "git cherry-pick --continue"。
提示:您也可以执行"git cherry-pick --skip" 命令跳过这个提交。
提示:如果想要终止执行并回到执行 "git cherry-pick" 之前的状态,执行 "git cherry-pick --abort"。
解决方案:
# 解决冲突
git add/rm [dir/file]
git cherry-pick --continue
# 跳过此提交,继续转移下一个提交
git cherry-pick --skip
# 终止执行并恢复到cherry-pick前的状态
git cherry-pick --abort
提交造成合并冲突
当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
,然后再把要修改的文件直接覆盖掉,然后再进行提交。
暂存代码
暂存代码可通过git stash
实现,基本用法如下:
# 暂存
git stash
# 取出
git stash pop
# 删除
git stash drop
若要暂存多次更改,建议在暂存时保存备注:
git stash save "stashMessage"
查看暂存列表:
git stash list
读取或删除指定暂存:
# 读取指定暂存
git stash apply stash@{index}
# 删除指定暂存
git stash drop stash@{index}
示例:
# 暂存修改1
$ git stash save "change1"
# 暂存修改2
$ git stash save "change2"
# 暂存修改3
$ git stash save "change3"
# 查看暂存列表
$ git stash list
stash@{0}: On master: change3
stash@{1}: On master: change2
stash@{2}: On master: change1
# 读取修改1
git stash apply stash@{2}
# 删除修改2的暂存
git stash drop stash@{1}
取消暂存区/取消add
进行add添加暂存区操作后,若要取消暂存区,可使用如下命令:
# Git 2.23及以后版本
git restore --staged [file/dir/.]
# 旧版Git
git reset [file/dir/.]
git reset # 取消全部暂存区
注意:git restore命令是Git 2.23版本及以后才添加的功能,若使用旧版Git可使用reset命令。
撤销更改
(1) 场景1:未添加暂存区
当你改乱了工作区某个文件的内容,但没有添加到暂存区。想直接丢弃工作区的修改时使用该命令:
# Git 2.23及以后版本
git restore [file/dir/.] # .表示还原所有文件
# 旧版Git
git checkout -- [file/dir/.]
(2) 场景2:已提交暂存区
当你不但改乱了工作区某个文件的内容,还添加到了暂存区时。想丢弃修改,则需先取消暂存区,再还原修改:
# Git 2.23及以后版本
# 取消暂存区,回到场景1
git restore --staged [file/dir/.]
# 还原修改
git restore [file/dir/.]
# 旧版Git
git reset [file/dir/.]
git checkout -- [file/dir/.]
(3) 场景3:已提交本地仓库
已经提交了不合适的修改到版本库时,想要撤销本次提交,参考下一步骤,版本回退,不过前提是没有推送到远程库。
版本回退
Git允许我们在版本的历史之间穿梭,命令:
git reset --hard [commit_id]
注意:必须有--hard
参数;若没有--hard
参数,则只是回退了commit,工作区的修改并不会回退。
临时回退
使用git checkout命令可以临时切换到指定提交,此时处于分离HEAD状态,不位于任何分支上。可基于当前提交新建分支进行新任务。
# 切换到指定提交/标签
git checkout [commit_id/tag_name]
# 新建分支进行新任务
git checkout -b [new_branch]
版本回退
要版本回退,用git log
可以查看提交历史和commit_id
,以便确定回退版本。若要在log
界面上下翻页,则按上下箭头(或回车)即可;要退出log
界面,按字母键Q
即可。
# 查看历史
git log [--oneline]
# 版本回退
git reset --hard [commit_id]
重返未来
要重返未来,用git reflog
查看命令历史,以便确定要回到未来的哪个版本,再用git reset
命令重置为指定版本。
# 查看未来历史
git reflog
# 重返未来
git reset --hard [commit_id]
强制推送
版本回退后,要强制推送到远程库才会起作用,否则只是本地库的版本回退,命令:
git push --force
# or
git push -f
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 push --force
补充
相似的,也可尝试 git revert
命令。
标签操作/tag
基础操作
# 查看标签
git tag
# 查看标签具体信息
git show [tag_name]
# 查看远程标签
git ls-remote --tags
# 切换到指定标签
git checkout [tag_name]
# 创建轻量标签
git tag [tag_name] [commit_id] # commit_id可不写,默认为最新提交
# 创建附注标签
git tag -a [tag_name] -m "[message]" [commit_id]
# 推送单独标签
git push origin [tag_name]
# 推送全部标签
git push origin --tags
# 删除本地标签
git tag -d [tag_name]
# 删除远程标签,一般在删除本地标签后操作
git push origin :refs/tags/[tag_name]
fork仓库拉取tag
git remote add upstream [upstream_url]
git fetch upstream
git push origin --tags
切换操作/switch
git switch 是 Git 2.23 版本引入的一个新命令,功能与 git checkout 类似。与 git checkout 不同,git switch 专注于分支切换的操作,并提供了更好的错误检查,可以避免一些常见的错误操作。
# 切换分支
git switch [branch_name]
# 创建新分支并切换
git switch -c [new_branch]
# 切换到前一个分支
git switch -
# 切换到指定提交,处于分离HEAD状态,不位于任何分支上
git switch [commit_id]
# 查看可用分支和标签
git branch
子模块/submodule
子模块即submodule,子模块允许将一个 Git 仓库嵌套在另一个 Git 仓库中。这对于管理项目中的依赖关系、使用外部库或者在一个仓库中包含另一个仓库的特定版本的代码非常有用。普通克隆时不会克隆子模块,需要使用特殊的命令克隆子模块。
克隆包含子模块的仓库
git clone --recursive [repository_url]
这将克隆包含子模块的存储库,并递归克隆并初始化子模块。
初始化子模块
git submodule update --init [--recursive]
如果已经通过普通命令克隆了包含子模块的存储库,可以使用此命令递归的初始化并更新子模块。
其中,--recursive
代表递归的意思,使用此参数可以递归的初始化并更新子模块;若不使用此参数,则不会递归处理子模块的子模块,仅处理直接的子模块。
查看子模块
git submodule
更新子模块
更新全部子模块:
git submodule update
更新单独子模块:
cd submodule_dir
git fetch
git rebase
绑定子模块
将子模块的某一提交绑定至父仓库中,需要先将子模块切换到指定提交,然后进行绑定,命令如下:
# 子模块切换到指定提交
cd submodule_dir
git checkout [commit_id]
# 子模块绑定至父仓库
cd parent_dir
git add submodule_name
# 提交并推送
git commit -m "update submodule"
git push
添加子模块
git submodule add [-b remote_branch] [subrepo_url] [subrepo_name]
# 示例
git submodule add https://github/iphysresearch/GWToolkit.git GWToolkit
其中,-b remote_branch
可省略,默认为远程默认分支;subrepo_url
为子模块仓库的url;subrepo_name
为子模块名称;
添加子模块后,主仓库目录中会出现子模块目录。
删除子模块
git rm --cached [sub_name] # 删除子模块git缓存
rm -rf [sub_name] # 删除子模块目录及源码
vi .gitmodules # 删除项目目录下.gitmodules文件中子模块相关条目
vi .git/config # 删除配置项中子模块相关条目
rm -rf .git/modules/[sub_name] # 删除模块下的子模块目录,每个子模块对应一个目录
git add . && git commit # 重新提交
3. 本地库使用流程
Git也可仅使用本地库进行版本管理,不与远程库进行连接。本地库的版本管理不需要使用SSH key进行验证,也不需要进行clone,pull和push,即把远程库流程中的SSH key操作,clone,pull和push操作去掉即可变为本地库的流程。本地库使用流程如下:
3.1. 基本流程
-
本地仓库初始化(将当前目录设置为git仓库):
git init
-
配置开发者的用户信息:
git config --global user.name "userName" git config --global user.email "userEmail"
以上为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
是要合并的分支名称 -
合并冲突
在远程库的使用流程中也涉及,此处不再重复。
3.2. 扩展流程
扩展流程同远程库的扩展流程,这里不再赘述,内容如下:
- 删除分支
- 合并冲突
- 撤销更改
- 版本回退
4. IDE集成Git使用流程
4.1 介绍
目前很多的IDE(Integrated Development Environment,集成开发环境)都已经集成了Git,如JetBrains IDEA,Visual Studio,微信开发者工具,等等。用户不需要想以前一样只能使用命令行进行代码的版本控制与合作,而是可以在IDE的图形化界面中操作。
当然,即使IDE集成了Git,我们也可以使用Git Bash命令行进行操作,二者互不影响,可以同时使用。下面我以JetBrains的IDEA为例,进行一些基础的讲解,其他软件的操作方法类似。更深入的操作和使用方法可以自行探索。
4.2 IDE与Git连接
- 下载安装Git Bash,下载地址:下载链接 。
- 打开Git Bash命令行,配置开发者的全局用户信息
以上为git全局的用户名和邮箱,不加git config --global user.name "userName" git config --global user.email "userEmail"
--global
即配置当前仓库的信息。 - 打开IDEA软件,
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
,点击Create API Token
,输入在GitHub中注册的用户名和密码,然后会自动生成Token
。点击Test,测试是否连接成功。如下图。
4.3. 集成Git使用流程(图形化操作)
使用时与远程仓库的使用流程大同小异,只是把命令行操作换成了图形化界面而已。其使用流程也分为2个方式,建立本地库和克隆远程库2种。
工作目录的状态
IDEA软件的工作目录中:
红色代表未被Git管理;
绿色代表以添加到缓存;
白色代表已提交至本地库;
蓝色代表已修改。
建立本地库方式
- 创建本地库
打开IDEA软件,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
界面。 -
其他操作
其他操作与上一方式(建立本地库方式)相同。
5. Git GUI使用流程
由于Git GUI的使用流程的原理与Git Bash相同,且操作方式与IDE集成的Git极其相似,因而在此不进行详细介绍,感兴趣的可以查看另一个博主的一篇博客:Git GUI的使用 。
打开Git GUI的方法:
在文件资源管理器中右键,点击Git GUI here
即可。
6. 常用命令
6.1. 远程仓库命令
添加远程库
若使用SSH方式则需要先配置SSH key;若使用HTTPS方式则需要在后续使用时输入HTTPS凭据的账户和密码。以下为添加远程库命令。
git remote add [remotename] [url]
[remotename]
为自定义的远程库别名,默认为origin
;
[url]
为远程仓库的SSH地址或HTTPS地址。
示例:
git remote add origin git@github:WongJay/w3cschool.git
查看当前的远程仓库
git remote
git remote -v
执行时加上 -v 参数,你还可以看到每个别名的实际链接地址,即SSH url
。
提取远程仓库
- 从远程仓库下载新分支与数据:
该命令执行完后需要执行git fetch [remotename] [branch] git merge [remotename] [branch]
git merge
远程分支到你所在的分支。在已经设置上流分支的情况下可省略[remotename]
和[branch]
,[remotename]
一般为origin
。 - 从远端仓库提取数据并尝试合并到当前分支(推荐):
该命令就是在执行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]
6.2. 其他命令
查看用户配置信息
- 查看所有配置
git config -l
- 查看全局配置
git config --global -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
- 显示摘要而非整个 diff:
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
重定基底(rebase)
- 合并提交(commit)
(1) 将提交历史整理成一条直线
git rebase
(2) 合并最近4条合并记录
git rebase -i HEAD~4
- 合并分支(在work分支下)
git rebase master
Git栈(stash)
git stash
:备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中。git stash pop
:从Git栈中读取最近一次保存的内容,恢复工作区的相关内容。由于可能存在多个Stash的内容,所以用栈来管理,pop会从最近的一个stash中读取内容并恢复。git stash list
:显示Git栈内的所有备份,可以利用这个列表来决定从那个地方恢复。git stash clear
:清空Git栈。此时使用gitg等图形化工具会发现,原来stash的哪些节点都消失了。
7. 团队开发流程
私有仓库开发流程
说明
若私有仓库开发团队人数较多,各自负责各自的功能模块,则为了更规范的开发,可参考如下开发流程。
若为开源仓库,可参考下文的开源仓库开发流程。
分支命名规则
主分支:master
开发分支:developer
功能分支:feature - 分支名称
分支发布:release - 版本号
bug 分支修复:bugfix - 版本号
开发流程
- 管理员「项目负责人」创建 git 仓库,建立 developer 分支
git branch develop git push -u origin develop
- 项目成员「开发者」clone 项目,在本地建立自己功能分支
git clone 项目 git 地址 git checkout -b develop origin/develop # 创建本地功能分支 git checkout -b feature-[name-desc] develop
- 在自己的分支上进行开发 :
git add
,git commit
等,注意此时不要 push 到远程分支(origin)。 - 功能完成后可以直接合并本地的 developer 分支后 push 到远程仓库,合并的时候很大几率发生冲突,此时需要 merge ,merge的时候确保不影响项目其他成员,如果多个人都操作了同一个类,最好当面确认后在进行修改。等合并完成确认无误后,删除本地开发分支.
git checkout develop git pull origin develop # 确保本地 developer 分支为最新的 git merge feature-[name-desc] git push git branch -d feature-[name-desc] # 删除本地分支
- 发布分支
git checkout -b release-0.1 develop # 一旦准备好了发版,合并修改到 master 分支和 developer 分支上,删除发布分支 # 合并修改到 master 分支 git checkout master git merge release-0.1 git push # 合并修改到 developer 分支 git checkout develop git merge release-0.1 git push # 删除发布分支 git branch -d release-0.1
- 为 master 分支打发版 tag
git checkout master git tag -a 0.1 -m "Initial public release" master git push --tags
- bug 修复分支,如果正在开发功能的同时,developer 上发现了线上 bug,或者未上线的 bug,我们可以开一个 bugfix 分支来修复 bug
git checkout -b bugfix-#001(bug 分支名称) master(或 developer) /*** 去修 bug 吧 */ .... /*** 修复完成 */ git checkout master git merge bugfix-#001 git push git branch -d bugfix-#001
开源仓库开发流程
说明
开源仓库除仓库管理员外,其他人没有合入权限,因此需要先派生(Fork)开源仓库,从派生仓库创建合并请求(PR,Pull Request)后,开源仓库管理员才能进行合入。以Github为例,开发流程如下。
专业术语:
Fork:派生
PR:Pull Request
上游仓库:即开源仓库
派生仓库:Fork的个人仓库
强制推送:git push -f
开发流程
- 找到开源仓库,即上游仓库。
- 从上游仓库派生个人仓库,即Fork。
- 克隆派生仓库,注意不要克隆上游仓库。
- 若克隆后长时间未修改,则需更新派生仓库,步骤见下文。
- 创建本地功能分支。
- 修改代码并本地提交。
- 更新派生仓库并rebase到最新。
- 提交到个人派生仓库,若失败可强制推送:git push -f [remote_name] [local_branch:remote_branch]
- 创建合并请求(PR),即创建派生仓库到上游仓库的合并请求。
- 再次修改代码,使用 git commit --amend 强推。
- 上游仓库管理员合并请求。
- PR合入后,删除本地分支。
更新派生仓库
当上游仓库有更新时,派生仓库不会自动更新,需要手动更新,步骤如下。
网页更新
在个人的派生仓库网页上点击更新派生仓库
即可,如下图:
命令更新
在派生仓库通过命令行更新,步骤如下:
# 查看已有远程仓库名称
git remote -v
# 添加上游仓库
git remote add [up_name] [up_url]
# 拉取上游仓库代码
git fetch [up_name] [remote_branch]
git rebase [up_name/remote_branch]
# 更新派生仓库,可强制推送
git push [-f] [remote_name] [local_branch:remote_branch]
# 示例
git remote add up https://github/xxxx/xxxx.git
git fetch up master
git rebase up/master
git push [-f] origin feature:master
其中,up_name
为上游仓库名称,up_url
为上游仓库url,local_branch
为本地分支,remote_branch
为远程分支。
远程仓库从上游仓库切换为派生仓库
当克隆上游仓库后,此时远程仓库为上游仓库。此时用户在GitHub平台的上游仓库创建了一个fork(即派生仓库),这时希望派生仓库作为本地项目的远程仓库,操作步骤如下:
# 移动到本地仓库
cd /path/to/git_dir
# 查看远程仓库的url
git remote -v
# 修改origin远程库的url为派生仓库的url
git remote set-url origin [fork_url]
# 添加up远程库,并设置为上游仓库的url
git remote add up [up_url]
此后,本地仓库已与派生仓库建立连接,且远程仓库名仍然为默认的origin,并可按照上文方法更新派生仓库。
版权声明:本文标题:Git使用流程及技巧 - 详细教程 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1726493527a1072817.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论