Git使用流程及技巧 - 详细教程_git使用的基本流程 site:blog.csdn.net-程序员宅基地

技术标签: 远程库及本地库使用流程  Skill  Git  # Git  配置多个SSH key  Git忽略规则  Code  IDE集成Git使用流程  

Git使用流程及技巧 - 详细教程

前言

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. 基础技巧

  1. 打开Git命令行:Git Bash的快捷方式或在文件资源管理器中右键Git Bash Here。
  2. 命令行中的基础操作同Linux命令行,如创建文件夹,Vim命令等。关于Linux的命令行基础命令和用法,详情请参见W3CSchool的教程网站:Linux教程
  3. 命令行中的 ~ 指根目录,即C:\Users\[username]\
  4. 在命令行中进行的全局设置(git config --global)保存在根目录下的.gitconfig文件中,可以使用笔记本进行查看和更改;进行的项目设置(git config)保存在项目文件夹下的.git/config文件中。
  5. 命令行中的文件目录使用符号 / ,例如:D:\Work\Temp 在命令行中要写成 d/work/temp 。路径名和文件名不区分大小写,且可以用Tab进行补全。
  6. 命令行中,单引号可以代替双引号,但一定要左右匹配,且为英文标点符号。
  7. 命令行中,若忘记命令的使用方法或options,则可以添加-h参数,查看帮助,如:git remote -h
  8. Git连接远程库有2种方式:HTTPS和SSH(推荐),正文有详细介绍。
  9. 在整个项目中,项目的文件夹名称,文件名称,Commit Message,Merge Message,等等,尽量不要使用中文。全部用英文较好,否则可能会出现命令行乱码问题。(乱码问题对功能没有影响,但可能会影响项目成员对文件和提交历史的识别)
  10. 当GitHub仓库的上传文件接口不起作用时,可能是浏览器的兼容问题,可以试试谷歌或火狐浏览器。
  11. 在GitHub平台的项目仓库中,文件夹名称中可能会出现斜杠符号 / ,众所周知,文件夹名称中不可能包含符号 / ,所以该符号表示该文件夹包含的子文件夹。
    举一个例子:名称为page/images的文件夹,代表page文件夹下的images文件夹。
  12. 本篇文章中,所有的[filename]都可以用 . 代替,代表当前目录所有文件。

1.2. 提升SSH传输速度

在使用 SSH 方式在GitHub上进行代码托管时,一般速度会很慢,可以修改Git软件的配置,即关闭GSS API校验来提升速度,解决方案如下。

解决方案
以Windows 10系统为例:

  1. 找到Git软件的安装目录,例如:D:\Program Files\Git
  2. 进入etc\ssh目录,找到ssh_config文件,使用Notepad打开。
  3. GSSAPIAuthentication no前面的注释#删掉,或新增一行GSSAPIAuthentication no,保存文件。
  4. 再次使用ssh命令操作GitHub项目,可以体验到速度的提升,本人从100k/s变为5M/s,速度提升50倍。

若无法找到Git软件安装目录,可以右键快捷方式,选择打开文件位置

也可以使用vim命令编辑ssh_config文件,方法如下:

  1. 右键文件资源管理器点击Git Bash here,打开git命令行。
  2. 编辑ssh_config文件:vim /etc/ssh/ssh_config
  3. 找到GSSAPIAuthentication no配置项。
  4. 配置方法同上。

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_CNCharacter set改为GBK;点击ApplySave。再输入命令就不是乱码了,如下图:
在这里插入图片描述
注意: 情况1和情况2只能解决1种,建议解决情况2。

情况2:远程库资源乱码(推荐解决)

非git命令中文显示正常,如:ls命令,等;但git命令无法显示中文,如:git status -s,等。如下图:
在这里插入图片描述
解决方案:
命令行窗口右键Options -> Text 界面,LocaleCharacter set为默认值(即空白);或Locale改为zh_CNCharacter set改为UTF-8;点击ApplySave

并修改全局配置,在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 i18n.commitencoding utf-8
git config --global i18n.logoutputencoding utf-8
export LESSCHARSET=utf-8

1.4. 解决冲突的方式和流程(减少冲突)

详情请见2.2 修改已提交造成合并冲突章节和2.2 本地修改未提交造成合并冲突章节。

主分支解决冲突

  1. 去自己的工作分支
    git checkout work
  2. 获取最新修改
    git pull
  3. 工作
  4. 提交工作分支的修改
    git commit -m
  5. 回到主分支
    git checkout master
  6. 获取远程最新的修改,此时不会产生冲突
    git pull
  7. 合并工作分支的修改,若有冲突在此时解决
    git merge work
  8. 推送到远程库
    git push

分支解决冲突(推荐)

