Git 基本使用手册

初步设置

安装好 Git 后,第一步是设置 Git 的用户名和邮箱,如果没有设置用户名和邮箱是无法提交版本的,如下设置:

# 设置用户名
$ git config --global user.name "username"

# 设置用户邮箱
$ git config --global user.email "useremail@163.com"

然后是 其他设置

初始化项目

在安装并配置好 Git 的用户名和邮箱后,我们可以开始初始化项目的版本库,初始化项目版本库只需在项目目录下执行如下命令:

# 该命令为初始化版本库
$ git init

Laravel

执行 git init 后会在该项目目录下生成 .git 的隐藏目录, 该目录用于存放版本管理信息。

跟踪文件

初始化好项目后或修改文件后,就可以将文件进行跟踪提交到缓存区,以备下次提交到版本库中,如下操作将文件或目录提交到缓存区中。

# 提交文件
$ git add filename

# 提交目录
$ git add dirname/

# 或提交全部
$ git add .

Laravel

将文件提交到缓存区后,下一步就是将缓存区的内容提交到版本库中。

提交到版本库

当完成某个功能并使用 git add 将文件添加到缓存区后,接下来就是把这个功能提交到版本库中了, 使用如下命令:

# 将前面跟踪到缓存区的文件提交到版本库
$ git commit -m '功能描述'

Laravel

这样就完成了将代码跟踪到版本库中的操作了,然后就可以将本地代码 推送到远程仓库 分享给其他人了。

修改上一个版本信息

有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。此时,可以运行带有 --amend 选项的提交命令尝试重新提交:

$ git commit --amend

这个命令会将缓存区中的文件提交。如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令),那么快照会保持不变,所修改的只是提交信息。
文本编辑器启动后,可以看到之前的提交信息。编辑后保存会覆盖原来的提交信息。

如果提交后发现忘记了缓存某些需要的修改,可以像下面这样操作:

# 提交版本
$ git commit -m 'initial commit'
# 重新添加文件
$ git add forgotten_file
# 修改上一个版本并重新提交
$ git commit --amend
# 注意如果上一个版本已推送到远程仓库,禁止这样操作,否则你会被打残的。

查看文件状态

当你需要提交版本库时,应当先使用 git status 确认当前文件的跟踪状态。
如下命令:

# 该命令查看文件跟踪的状态, 哪些文件已跟踪哪些文件未跟踪。
$ git status

注意:当将文件提交到版本库中后,使用 git status 是查看不到已提交到版本库中的信息的,当缓存区信息为空时表示已没有修改文件可提交了。

忽略文件

一般总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。在这种情况下,可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。

示例:

$ cat .gitignore
TEST.md
*.log

第一行告诉 Git 忽略 TEST.md 文件。第二行告诉 Git 忽略所有以 .log 结尾的文件。要养成一开始就设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。

文件 .gitignore 的格式规范如下:

  • 所有空行或者以 # 开头的行都会被 Git 忽略。
  • 可以使用标准的 glob 模式匹配。
  • 匹配模式可以以/开头防止递归。
  • 匹配模式可以以/结尾指定目录。
  • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号!取反。

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号 * 匹配零个或多个任意字符; [abc] 匹配任何一个列在方括号中的字符( 这个例子要么匹配一个a , 要么匹配一个b, 要么匹配一个c); 问号 ? 只匹配一个任意字符; 如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配( 比如 [0-9] 表示匹配所有 0 到 9 的数字 )。 使用两个星号 * 表示匹配任意中间目录, 比如 a/**/z 可以匹配 a/z, a/b/z 或 a/b/c/z 等。

GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表,可以在 GitHub 找到它.

查看历史提交记录

需要查看历史的提交列表信息使用 git log 命令。

# 查看提交的版本列表
$ git log

可以使用 -p 显示每次提交的内容差异,也可以加上 -2 来仅显示最近两次提交:

$ git log -p -2

