文章

git操作

记录git的基础/常用操作,以备查阅

参考/推荐

廖雪峰的Git教程

Git菜鸟教程

Learn Git Branching

Game of Git

Playground

基础操作

基础操作

git各个区域及基础操作:

image.png git区域与基础操作

注意: pull = fetch + merge 即拉取远程仓库的内容并合并到本地仓库

遇到的小问题

有时候可能会因为种种原因无法连接到remote,这时可以尝试以下方法:

查看git的ssh连接状态, 可以使用ssh -v -T命令:

1
2
3
4
$ ssh -v -T # 查看ssh连接状态, -v: verbose, -T: 不分配伪终端
$ ssh -vT # 与上面命令等价

$ ssh ... -v # 使用verbose模式运行其他git命令

设置git代理:

1
2
3
4
5
6
7
8
9
10
11
# 一次性代理
git -c http.proxy="https://1.2.3.4:1234" clone <repo-url>
# 设置全局代理
git config --global http.proxy https://1.2.3.4:1234
git config --global https.proxy https://1.2.3.4:1234
# 设置socks5代理
git config --global http.proxy socks5://1.2.3.4:1234
# 只对github.com设置代理
git config --global http.https://github.com.proxy http://1.2.3.4:1234
git config --global https.https://github.com.proxy http://1.2.3.4:1234
git config --global http.https://github.com.proxy socks5://1.2.3.4:1234

git初始化

1
2
3
4
5
$ git init    # 初始化仓库
$ git clone # 从remote克隆一个仓库到本地
$ git add .    # 把所有文件添加到staging area
$ git commit . # 将staging area 中所有内容提交到 local repository
$ git commit . -m <message> # 将staging area 中所有内容提交到 local repository,且快速添加信息

加入暂存区

1
2
3
$ git add <file> # 将指定文件添加到暂存区
$ git add . # 将所有文件添加到暂存区
$ git add -p # 交互式按块添加文件到暂存区(逐个文件交互式添加)

状态查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ git status # 查看当前状态
$ git log # 查看日志
$ git shortlog # 查看短日志

$ git reflog # 查看历史操作记录
$ git reflog -2 # 查看最近两次操作记录
$ git reflog -2 <branch-name> # 查看branch-name分支的最近两次操作记录

$ git diff # 查看工作区与暂存区的差异
$ git blame <file> # 以列表形式查看指定文件的历史修改记录

$ git show <commit-id> # 查看指定commit-id的提交记录
$ git show <commit-id> <file> # 查看指定commit-id的指定文件的提交记录
$ git show HEAD~2 # 查看倒数第二次提交记录
$ git show <tag-name> # 查看指定tag的提交记录

分支操作

1
2
3
$ git checkout -b <new-branch-name> # 创建新分支
$ git checkout <branch-name> # 切换(检出)到指定分支
$ git checkout master^^ # 切换到master分支的上上个版本
1
2
3
4
$ git branch # 查看本地所有分支
$ git branch -r # 查看remote上的分支
$ git branch -a # 查看所有(本地+remote)分支
$ git branch -d <branch-name> # 删除指定分支
1
2
$ git merge <branchA> # 将branchA合并到当前分支
# 注意: merg时可能会出现分支冲突,这时需要手动add 有冲突的文件

switch指令专门用来简化分支移动操作:

1
2
$ git switch <branch-name> # 切换到指定分支
$ git switch -c <new-branch> # 创建并切换到新分支

回退版本

1
2
3
4
$ git reset [--hard] HEAD^ # 回退一个版本
$ git reset [--hard] HEAD^^ # 回退两个版本
$ git reset [--hard] HEAD~n # 回退n个版本
$ git reset [--hard] <commit-id> # 回退到指定版本

reset指令的三种模式:

  • –soft: 仅仅在本地移动HEAD指针,不改变暂存区和工作区
  • –mixed: 默认模式,移动HEAD指针和暂存区,不改变工作区
  • –hard: 移动HEAD指针、暂存区和工作区

reset也可以用于回退后又想恢复的情况,可以通过git reflog查看历史操作记录,然后通过git reset --hard <commit-id>恢复:

1
2
$ git reflog # 查看历史操作记录
$ git reset --hard <commit-id> # 恢复到指定版本

文件删改

1
2
3
4
$ git rm <file> # 删除文件
$ git mv <old-file> <new-file> # 重命名文件
$ git checkout -- <file> # 撤销工作区的修改
$ git diff # 查看工作区与暂存区的差异

远程操作

在 Git 中,origin 是默认的远程仓库的名称。当你克隆一个远程仓库到本地时,Git 会自动创建一个名为 origin 的远程仓库别名,指向原始的远程仓库。

1
2
3
4
5
6
7
$ git remote add origin <remote-url> # 添加远程仓库
$ git -T <remote-url> # 测试远程仓库是否连接成功
$ git remote -v # 查看远程仓库
$ git push origin <branch-name> # 将本地HEAD所在节点分支推送到远程仓库<branch-name>分支
$ git pull origin <branch-name> # 从远程仓库拉取<branch-name>分支到本地HEAD所在节点分支(工作区)
$ git push origin --delete <branch-name> # 删除远程仓库<branch-name>分支
$ git merge origin/<branch-name> # 将远程仓库<branch-name>分支合并到本地HEAD所在节点分支

HEAD指针

HEAD 指针是一个指向当前所在分支的指针,它通常指向最近一次提交的结果。