在分支解决冲突,可以避免主分支出现冲突问题而造成的代码混乱。

  1. 去自己的工作分支
    git checkout work
  2. 获取最新修改
    git pull
  3. 工作
  4. 提交工作分支的修改
    git commit -a
  5. 回到主分支
    git checkout master
  6. 获取远程最新的修改,此时不会产生冲突
    git pull
  7. 回到工作分支
    git checkout work
  8. 合并主干的修改,如果有冲突在此时解决
    git merge master

    git rebase master(推荐)
  9. 回到主分支
    git checkout master
  10. 合并工作分支的修改,此时不会产生冲突。
    git merge work
  11. 推送到远程库
    git push

1.5. 使用rebase整理提交历史

拉取代码

rebase用于本地拉取代码时,和git pull的作用类似。

git pull将从远程仓库拉取最新的更改并将其merge到当前分支。git rebase会将当前分支的提交按照指定的基底重新应用在另一个分支上,从而产生一个线性的提交历史。相对于mergerebase 产生的历史更加清晰,没有多余的合并提交。

使用rebase拉取代码的用法如下:

git fetch
git rebase

若没有建立上游分支,则需要指定远程分支名称,用法如下:

git fetch [origin remote_branch]
git rebase [origin/remote_branch]

其中,[remote_branch]为远程分支名称。

若有以下不能变基提示,则先commitrebase即可。

不能变基:您有未暂存的变更

直线变基

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

修改提交

操作步骤同合并提交,首先查看提交记录:

git log [--oneline]

修改提交:

# 修改指定版本,commit_id为指定版本的前一个版本
git rebase -i [commit_id]
# 将指定版本的pick修改为e,保存退出
# 可修改代码
git add .
git status -s
# 重新提交,可修改提交信息
git commit --amend
# 继续变基
git rebase --continue

合并分支

git merge 操作合并分支会让两个分支的每一次提交都按照提交时间(并不是push时间)排序,并且会将两个分支的最新一次commit点进行合并成一个新的commit,最终的分支树呈现非整条线性直线的形式。

git rebase操作实际上是将当前执行rebase分支的所有基于原分支提交点之后的commit打散成一个一个的patch,并重新生成一个新的commit hash值,再次基于原分支目前最新的commit点上进行提交,并不根据两个分支上实际的每次提交的时间点排序,rebase完成后,切到基分支进行合并另一个分支时也不会生成一个新的commit点,可以保持整个分支树的完美线性。

  1. 先从 master 分支切出一个 feature1 分支,进行开发
    git checkout -b feature

    分支树如下图:
    分支图

  2. 这时,你的同事完成了一次修改(hotfix) ,并合并了 master 分支,此时 master 已经领先于你的 feature1 分支了:
    分支图

  3. 此时,我们想要同步 master 分支的改动

    方法一:merge方法
    git(feature1): git merge master
    在这里插入图片描述
    若执行git log命令,就会在记录里发现一些 merge 的信息,但我们想要保持一份干净的 commit 。这时候, git rebase 就派上用场了,详情见方法二。

    方法二:rebase方法
    git(feature1): git rebase master
    在这里插入图片描述
    commit 记录我们可以看出来, feature1 分支是基于 hotfix 合并后的 master ,自然而然的成为了最领先的分支,而且没有 mergecommit 记录,是不是感觉很舒服了。

    补充一下rebase的原理:
    首先, git 会把 feature1 分支里面的每个 commit 取消掉;
    其次,把上面的操作临时保存成 patch 文件,存在 .git/rebase 目录下;
    然后,把 feature1 分支更新到最新的 master 分支;
    最后,把上面保存的 patch 文件应用到 feature1 分支上;

  4. rebase 的过程中,也许会出现冲突 conflict 。在这种情况, git 会停止 rebase 并会让你去解决冲突。在解决完冲突后,用 git add 命令去更新这些内容。

    注意,你无需执行 git commit,只要执行 continue
    git rebase --continue
    这样 git 会继续应用余下的 patch 补丁文件。

  5. 在任何时候,我们都可以用 --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使用流程

  1. 在项目根目录打开Git Bash命令行(即Git Bash Here)。

  2. 创建.gitignore文件

    touch .gitignore
    
  3. 编辑.gitignore文件

    vim .gitignore
    

    示例内容:

    # 忽略当前目录的dir文件夹
    /dir/
    
    # 忽略所有目录的dir文件夹
    dir/
    
    # 忽略当前目录的file文件
    /file
    
    # 忽略所有目录的file文件
    file
    
    # 忽略所有目录的test.txt文件
    test.txt
    
    # 忽略所有目录的html文件
    *.html
    
  4. 保存.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.objtools/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删除源码文件,步骤如下:

  1. 先将要忽略的文件在本地备份
  2. 在本地删除要忽略的文件
  3. 通过Git Bash推送(push)本地代码到远程仓库
  4. 创建.gitignore文件并写入忽略规则
  5. 拷贝本地备份的忽略文件到本地原位置
  6. 打开IDE查看git操作是否正常,下次commit便不会提交忽略文件了