如果想看到每次提交的简略的统计信息,可以使用 --stat 选项:

$ git log --stat

或者查看某个文件的提交列表:

$ git log filename

工作区/缓存区

工作区(Working Directory)
工作区就是你修改文件下的目录就是一个工作区, 工作区有一个隐藏目录 .git, 这个不算工作区, 而是 git 的版本库。
Git 的版本库里存了很多东西,其中最重要的就是称为 stage(或者叫index)的缓存区,还有 Git 为我们自动创建的第一个分支 master,以及指向 master 的一个指针叫 HEAD。

文件往 git 版本库提交的时候,分两步执行。

  • 第一步 git add 把文件提交到缓存区.
  • 第二步 git commit -m '****' 把缓存区内容提交到版本库分支。

如下图提交流程:

Laravel
Laravel

注意: 修改的文件只有 git add 提交到缓存区后才能被 git commit -m '***' 提交到版本库里, 否则工作区的内容是提交不到版本库内。

查看已缓存/未缓存信息

有时候我们需要查看修改了文件的哪些内容,可以使用以下命令查看。

$ git diff filename

如果要查看缓存区内与上次提交之间的差别呢?这就需要使用到 --cached 参数:

$ git diff --cached

注意:当将文件提交到版本库中后,使用 git diffgit diff --cached 也不会有任何输出.

还可以使用 git diff 来查看两个分支的差异。
命令如下:

# 该命令是分支和分支的比较
$ git diff <分支名称> <分支名称>

如果需要查看当前工作区和最新的版本的区别,则可以使用如下命令:

# 查看当前 filename 文件在工作区与最新版本的一个区别
$ git diff HEAD -- filename

撤销修改

当我们在项目中新增了功能修改而后又不需要此次修改的时候,我们就需要将当前的修改全部撤销或撤销部分文件修改。

撤销缓存区的修改

当修改已提交到缓存区后需要使用 git reset HEAD filename 命令将文件撤回到工作区:

# 将缓存区的 file.txt 文件撤回到工作区中
$ git reset HEAD file.txt

将修改撤回到工作区中后,到这里还没有将修改的内容彻底撤回。只是在提交版本库的时候不会将缓存区撤回的内容提交到版本库中,但是修改内容依然还在,只是在工作区中而已。

git reset 命令既可以回退版本,也可以把缓存区的修改回退到工作区。当我们用 HEAD 时,表示最新的版本。

撤销工作区修改

下面就是撤回在工作区中的修改内容。
当修改后的内容在工作区中不需要的时候,使用 git checkout -- filename 命令将工作区中的修改文件内容撤销掉。

丢弃工作区的修改:

# 丢弃 file.txt 文件中的修改
$ git checkout -- file.txt

git checkout -- file.txt 意思就是把 file.txt 文件在工作区的修改全部撤销, 这里有两种情况:

  • 一种是 file.txt 自修改后还没有被放到缓存区,现在,撤销修改就回到和版本库一模一样的状态;
  • 一种是 file.txt 已经添加到缓存区后,又作了修改,现在,撤销修改就回到添加到缓存区后的状态。总之,就是让这个文件回到最近一次 git commitgit add 时的状态。

移除文件

从版本库中移除文件

要从 Git 中移除某个文件, 就必须要从已跟踪文件清单中移除(确切地说, 是从缓存区域移除)然后提交。
可以用 git rm 命令完成此项工作, 并连带从工作目录中删除指定的文件, 这样以后就不会出现在未跟踪文件清单中了。

如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changes not staged for commit” 部分(也就是 未缓存清单)看到:

$ rm TESTS.md

$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
        deleted:    TESTS.md
no changes added to commit (use "git add" and/or "git commit -a")

然后再运行 git rm 记录此次移除文件的操作:

$ git rm TESTS.md
rm 'TESTS.md'

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        deleted:    TESTS.md