我们最好要避免出现 HEAD 指针指向一个分离状态,这种状态下,HEAD 指针不再指向任何分支,而是直接指向一个提交。摆脱分离:git switch <branch-name>

1
2
$ git checkout HEAD <file> # 撤销工作区的修改,相当于将HEAD指针的内容覆盖到工作区
$ git reset HEAD <file> # 撤销暂存区的修改,相当于将HEAD指针的内容覆盖到暂存区

标签操作

1
2
3
$ git tag # 查看所有标签
$ git tag <tag-name> # 创建标签,默认为HEAD所在节点
$ git checkout tags/tagname # 切换到指定tag的分支

冲突解决

一般情况下,冲突解决的步骤如下:

  1. git pull 拉取远程仓库的内容
  2. git status 查看冲突文件; git diff 查看冲突文件的具体内容
  3. 手动解决冲突文件:
    • 对于冲突文件,会有类似如下的标记:
      1
      2
      3
      4
      5
      
      <<<<<<< HEAD
      本地仓库的内容
      =======
      远程仓库的内容
      >>>>>>> 123456
      

      我们在解决冲突时,需要手动删除标记(即<<<<<<< HEAD=======>>>>>>> 123456),并保留需要的内容。

      或者使用Vscdoe等IDE的冲突解决工具。

    • 对于我们在git pull后一些本地分支上的文件因为pull而丢失,我们可以使用git checkout -- <file>来撤销工作区的修改,然后再手动解决冲突文件。可以遵循以下步骤:
      1
      2
      3
      4
      5
      6
      
      $ git log # 查看提交记录的hash 或者使用git reflog查看历史操作记录
      $ git show <commit-hash> # 查看提交记录的详细信息
      $ git checkout <commit-hash> -- <file> # 恢复指定文件
      $ git add <file> # 添加冲突文件
      $ git commit -m "恢复丢失的文件" # 提交冲突文件
      $ git push # 推送到远程仓库
      
  4. git add <file> 添加冲突文件
  5. git commit -m <message> 提交冲突文件
  6. git push 推送到远程仓库

添加子模块/子仓库

子模块是一个独立的仓库,可以被添加到主仓库中。子模块的内容可以独立于主仓库的内容进行更新和修改。

git submodule 命令用于管理包含其他Git仓库的项目。

初始化子模块

1
2
3
4
5
6
7
8
9
$ git submodule int # 添加子模块

# 常使用以下流程初始化子模块:
$ git clone <repo-url> # 克隆子模块仓库
$ cd <submodule-dir> # 进入子模块目录
$ git submodule init # 初始化子模块

# 或者使用以下命令直接add并初始化子模块:
$ git submodule add <repo-url> [<submodule-dir>] # 添加子模块

更新子模块

1
2
3
$ git submodule update # 更新子模块
$ git submodule update --remote # 更新子模块并拉取远程仓库的内容
$ git submodule update --recursive --remote # 更新子模块并递归更新子模块的子模块

添加子模块

1
$ git submodule add <repo-url> [<submodule-dir>] # 添加子模块

删除子模块

1
2
$ git submodule deinit <submodule-dir> # 删除子模块
$ git rm <submodule-dir> # 删除子模块

查看子模块

1
2
$ git submodule # 查看子模块
$ git submodule status # 查看子模块状态

使用.gitmodules文件

.gitmodules 文件用于指定子模块的地址、路径等信息。

1
2
3
[submodule "submodule-name"]
    path = submodule-path
    url = submodule-url

相关配置文件

.gitignore

.gitignore 文件用于指定不需要加入版本控制的文件,比如编译生成的文件、日志文件、临时文件等。

# 忽略所有 .a 结尾的文件
*.a

# 但是 lib.a 除外
!lib.a

# 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
/TODO

# 忽略 build/ 目录下的所有文件
build/

# 忽略 doc/notes.txt 文件,但不忽略 doc/server/arch.txt 文件
doc/*.txt

# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf

.gitattributes

.gitattributes 文件用于指定文件的属性,比如文本文件、二进制文件、换行符等。

# 设置所有文件以文本文件处理
* text=auto

# 设置所有文件以二进制文件处理
*.bin binary

# 设置所有文件以文本文件处理,且换行符为LF(即\n)
* text eol=lf

# 设置所有文件以文本文件处理,且换行符为CRLF(即\r\n)
* text eol=crlf

.gitmodules

.gitmodules 文件用于指定子模块的地址、路径等信息。

[submodule "submodule-name"]
    path = submodule-path
    url = submodule-url

git Flow工作流

img

  • master 分支
    • 永远保持稳定和可发布的状态。
    • 每次发布一个新的版本时,都会从 develop 分支合并到 master 分支。
  • hotfix 分支
    • 用于修复紧急问题。
    • 从 master 分支创建,修复完成后合并回 master 和 develop 分支,并打上版本标签。
    • 命名规范:hotfix/hotfix-name。
  • release 分支
    • 用于准备新版本的发布。
    • 从 develop 分支创建,进行最后的测试和修复,然后合并回 develop 和 master 分支,并打上版本标签。
    • 命名规范:release/release-name。
  • develop 分支
    • 用于集成所有的开发分支。
    • 代表了最新的开发进度。
    • 功能分支、发布分支和修复分支都从这里分支出去,最终合并回这里。
  • feature 分支
    • 用于开发新功能。
    • 从 develop 分支创建,开发完成后合并回 develop 分支。
    • 命名规范:feature/feature-name。
本文由作者按照 CC BY 4.0 进行授权