解决方案2
由于Git远端仓库平台,如github、gitee、等等,它们都支持online删除源码文件。因此也可使用如下步骤:

  1. 先将要忽略的文件在本地备份
  2. 在远程仓库分支上删除要忽略的文件
  3. 通过Git Bash拉取(pull)远程库的代码
  4. 创建.gitignore文件并写入忽略规则
  5. 拷贝本地备份的忽略文件到本地原位置
  6. 打开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. 忽略规则示例),少数例外情况除外:

  1. 禁止负型
  2. 匹配目录的模式不会递归匹配该目录中的路径,因此使用尾随斜杠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。

属性

  1. text
    控制行尾的规范性。如果一个文本文件是规范的,则Git库汇总该文件的行尾总是LF。对于工作目录,除了text属性之外,还可以设置eol属性或core.eol配置变量。
  2. eol
    设置行末字符。
    eol=lf ,入库时将行尾规范为LF,检出时禁止将行尾转换为CRLF
    eol=crlf,入库时将行尾规范为LF,检出时将行尾转换为CRLF。
  3. diff
    diff属性影响Git对特殊文件生成差异的方式。它可以告诉Git是否为路径生成文本补丁还是将路径视为二进制文件。它也可以影响在hunk头部显示的@@ -k,l +n,m @@,告诉Git使用外部命令来生成差异,或者是在生成差异之前让Git将二进制文件转换为文本文件。
  4. 其他属性即详情在这里不再介绍,请参照官方文档:gitattributes文档

优先级

  1. 同一个gitattributes文件中,按照行的先后顺序,优先级从上到下;如果一个文件的某个属性被多次设置,则后序的设置优先。
  2. 在一个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远程仓库

使用局域网开发有时不能连接到GitHub,因此需要建立一个公共的远程库供项目组使用。在Windows10系统环境下,步骤如下。

  1. 在公共服务器下创建远程仓库
    公共服务器(局域网服务器)可以是局域网中任意一台电脑,当做Git的远程仓库来使用,创建的远程仓库为空仓库。可供其他电脑进行代码的pullpush。步骤如下。

    (1) 创建一个文件夹,如public.git
    mkdir public.git
    (2) 进入该文件夹,建立裸仓库
    git init --bare

  2. 设置网络访问权限
    (1) 设置共享文件夹及共享权限
    设置 public.git 为共享文件夹。右键文件夹 —> 属性 —> 共享 —> 高级共享;设置共享名,添加;设置权限,编辑组和用户名,默认为Everyone,为Everyone添加允许完全控制权限。

    (2) 检测文件夹是否可访问
    确认在本机文件管理器中通过共享文件夹路径 \\IP地址\共享文件夹名称\\主机名称\共享文件夹名称 访问到,推荐使用IP地址,因为主机名可能出现重名冲突,而且速度更快,更精确。

    IP地址为本机(公共服务器)的IP地址,可通过Win10的 CMD命令提示符ipconfig命令查看,对应的网络适配器的IPv4地址即为本机的 IP地址

    主机名称可以右键桌面的 此电脑 图标,点击属性可以查看。也可在Git bash命令行中查看,@前面的即为主机名。

    注意: 共享文件夹名称可以与文件夹名称不同;共享文件夹路径的主机名称和共享文件夹名称不规范大小写;Git访问时,应该使用正斜杠 /

  3. 项目组成员连接局域网远程仓库
    项目组成员在自己的机器(包括公共服务器本机)上,参照以下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地址。

  4. 注意事项
    (1) 密码保护
    若共享设置中开启了密码保护,则项目组用户必须拥有公共服务器的用户账户(主机名)和密码(登录密码),才能访问共享文件夹。项目组成员在进行pullpush时需要填写用户账户和密码才能继续操作。

    控制面板\网络和 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

连接远程仓库的方式

HTTPS方式:适合初学者,操作简单,但使用较麻烦。
SSH方式(推荐):适合对电脑有一定基础的用户,配置较麻烦,但使用方便。

区别:使用https url克隆对初学者来说会比较方便,复制https url然后到git Bash里面直接用clone命令克隆到本地就好,但是每次pullpush代码都需要输入账号和密码,这也是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公钥

clip < ~/.ssh/id_rsa.pub
# or
cat ~/.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 -seval $(ssh-agent -s)

添加私钥:

ssh-add ~/.ssh/github_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"。或者使用记事本修改,文件位置如下:

C:\Users\[username]\.ssh\config

变量说明:
Host:可随意填写,方便自己记忆,是替换HostName的变量,后续在添加remote(远程库)时还需要用到;
HostName:远程库SSH地址的“git@”与“:”之间的域名(网站的或公司的,如GitHub的HostNamegithub.com);
IdentityFile:填写对应的私钥文件及路径;
User:用户名,可有可无,起标识作用。