下一次提交时, 该文件就不再纳入版本管理了。如果删除之前修改过并且已经放到缓存区域的话,则必须要用强制删除选项 -f (译注:即 force 的首字母)。这是一种安全特性, 用于防止误删还没有添加到快照的数据, 这样的数据不能被 Git 恢复。

还有一种情况是, 把文件从 Git 仓库中删除(亦即从缓存区域移除), 但需要保留在当前工作目录中。为达到这一目的, 使用 --cached 选项:

# 只是从仓库记录中删除
$ git rm --cached README.md

git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式。比如说:

$ git rm log/\*.log

版本回退

在我们的项目中,当发布一个新版本后发现有严重的BUG时,我们就需要将项目回退到稳定的旧版本中,或者是我们提交的新版本功能已经不需要了,这时我们也需要将版本回退掉。
接下来开始讲解如何回退版本。

回退到指定版本

首先要讲的是最简单的一个回退到上一个版本命令 git reset --hard HEAD^,该命令只是单纯的将版本回退到上一个版本中。

# 回退到上一个版本中
$ git reset --hard HEAD^

如果需要回退到再上一个版本中只需在 HEAD 的后面再加一个 ^ 符号即可,如下。

# 回退到上上一个版本中
$ git reset --hard HEAD^^

需要回退到上几个版本就可以在 HEAD 后面加几个 ^

如果要回退到 10 或 100 个以上版本中该如何呢?我们可以写成这样 HEAD~100

# 回退到前100个版本中
$ git reset --hard HEAD~100

或者使用 commit id 回退到指定的版本中。

$ git reset --hard 1094a

回退文件到指定版本

当在项目开发中提交一个版本后发现该版本中有几个文件的修改已经不需要了,我们可以使用 git checkout <commit id> filename 命令来单独来回退指定文件的版本,而不影响整个提交的版本。

# 回退 index.txt 文件至 2dc9de54f352e754 版本
$ git checkout 2dc9de54f352e754 index.txt

# 回退后需要提交新版本
$ git commit -m "回退文件"

也可回退整个目录,只需将 index.txt 文件名改成目录名即可。

回退远程仓库的版本

删除最后一次提交:

# 回退一次提交
$ git revert HEAD
# 推送分支
$ git push origin master

使用 revert 回退还可以使用以下方式:

# 回退到上上个版本
$ git revert HEAD^

# 回退到3个版本前
$ git revert HEAD~3

# 回退到指定的 commit id
$ git revert 0818bad

回退版本强制推送:

# 回退版本
$ git reset --hard HEAD^

# 强制推送 master 分支
$ git push origin master -f

不推荐使用该方式,强制推送会导致项目的其他人合并混乱。

远程仓库管理

克隆远程仓库

在一个项目需要多人协助开发时就需要用到远程仓库,将远程仓库的代码下载到本地可以使用 git clone 命令。

$ git clone https://github.com/xueyong-q/docker-database.git

克隆时还可以指定在本地克隆后的项目名称。

$ git clone https://github.com/xueyong-q/docker-database.git MyProject

克隆后会将代码保存在 MyProject 目录下,也可以将 MyProject 换成 . 表示克隆到当前目录下。

关联远程仓库

有时候我们会先在本地新建好项目,然后再新建仓库,这样的话就需要将本地的项目关联到新仓库中:

$ git remote add origin https://github.com/xueyong-q/docker-database.git

关联好远程仓库后,下一步就是把本地仓库内容推送到远程仓库:

# 第一次推送远程仓库时需要加上 -u 参数
$ git push -u origin master

把本地库的内容推送到远程,用 git push 命令,实际上是把当前分支 master 推送到远程。
第一次推送 master 分支时,加上 -u 参数,Git 不但会把本地的 master 分支内容推送的远程新的 master 分支,还会把本地的 master 分支和远程的 master 分支关联起来,在以后的推送或者拉取时就可以简化命令。

现在只要本地做了提交, 下次就可以使用如下命令推送到远程仓库了:

