【Git 学习笔记】第二章 Git 的配置(下)

2.5 几个配置示例

2.5.1 变基(rebase)与合并(merge)设置

默认情况下,在执行 git pull 时,如果本地分支的历史记录与远程分支的历史不同,则会进行合并提交。修改默认方式可使用:

bash 复制代码
# use rebase instead of merge: true / false
$ git config pull.rebase true

切换分支时,取消默认按合并(merge)的方式进行分支切换:

bash 复制代码
# never(default) lacal remote always
$ git config branch.autosetuprebase always

设置具体某分支在执行 git pull 操作时按 git rebase 进行:

bash 复制代码
# pattern: branch.<name>.rebase approach
$ git config branch.feature/2.rebase true

2.5.2 有效期设置

默认情况下,Git 将对未引用对象执行垃圾回收,并对为超过 90 天的 reflog 条目进行清理。一个 git 对象必须被其他对象引用,这个其他对象可以是一个 tree 树,一个 tag 标签,一个 branch 分支,或者其他 Git 内部簿记,如 stashreflog。有三个配置项可对有效期进行设置:

  • gc.reflogexpire
  • gc.reflogexpireunreachable
  • gc.pruneexpire
bash 复制代码
# To set a non-default expiry date on remote branches only
$ git config gc./refs/remote/*.reflogexpire never
# How long the reflog entries that are not a part of the current branch history should be available in the repository, 30d by default:
$ git config gc./refs/remote/*.reflogexpireunreachable "2 months"
# Set a date so git gc will prune objects sooner
$ git config gc.pruneexpire 3.days.ago

2.5.3 设置自动更正

出现笔误时 git 会自动提示:

可以设置自动更正的时间间隔,单位 厘秒(0.1秒):

bash 复制代码
$ git config help.autocorrect 5
$ git statis
WARNING: You called a Git command named 'statis', which does not exist.
Continuing under the assumption that you meant 'status'
in 0.5 seconds automatically...
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   another-file.txt
#

实测效果:(设为 3 秒后自动更正)

2.6 设置 Git 别名

设置常见通用别名:

bash 复制代码
$ git config --global alias.co checkout 
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status

新增自定义别名:让某文件取消暂存

bash 复制代码
# pattern: git unstage <FILE>...
$ git config --global alias.unstage 'reset HEAD --'

# Test
$ echo "Something new" >> .\README.md
$ git unstage .\README.md
Unstaged changes after reset:
M       README.md
$ git unstage .\README.md
Unstaged changes after reset:
M       README.md
$ git st
On branch master
Your branch is behind 'origin/master' by 5729 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

实测截图:

更常见的是将自定义的 git 格式化后的日志形式存为一个别名:

bash 复制代码
$ git config --global alias.ll "log --pretty=format:'%C(yellow)%h%Cred%d %Creset%s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --numstat"

实测效果:

git 也可以为自定义的外部脚本设置别名,此时别名内容前需要加感叹号 !。示例如下:

bash 复制代码
# add the line onto your ~/.gitconfig file
editconflicted = "!f() {git ls-files --unmerged | cut -f2 | sort -u ; }; $EDITOR 'f'"

这段脚本会打开预设的编辑器,其中包含由于合并或变基而处于冲突状态的所有文件。 该操作可以快速修复冲突并继续合并/变基。

测试如下:

bash 复制代码
$ git branch A 03f78fc
$ git branch B 9891497
$ git checkout A
Switched to branch 'A'
$ git merge B  
# conflicts found, and a list of conlicted files print out
# Resolve all these files and then run the script
$ git editconflicted
# Check the status
$ git st
# then commit to resolve merge
$ git ci

另一种创建 Git 别名的方法,是新建一个 shell 脚本,并使用名称 git-<your-alias-name> 保存。 设置文件权限为 可执行 ,并将其放在 $PATH 某一路径下,用命令行运行 git <your-alias-name> 看到相应结果。

查看当前定义的所有别名:

bash 复制代码
# Linux
$ git config --list | grep alias
# Powershell
> git config --list | where {$_ -match "alias"}

2.7 refspec 举例

设置 git 时,很难第一时间就想到 refspec,因为它通常是在执行 git 命令时被隐式调用。当执行仓库复制或添加远程分支时,.git/config 文件会有类似配置:

ini 复制代码
[remote "origin"]
  url = https://git.eclipse.org/r/jgit/jgit
  fetch = +refs/heads/*:refs/remotes/origin/*

其中 fetch 这行就包含了该仓库执行 fetch 时的 refspec

本例将在本地创建一个 bare 仓库(工作目录为空的仓库),以便示例代码执行 push 操作(否则会覆盖目标仓库的工作区(work area)和索引(index)。

bash 复制代码
# Create bare repo from Eclipse remote repo
$ git clone --bare https://git.eclipse.org/r/jgit/jgit jgit-bare.git
# Init local repo for demo
$ git init refspec-tests
Initialized empty Git repository in /Users/john.doe/refspec-tests/.git/
# Add remote origin for the local repo
$ cd refspec-tests
$ git remote add origin ../jgit-bare.git
# Enter the bare repo and rename "stable-*" branches into "stable/*"
$ cd ../jgit-bare.git && for br in $(git branch  -a | grep "stable-"); do new=$(echo $br| sed 's/-/\//'); git branch $new $br; done

这里发现两处笔误:

  1. Linux 环境下执行 sed 命令,替换为目标字符串的 / 需要转义,写作 \/,书中写为 /
  2. 远程分支的重命名,应该在 bare 仓库中进行,原书中少了一句 cd ../jgit-bare.git。反馈给作者核实后,两处笔误均已更正。
  3. 实测时由于与作者成书时的间隔已有三年多之久,这其间 jgit 库一直在更新;加上国内网络环境查,无法按照书中的命令在线同步 jgit 代码库。变通办法为:先同步 jgit 远程库到本地,然后重命名 stable 分支,再以此为基础创建 bare 仓库。如果本地库不预先拉取 jgit 的所有远程分支,拷贝 bare 库时将丢失所有远程分支。切记!

关于离线版的准备工作,操作如下:

bash 复制代码
# ... get local copy of jgit repo, named demo ... (by fortune)
# Rename branches: e.g. stable-1.2 --> stable/1.2
$ cd ./demo && for br in $(git branch  -a | grep "stable-"); do new=$(echo $br | sed 's/-/\//'); git branch $new $br; done
# clone bare repo based on local 'demo' repo
$ cd .. && git clone --bare ./demo jgit-bare.git
# ... (same as mentioned above)

再次强调

再次强调

再次强调

从本地仓库新建 bare 库时,数据源仓库的 所有本地分支 将作为 bare 库的远程跟踪分支(remote-tracking branch),被后续基于该 bare 库的其他衍生仓库查询出来。因此第 2 步中必须先将示例要用到的所有分支(即所有带 stable- 前缀的分支)签出。


示例一:只同步拉取 master 分支

ini 复制代码
# Edit .git/config file: heads/* --> heads/master; origin/* --> origin/master
[remote "origin"]
  url = ../jgit-bare.git
  fetch = +refs/heads/master:refs/remotes/origin/master

设置生效后,执行如下命令将只对 master 分支生效:

  • git fetch
  • git pull
  • git remote update origin

示例二:只同步带 stable 字样的分支

ini 复制代码
[remote "origin"]
  url = ../jgit-bare.git
  fetch = +refs/heads/master:refs/remotes/origin/master
  fetch = +refs/heads/stable/*:refs/remotes/origin/stable/*

示例三:设置推送到远程仓库的默认远程分支名称

添加默认推送名称:

ini 复制代码
[remote "origin"]
  url = ../jgit-bare.git
  fetch = +refs/heads/master:refs/remotes/origin/master
  fetch = +refs/heads/stable/*:refs/remotes/origin/stable/*
  push = refs/heads/develop:refs/remotes/origin/integration/master

创建本地分支并提交一个新版本:

bash 复制代码
# Create local branch 'develop', then add one commit
$ git checkout -b develop
Switched to a new branch 'develop'
$ echo "This is the developer setup, read carefully" > readme-dev.txt
$ git add readme-dev.txt
$ git commit -m "adds readme file for developers"

推送到远程分支(确认是否默认推送至 integration/master 分支):

bash 复制代码
$ git push

实测结果:

几点说明:

  1. integration/master 分支仅在本地存在,远程仓库(bare 库)不存在。

  2. refspec 的格式为:<source>:<destination>

    1. fetch 操作:远程库为 source,本地库为 destination

    2. push 操作:远程库为 destination,本地库为 source

    3. refspec 中的 + 号,是指具体的引用写法可以被修改,即便不是快进式修改(即按时间顺序进行的修改,原文为:... to indicate that the ref pattern can be updated even though it isn't a fast-forward update)

    4. refspec 不支持模糊匹配,因此不能写作:

      ini 复制代码
      fetch = +refs/heads/stable*:refs/remotes/origin/stable*

      ref 的写法可以按命名空间设置,如:

      ini 复制代码
      fetch = +refs/heads/stable/*:refs/remotes/origin/stable/*

      这也是为什么示例一开始就要重命名分支名称的根本原因;同时也从另一个角度说明,分支的命名最好按命名空间的方式进行设计。


关于上面提到的笔误,当时还联系了出版社求证,并有幸得到了作者的反馈,确实是写错了。原文如下:

Hi Anton,

Hope you are doing well.

This is what we have received from the author for the first query:

"I have walked through the section, and the missing \ in the command is correct.

Moreover, in order to archive what is described in the section, it is vital to mention that the renaming command (for br ...) must be executed in the directory jgit-bare.git. If you follow the commands in the section strictly, you will be in the directory refspec-tests.

By changing the "for br ..." command to "(cd .../jgit-bare.git && for br ...)", it will work. The parenthesis at the beginning and at the end are important."

(第二章完)

相关推荐
冷眼看人间恩怨8 分钟前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
丁总学Java2 小时前
git branch -r(--remotes )显示你本地仓库知道的所有 远程分支 的列表
git
数据的世界012 小时前
.NET开发人员学习书籍推荐
学习·.net
四口鲸鱼爱吃盐2 小时前
CVPR2024 | 通过集成渐近正态分布学习实现强可迁移对抗攻击
学习
OopspoO4 小时前
qcow2镜像大小压缩
学习·性能优化
yylの博客5 小时前
Windows通过git-bash安装zsh
windows·git·bash·zsh
A懿轩A5 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
居居飒5 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
丁总学Java5 小时前
(Z Shell)zsh: no matches found: ? 使用单引号包裹
git·zsh
kkflash35 小时前
提升专业素养的实用指南
学习·职场和发展