配置完成后,在连接非默认帐号的github仓库时,远程库SSH地址要对应地做一些修改,把HostName替换为Host

示例1:

git remote add orgin [email protected]:NSJim/test.git
# 更改为
git remote add orgin git@[Host]:NSJim/test.git

示例2:

git clone [email protected]:NSJim/test.git
# 更改为
git clone git@[Host]:NSJim/test.git

复制SSH公钥

clip < ~/.ssh/id_rsa.pub
# or
cat ~/.ssh/id_rsa.pub

粘贴SSH公钥
与上文同理,将SSH公钥粘贴到GitHub对应的位置并点击确定。

检测是否成功配置SSH key

默认SSH key检测:

ssh -T [email protected]

然后输入yes回车,若提示Hi, username! 则成功。

设有多个SSH key时检测:

ssh -T git@[Host]

Host~/.ssh/config 中的Host,用来代替HostName;若提示Hi, username! 则成功。

连接远程仓库

即本地库与远程库的连接,为后续进行代码的pullpush做准备。需要使用2.1.1. 新建远程仓库中的SSH地址或HTTPS地址。

方式一(推荐):将远程仓库clone到本地

git clone [url]

[url]即远程库的SSH urlHTTPS url(地址),需从网页端的远程仓库复制。

若不需要参与整个项目的开发工作,且想加快克隆的速度,可限制clone的深度:

git clone --depth=1 [url]

此命令限制 clone 的深度,不会下载 Git 协作的历史记录,可以加快克隆的速度,depth用于指定克隆深度,为1即表示只克隆最近一次commit。

方式二:本地仓库初始化并连接

该方式先进行本地仓库的初始化,然后再进行远程库连接,该方法略微麻烦,效果和方式一相同。优点是可以自定义本地仓库文件夹的名称,并可将仓库文件夹中的代码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]分支。

步骤示例:

cd /d/Work/Project
git init
git remote add origin [email protected]:WongJay/w3cschool.cn.git
git branch --set-upstream-to origin/master 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 [branch_name]
# 创建并切换分支
git checkout -b [branch_name]
# 删除分支
git branch -d [branch_name]
# 强制删除分支
git branch -D [branch_name]

补充
查看分支时,带 * 和高亮的为当前分支。
切换分支前需先进行提交(commit)。
若没有合并分支,则不能删除此分支,但可以进行强制删除。

拉取远程分支到本地
克隆时拉取:

git clone -b [branch_name] [url]

其中,branch_name为远程分支的名称,url可以是ssh_urlhttp_url。此方法仅在克隆时使用有效,而且拉取的本地分支自动和远程同名分支建立追踪关系。

克隆后拉取:
(1)git fetch方法

# 将远程仓库的所有分支拷贝到本地仓库
git fetch
# 切换到我们想要拉取的远程分支
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 fetchgit rebase下拉代码,用法如下:

git fetch
git rebase

若没有建立上游分支,则需要指定远程分支名称,用法如下:

git fetch [origin remote_branch]
git rebase [origin/remote_branch]

报错
若提示:请指定要合并的分支,如下:

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 add .
git status -s
git commit -m "[message]"
git push

分步解析:

  1. git status
    查看项目当前的文件更新状态,也可以用git status -s简洁显示,一般与git diff命令配合使用,可省略。在任何时刻都可使用git statusgit 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
    将本地库推送(即上传)到远程库

    提示没有上游分支

    报错如下:

    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 push --force
    或
    git push -f
    

合并分支

方法1:线上合并
网页上新建分支请求、接受合并请求。

方法2:命令行合并

  1. 切换到要合并的分支:git checkout [branchname]
  2. 下拉刷新:git pull
  3. 合并分支:git merge [branchname]git merge [branchname] -m "[message]"
    branchname是要合并的分支名称。
    合并分支时需要填写合并信息,也可以写在[message]参数中。
  4. 上传合并分支:git push

2.2. 扩展流程

设置多个SSH key

由于该步骤比较常见,所以分类归到了基本流程当中,详情请查看2.1. 基本流程中的2.1.5. 设置多个SSH key

可只用默认的1个SSH key,不设多个,但当同时需要2个SSH的时候需要设置。因为GitHub的某一个SSH只允许一个账户或仓库使用,所以一个终端经常需要设置多个SSH。

删除分支

  1. git branch -d [branchname]
    普通删除,若没有合并分支,则不能删除。
  2. git branch -D [branchname]
    强制删除分支。

输入信息

输入提交信息
git commit时,若忘记填写-m参数,命令行会提示

Please enter the commit message for your changes.

此时需要在vim编辑器中按 I 键填写message,然后按Esc键,输入:wq,保存退出。