$ git push origin master

当远程仓库有新的修改时可以使用 git pull 命令同步并合并下来。
当多人协作时,提交到远程仓库前,最好使用 git pull 合并远程仓库的修改再提交到远程仓库。
当多人协作时可能会遇到提交冲突,使用 git pull 合并远程仓库可以在本地解决冲突再提交到远程仓库。

更换远程仓库

当我们需要将旧项目更换到一个新的仓库中时,就只需将本地项目的远程仓库地址更换为新仓库地址即可。

# 更换远程地址
$ git remote set-url origin https://github.com/xueyong-q/docker-nginx-php.git

# 然后推送分支
$ git push -u origin master

分支管理

Git 的分支模型这一特性,使的 Git 能从众多版本控制系统中脱颖而出。Git 处理分支的方式是难以置信的轻量,创建分支几乎能在瞬间完成,不同分支之间切换也是一样便捷的, Git 鼓励在工作流中频繁的使用分支与合并。

查看项目分支列表命令:

$ git branch

分支前面有一个 * 号表示当前所在的分支。

创建分支

简单创建分支命令 git branch <分支名称>

# 新建 develop 分支
$ git branch develop

创建并切换分支命令 git checkout -b <分支名称>

# 创建并切换到 develop 分支
$ git checkout -b develop

合并分支

简单的合并一个分支,如这里有两个分支 master、develop,当前所在分支为 master 需要合并 develop 分支的内容:

# 将 develop 分支的内容合并到 master 分支上
$ git merge develop

解决合并冲突

当两个分支都有不一样的提交时合并分支就有可能会产生冲突。当产生冲突后可使用 git status 查看冲突的文件,在文件内, Git 用 <<<<<<<,=======,>>>>>>> 标记出不同分支的内容需要我们手动去修改,然后保存提交。

删除分支

删除一个分支使用如下命令。

# 删除 develop 分支
$ git branch -d develop

如果一个分支有修改内容还未提交或有内容未合并,则无法直接删除,如果确定需要删除则使用 -D 参数来强制删除。

# 强制删除 develop 分支
$ git branch -D develop

关联远程分支

为了方便推送代码和拉取代码,可以将本地的分支与远程仓库的分支进行关联。关联远程分支命令 git branch --set-upstream-to=origin/<远程分支名称> <本地分支名称>

# 将本地的 develop 分支与远程的 develop 分支关联
$ git branch --set-upstream-to=origin/develop develop

分支管理策略

  • master 分支应该是非常稳定的,也就是仅用来发布稳定的版本,不能在上面进行工作。
  • develop 分支用于新功能测试分支,将新开发的功能或修复的 BUG 合并到该分支进行测试,待稳定后合并到 master 分支中。
  • mydev 你的开发分支,就是你在本地干活的分支,分支名称可以自定义。

BUG分支

bug 修复时的临时分支。
当需要修复一个 bug, 而当前工作分支还没提交时, 可以使用 stash 功能把当前工作区 “储藏” 起来,等以后恢复后继续工作。

# 暂存当前的修改
$ git stash

然后创建一个分支来修复 bug。
修复 bug 后就可以恢复刚刚暂存的修改继续工作。

# 查看刚刚储存的工作区
$ git stash list

# 恢复,但是恢复后,stash 内容并不删除
$ git stash apply

# 恢复的同时把 stash 内容也删了
$ git stash pop

# 可以多次 stash,恢复的时候,先用 git stash list 查看,然后恢复指定的 stash,用命令
# 恢复 stash@{0} 条目
$ git stash apply stash@{0}

显示存储项中记录的更改内容

# 查看 stash@{1} 条目内的修改内容
$ git stash show -p stash@{1}

从存储条目列表中删除一个存储条目:

# 删除 stash@{1} 条目
$ git stash drop stash@{1}

清除所有储藏条目:

# 注意这会清除所有的条目
$ git stash clear