输入合并信息
git pullgit 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的修改提交章节。

转移提交

可使用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 pullgit 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

方案三:手动备份
先备份好本地写好的代码,然后放弃本地修改,然后进行pullmerge,然后再把要修改的文件直接覆盖掉,然后再进行提交。

暂存代码

暂存代码可通过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}

撤销更改

(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]

注意:必须有--hard参数;若没有--hard参数,则只是回退了commit,工作区的修改并不会回退。

回到过去
要回到过去,用git log可以查看提交历史和commit_id,以便确定回退版本。若要在log界面上下翻页,则按上下箭头(或回车)即可;要退出log界面,按字母键Q即可。

git log [--oneline]

重返未来
要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本,再用git reset命令重置为指定版本。

git reflog

强制推送
版本回退后,要强制推送到远程库才会起作用,否则只是本地库的版本回退,命令:

git push --force
# or
git push -f

commit_id(版本号)
当前版本为HEAD,上一个版本就是HEAD^HEAD~1,上上一个版本就是HEAD^^HEAD~2,当然往上100个版本写100个^并不容易,所以可以写成HEAD~100

可以使用HEADcommit_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 命令。

标签操作

基础操作

# 查看标签
git tag
# 查看标签具体信息
git show [tag_name]
# 查看远程标签
git ls-remote --tags
# 创建轻量标签
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

子模块

子模块即submodule,子模块允许将一个 Git 仓库嵌套在另一个 Git 仓库中。这对于管理项目中的依赖关系、使用外部库或者在一个仓库中包含另一个仓库的特定版本的代码非常有用。普通克隆时不会克隆子模块,需要使用特殊的命令克隆子模块。

克隆包含子模块的仓库

git clone --recursive [repository-url]

这将克隆包含子模块的存储库,并递归克隆并初始化子模块。

初始化子模块

git submodule update --init [--recursive]

如果已经通过普通命令克隆了包含子模块的存储库,可以使用此命令递归的初始化并更新子模块。
其中,--recursive代表递归的意思,使用此参数可以递归的初始化并更新子模块;若不使用此参数,则不会递归处理子模块的子模块,仅处理直接的子模块。

3. 本地库使用流程

Git也可仅使用本地库进行版本管理,不与远程库进行连接。本地库的版本管理不需要使用SSH key进行验证,也不需要进行clone,pull和push,即把远程库流程中的SSH key操作,clone,pull和push操作去掉即可变为本地库的流程。本地库使用流程如下:

3.1. 基本流程

  1. 本地仓库初始化(将当前目录设置为git仓库):git init

  2. 配置开发者的用户信息:

    git config --global user.name "userName"
    git config --global user.email "userEmail"
    

    以上为git全局的用户名和邮箱,不加--global即配置当前仓库的信息

  3. 创建和切换分支(初始化后默认为master分支):
    (1) 查看已有分支():git branch
    *和高亮的为当前分支
    (2) 创建分支:git branch [branchname]
    (3) 切换分支:git checkout [branchname]
    切换前需先进行提交(commit)。
    (4) 创建并切换分支:git checkout -b [branchname]

  4. 上传代码到本地库:
    (1) git status
    查看项目当前状态,也可以用git status -s简洁显示,一般与git diff命令配合使用,也可不查看状态直接进行git add。可在任何时刻使用git statusgit 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仓库的用户名和邮箱才能正常使用该命令。

  5. 合并分支:
    (1) 切换到主分支
    (2) 合并分支:git merge [branchname]
    branchname是要合并的分支名称

  6. 合并冲突
    在远程库的使用流程中也涉及,此处不再重复。

3.2. 扩展流程

扩展流程同远程库的扩展流程,这里不再赘述,内容如下:

  1. 删除分支
  2. 合并冲突
  3. 撤销更改
  4. 版本回退

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连接

  1. 下载安装Git Bash,下载地址:下载链接
  2. 打开Git Bash命令行,配置开发者的全局用户信息
    git config --global user.name "userName"
    git config --global user.email "userEmail"
    
    以上为git全局的用户名和邮箱,不加--global即配置当前仓库的信息。
  3. 打开IDEA软件,File/Configure -> Settings -> Version Control -> Git,在Path to Git executable中选择上一步Git Bash安装目录中的cmd文件夹下的git.exe文件。点击右侧的Test,会弹出Git Executed Successfully提示框。如下图:
    在这里插入图片描述
  4. File -> Setting -> Version Control -> GibHub中,Host填写github.com,点击Create API Token,输入在GitHub中注册的用户名和密码,然后会自动生成Token 。点击Test,测试是否连接成功。如下图。
    在这里插入图片描述

4.3. 集成Git使用流程(图形化操作)

使用时与远程仓库的使用流程大同小异,只是把命令行操作换成了图形化界面而已。其使用流程也分为2个方式,建立本地库和克隆远程库2种。

工作目录的状态

IDEA软件的工作目录中:
红色代表未被Git管理;
绿色代表以添加到缓存;
白色代表已提交至本地库;
蓝色代表已修改。

建立本地库方式

  1. 创建本地库
    打开IDEA软件,VCS -> Import into Version Control -> Create Git Repository,然后选择相应的项目目录。之后工作目录的文件会变红。
  2. 添加远程库
    VCS -> Git -> Remote,或右键项目Git -> Repository -> Remote,点击右侧的加号,填写NameURLName默认为OriginURL为远程仓库地址,可以是HTTPSSSH方式。
  3. 添加到缓存
    右键项目Git -> add,或快捷键Ctrl+Alt+A,将文件添加到Git缓存。
  4. 提交及推送
    右键项目Git -> Commit Directory,或快捷键Ctrl+K,或点击软件右上方的Commit按钮;输入Commit Message,若想节省时间,可以取消勾选Porform code analysisCheck TODO
    之后点击弹窗下方的Commit,或下拉箭头中的Commit and Push (Ctrl+Alt+K),即可完成提交或推送。如下图:
    在这里插入图片描述
  5. 从远程库拉取代码
    右键项目Git -> Repository -> Pull,选择相应的RemoteBranchStrategy,之后点击Pull即可。
    或者直接点击软件右上方的Update Project (Ctrl+T),选择相应的Update Type,点击OK即可。
  6. 分支操作
    在软件右下角的Git:后面会显示当前分支,点击此处,可以显示所有分支并进行切换(checkout即为切换),也可进行创建新分支,删除分支等操作。如下图:
    在这里插入图片描述
  7. 合并
    右键项目Git -> Repository -> Merge Changes
  8. 处理冲突
    可以选择接受哪个更改,也可以先合并,然后再手动更改,更改之后要进行addcommitpush
  9. 栈操作
    入栈:右键项目Git -> Repository -> Stash Changes
    出栈:右键项目Git -> Repository -> Unstash Changes
  10. 查看提交历史
    右键项目Git -> Show History,即可查看提交历史。
  11. 版本回退
    右键项目Git -> Repository -> Reset HEAD,在To commit中填写HEAD^HEAD~1进行版本回退,点击Validate按钮可以查看回退的版本信息。
    注意: 当前版本为HEAD,上一个版本就是HEAD^HEAD~1,上上一个版本就是HEAD^^HEAD~2,当然往上100个版本写100个^并不容易,所以可以写成HEAD~100

克隆远程库方式

  1. 从远程库克隆代码
    在IDEA的Welcome界面,选择Check out from Version Control -> Git,然后填写URLDirectoryURL为远程库地址,可以是HTTPSSSH方式。Directory为项目路径,必须是空文件夹。点击Clone即可克隆代码。

    在IDEA的项目界面下,VCS -> Git -> Clone或右键项目Git -> Repository -> Clone,可同样进入Clone界面。

  2. 其他操作
    其他操作与上一方式(建立本地库方式)相同。

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 [email protected]:WongJay/w3cschool.cn.git

查看当前的远程仓库

git remote
git remote -v

执行时加上 -v 参数,你还可以看到每个别名的实际链接地址,即SSH url

提取远程仓库

  1. 从远程仓库下载新分支与数据:
    git fetch [remotename] [branch]
    git merge [remotename] [branch]
    
    该命令执行完后需要执行git merge 远程分支到你所在的分支。在已经设置上流分支的情况下可省略 [remotename][branch][remotename]一般为origin
  2. 从远端仓库提取数据并尝试合并到当前分支(推荐):
    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. 其他命令

查看用户配置信息

  1. 查看所有配置
    git config -l
  2. 查看全局配置
    git config --global -l
  3. 查看指定配置
    git config user.name

状态

  1. 查看状态
    git status
  2. 简要查看状态
    git status -s
  3. 几种状态如下:
    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 命令显示已写入缓存与已修改但尚未写入缓存的改动的区别。

  1. 尚未缓存的改动:git diff
  2. 查看已缓存的改动: git diff --cached
  3. 查看已缓存的与未缓存的所有改动:git diff HEAD
  4. 显示摘要而非整个 diff:git diff --stat

分支

  1. 普通删除分支
    git branch -d [branchname]
  2. 强制删除分支
    git branch -D [branchname]

缓存

  1. 将单个或多个文件上传到缓存
    git add [filename] [filename2]
    filename为文件的路径及名称,可使用相对路径,文件夹符号使用“/”。
  2. 丢弃工作区的修改
    git checkout -- [filename]
  3. 取消缓存已缓存的内容
    git reset HEAD [filename]
  4. 将文件从缓存区中移除
    git rm [filename]
    默认情况下,git rm file 会将文件从缓存区和你的硬盘中(工作目录)删除。 如果要在工作目录中留着该文件,可以使用命令: git rm --cached [filename]
  5. 将文件夹从缓存区中移除
    git rm -r [dirname]