Feature分支

添加一个新功能,最好新建一个 feature 分支,在上面开发。
在开发完成并合并后,即可将该分支删除。

标签管理

为项目打标签:

# 添加简单标签 v1.0
$ git tag v1.0

# 添加附注标签
$ git tag -a v1.0.0 -m '标签说明'

# 查看所有标签
$ git tag

# 查看v1.0标签详细信息
$ git show v1.0

一般我们打标签时应该选择使用附注标签。

子模块

当一个项目需要分成多个仓库来管理时,就需要使用 Git 的子模块来管理更方便。

添加子模块

可以通过在 git submodule add 命令后面加上想要跟踪的项目的相对或绝对 URL 来添加新的子模块。

# 在当前目录下添加一个名为 DbConnector 的子模块
$ git submodule add https://github.com/chaconinc/DbConnector

# 添加后就可以初始化配置并将代码拉取下来
$ git submodule init

# 抓取并检出子模块
$ git submodule update

这样子模块就添加完成。

也可将子模块添加到其他目录下:

# 在当前的 base 目录下添加一个名为 DbConnector 的子模块
$ git submodule add https://github.com/chaconinc/DbConnector base/DbConnector

如果这时运行 git status,你会注意到几件事。

$ git status

On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
  new file: .gitmodules
  new file: DbConnector

添加子模块后新增了 .gitmodulesDbConnector 这两个文件,然后将它们提交至版本库中即可。

同步子模块

在克隆一个包含子模块的新项目后,子模块中是空的需要我们去手动拉取。
必须运行两个命令:git submodule init 用来初始化本地配置文件,而 git submodule update 则从该项目中抓取所有数据并检出父项目中列出的合适的提交。

# 初始化本地配置,如已初始化则可以跳过
$ git submodule init

# 抓取并检出子模块
$ git submodule update

目录转换为子模块

在需要将目录转换为子模块时需要注意,一定先从 git 仓库中删除该文件或目录:

# 先从仓库删除该目录
$ git rm -r DbConnector

# 然后在当前目录下添加一个名为 DbConnector 的子模块
$ git submodule add https://github.com/chaconinc/DbConnector

其他设置

生成SSH密钥

本地生成 SSH 密钥

$ ssh-keygen -t rsa

执行以上命令会在用户 home 目录下的 .ssh 目录中生成 id_rsaid_rsa.pub 文件, 其中 id_rsa 为私钥 id_rsa.pub 为公钥, 把 d_rsa.pub 的内容添加到仓库平台的 SSH 证书配置中。 这样推送代码至远程仓库就不需要使用密码.

CRLF换行符

windows 系统下请设置:

# 提交时转换成 LF,签出时转换为 CRLF
$ git config --global core.autocrlf true

Linux & Mac 系统下配置:

# 表示检出时不转换,提交时转换为 LF
$ git config --global core.autocrlf input

查看版本状态中文无法显示

在 Windows 平台下执行 git status 中文转义致乱码的解决方案。
core.quotepath 设为 false 的话,就不会对 0x80 以上的字符进行 quote。中文显示正常。

$ git config --global core.quotepath false

版本库权限跟踪设置

当开启版本库权限跟踪时,修改了文件的权限 Git 会对其进行跟踪。
当关闭版本库权限跟踪时,只修改了文件的权限 Git 就不会对其进行跟踪。

# 当前版本库设置
$ git config core.filemode false

# 全局设置
$ git config --global core.filemode false

Git缓存GitHub登录凭据

在终端下使用 HTTPS 克隆的 GitHub 仓库推送代码时经常会弹出要我们登录,下面我们可以设置凭据缓存来减少登录次数。

设置 Git 缓存凭据:

$ git config --global credential.helper cache

也可以设置缓存凭据时间。

$ git config --global credential.helper 'cache --timeout=3600' # 这里缓存一小时

学习资料

git
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 1年前 自动加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 3

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!