提交记录

  1. 查看提交历史
    git log
  2. 查看未来的提交历史
    git relog

重定基底(rebase)

  1. 合并提交(commit)
    (1) 将提交历史整理成一条直线
    git rebase
    (2) 合并最近4条合并记录
    git rebase -i HEAD~4
  2. 合并分支(在work分支下)
    git rebase master

Git栈(stash)

  1. git stash:备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中。
  2. git stash pop:从Git栈中读取最近一次保存的内容,恢复工作区的相关内容。由于可能存在多个Stash的内容,所以用栈来管理,pop会从最近的一个stash中读取内容并恢复。
  3. git stash list:显示Git栈内的所有备份,可以利用这个列表来决定从那个地方恢复。
  4. git stash clear:清空Git栈。此时使用gitg等图形化工具会发现,原来stash的哪些节点都消失了。

7. Git团队开发流程

说明

若开发团队比较大,各自负责各自的功能模块,则为了大家更规范的开发,可参考如下团队开发流程。
摘自简书博客:链接

分支命名规则

主分支:master
开发分支:developer
功能分支:feature - 分支名称
分支发布:release - 版本号
bug 分支修复:bugfix - 版本号

操作步骤

  1. 管理员「项目负责人」创建 git 仓库,建立 developer 分支
    git branch develop 
    git push -u origin develop
    
  2. 项目成员「开发者」clone 项目,在本地建立自己功能分支
    git clone 项目 git 地址 
    git checkout -b develop origin/develop
    
    # 创建本地功能分支
    git checkout -b feature-[name-desc] develop
    
  3. 在自己的分支上进行开发 : git addgit commit 等,注意此时不要 push 到远程分支(origin)。
  4. 功能完成后可以直接合并本地的 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]  # 删除本地分支
    
  5. 发布分支
    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
    
  6. 为 master 分支打发版 tag
    git checkout master 
    git tag -a 0.1 -m "Initial public release" master 
    git push --tags
    
  7. 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
    
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/NSJim/article/details/93794675

智能推荐

Oracle分区-程序员宅基地

文章浏览阅读6.4k次,点赞2次,收藏34次。ORACLE 分区分区的原因分区的优势分区方式分区sql说明:分区方式oracle 11g 支持自动分区,不过得在创建表时就设置好分区。分区的原因单表的数据量如果太大,会影响到读写性能。我们可以使用分库分表来解决单表的性能问题。Oracle的分区表是将一张大表在物理上分成几张较小的表,从逻辑上来看仍然是一张完整的表。这样每次DML操作可以只考虑其中一张分区表。oracle建议单表大小超过2GB时就使用分区表。分区功能能够将表、索引或索引组织表进一步细分为段,从而能够更精确地管理和访问这些数据库对象。_oracle分区

OKR的入门流程_titaokr运用教程-程序员宅基地

文章浏览阅读121次。您可以按照以下步骤创建有效的OKR流程:定义组织目标: 制定组织目标非常重要。您应该制定一到三个可以长期实现的目标。例如,如果您从事客户服务工作,那么您的目标可能是使客户满意度提高13%,并将客户呼叫时间减少两分钟。建立员工目标: 建立目标之后,您需要制定目标或实现目标的步骤。尝试将您的目标分成较小的目标,以创建可以遵循的时间表。如果您与团队合作,请确保将步骤告知他们,以确保您都可以朝着相同的目标努力。持续监控绩效和进度: OKR可以创建更有效的管理,但对于监控员工的进度和绩效也很重要。您应该监视进_titaokr运用教程

搭建jmeter分布式压测机_jmeter压测集群ip-程序员宅基地

文章浏览阅读1w次,点赞2次,收藏7次。一、前言 最近收到一个任务,需要压测某个后端服务接口,量级分别3W、6W、10W持续增量,然后就根据这个需求搭建了一个jmeter分布式负载机,其中也遇到不少坑,遂进行总结二、搭建分布式负载机集群本文采用A、B、C三台机器作为样式,A操控BC(集群)A为操控机,IP 192.168.1.1B为远程负载机,IP 192.168.1.2C为远程负载机,IP 192.168.1.3jmeter版_jmeter压测集群ip

平均曲率流(MCVF)-程序员宅基地

文章浏览阅读1.2w次。写在前面的话:今天听了一天的电,上午学习英语,下午在那里看《云革命》(Charles Babcock)著,挺不错的,让我对“云”这个晕的概念有了一定了解,关于读后感已经写在了笔记本上,就不再抄录。借此能上网的机会,学习一下平均曲率流。Alvarez等人提出了平均曲率流扩散方程:U被定义为灰度值函数,u0表示t=0时刻输入的灰度值函数。div(.)代表了图像上相等灰度值像素所组成的曲线的_平均曲率流

matlab仿真进程迁移,GUIDE 迁移策略-程序员宅基地

文章浏览阅读658次。将用 GUIDE 开发的 App 迁移到 App 设计工具将使用 GUIDE 创建的 App 迁移到 App 设计工具后,您可以继续以交互方式设计 App 的布局。您还可以利用增强的 UI 组件集和自动调整布局选项等功能,使您的 App 能够响应屏幕大小的变化。您还可以创建 App 并将其作为 Web App 进行共享(需要 MATLAB Compiler)。GUIDE to App Desig..._guide to app designer migration tool for matlab

计算机视觉课程 安装VSCode+python+opencv环境_vscode中怎么安装python opencv-程序员宅基地

文章浏览阅读4.2k次,点赞6次,收藏37次。计算机视觉课程(一)安装VSCode+python+opencv环境整个系统我配置了大约3个小时才基本搞定,由于在写博客前就已经安装完成,所以有的出错的地方无法截图展示。先声明一下,我安装的是VSCode+python+opencv,至于是否还有其他未知的兼容问题还需要我日后使用过程中慢慢总结。主要流程参考这个网址:https://blog.csdn.net/qq_21400315/artic..._vscode中怎么安装python opencv

随便推点

安卓app开发工具_软件开发常用的几款app开发工具-程序员宅基地

文章浏览阅读6.1k次,点赞5次,收藏47次。随着移动互联网的飞速发展,智能手机的普及化,手机app应用软件已经成为了人们生活中的一部分,APP开发行业也由过去的蓝海变成红海了。app软件开发的效率已经成为了目前开发行业的关键,如何才能快速提升app软件开发效率,这是每一位app软件开发工程师最为关心的问题了,那么如何才能提升软件的开发效率呢?这当然离不开一款好的app软件开发工具了。下面优匠科技为大家介绍几款目前APP定制开发市场的主流开发..._手机版软件开发工具

oracle转 mysql (数据库-语法篇)_oracle start with connect by 转化成mysql-程序员宅基地

文章浏览阅读1.2k次。oracle数据库 转 mysql 数据库1、rownum2、START WITH CONNECT BY PRIOR3、decode4、to_date1、rownumoracle:select u.name from u from wo where u.login_name = wo.APPLY_USER and rownum = 1 mysql: select u.name from u from wo where u.log_oracle start with connect by 转化成mysql

swiper轮播图的动画_swiper轮播动画-程序员宅基地

文章浏览阅读1.2k次。1. indicator-dots:是否显示小圆点,默认为false2. autoplay: 是否自动轮播3. interval:间隔时间多长4. duration: 动画时间5. circular:是否采用衔接滑动,也就是无缝滑动。6. vertical:是否纵向滑动,默认是横向滑动。7. display-multiple-items:同时显示的滑块数量,默认是1个。这里会出现一个问题,如果把值..._swiper轮播动画

CF1436 E. Complicated Computations MEX性质分析+权值线段树维护区间种类_线段树维护区间的种类-程序员宅基地

文章浏览阅读225次。思维量比较大的一道题,如果之前做过类似的就很简单,但没做过的话真的有点难想。。首先一个比较容易想到的点:从1枚举到n+1,用某种方法计算最终的MEX序列是否出现i。对于一个子数组[L,R],若其MEX等于x,则其必须满足:区间内不包含x,且区间内包含所有1 - x-1的数。关键点在于这里如何进行维护。我们可以这样做:对于区间不好含x这个限制我们可以每次取区间:(lst[a[i]],i),这样区间一定不包含a[i],而包含1 - x-1的数可以考虑用权值线段树维护:从左往右.._线段树维护区间的种类

机器学习白板推导(2)_白板推导 逻辑回归-程序员宅基地

文章浏览阅读1k次。4.Bayesian Network-具体模型Bayesian Network{ 单一:Naive Nayes⟶P(x∣y)=∏i=1pp(xi∣y=1)混合:GMM时间:{Markov ChainGuassian Process(无限维高斯分布)}动态模型 连续:Guassian Bayesian NetworkBayesian \ Network\begin{cases}\ \ 单一:Naive _白板推导 逻辑回归

VM中Windows server 2012 R2系统安装SQL SERVER 2012的安装步骤-程序员宅基地

文章浏览阅读955次。一、WINDOWS SERVER 2012 R2 的系统需要安装SQL SERVER 2012 以上的系统。(标红色的为注意事项)二、开始安装第一步:打开虚拟机设置,将下好的SQL2012的映像文件导入。(需要在选项中设置共享物理机的硬盘,即可导入文件)第二步:检查虚拟机中的驱动器是否连接第三步:打开控制面板中的程序(启用或关闭WINDOWS功能)第..._server 2012r2 sql 2012