git相关

在客户环境里用git时遇到一个很讨厌的事情。既之前设置的git账号的密码变了,当然这个改变是因为客户IT每隔一段时间就会修改密码。

事情原尾是这样的:
我们用uipath开发RPA流程,在客户虚拟机上运行。 UiPath自带版本管理工具,支持git和TFS等。 我们为了方便集中管理多个流程,就让用户建了一个仓库,把所有流程都放在这个仓库里,以不同的文件夹区分开。
后期我们使用时经常遇到各种问题(在uipath界面中操作):

  1. 明明只想提交对一个流程的修改,但其他流程跟着一块提交了。
  2. 本想undo一个流程,但总是undo不干净,点击undo之后总是还会提示期望undo的文件没有被undo。

一时想不全,感觉就是问题一大堆。 于是打算用git命令行自己来控制文件的提交。 但命令行直接git pull,提示authentication failed。 明明uipath界面里的账号和密码是对的,但是命令行里不知道保存的何时的密码,也不知道保存在了哪里。
对着chatGPT一通问,中间不知反复尝试了多少种命令。 总之,就是手工把凭据管理器里的凭据删掉了。 希望在命令行里使用git pull命令时会弹出输入账号密码的弹窗,但就是不弹,只提示authentication failed。
最后有效的解决步骤如下:
依次执行了下述命令
git config --system --unset credential.helper
git config --global --unset credential.helper
git config --local --unset credential.helper
git config --global credential.interactive always
git pull
在命令行里提示输入用户名和密码。
输入后,命令执行成功。 但是因为目前设置的是每次git pull或git push这种命令都需要输入用户名和密码,于是再执行下面命令
git config --global credential.helper store (注意,这种方法存储用户名密码是以明文存储,不借助windows凭据管理器,但简单有效。)
git config --global --unset credential.interactive

中间还记着用过git credential fill | approve | rejct等命令,不知道干啥用,也不知道起没起作用。
总之,git 在windows上总是感觉有莫名奇妙的问题,很恶心。
客户环境更恶心,首先没有管理员权限,有些东西设置不了,也不能安装东西。 其次,不能访问外网,查个百度都不能。 最后,东西进不去出不来,完全与世隔绝。 最最重点的是,机器慢的要死,卡的要死。 vpn连他们环境还总掉线,垃圾的一批。

查看本地仓库关联的无端库信息:
git remote -v

查看所有本地及远端分支:
git branch -a

当我做了些修改,但我想还原这些操作
git restore .

但是当我添加了一些文件,并且这些文件没有使用git add . 命令添加到暂存区,同时这些文件也从未被跟踪过,我想移除这些文件
git clean -f

但是如果同时也想删除未被跟踪的目录则要用下面的命令
git clean -fd

如果我想还原的文件已经被我添加到了暂存区,即git add .命令添加的。那么我要执行下面两个命令才能还原。
git reset 将暂存区的内容移除
git restore . 将未被添加到暂存区的改动进行还原。

当我有已跟踪的文件发生了改变,我想直接提交,可以这样
git commit -a -m "messge"
它相当于执行了 git add . 加上 git commit -m "message" 这两条命令。

但是如果我有新增的文件(从未被跟踪过),并且其没有添加到暂存区, 这时使用**git commit -a -m "message" **命令并不能将其提交到仓库,而是得顺序执行下面两条命令
git add .
git commit -m "message"

当我想查看都哪些文件被跟踪了,其实就是当前仓库里已经提交过的文件
git ls-files

当想将本地仓库关联到远端仓库里
git remote add origin https://gitee.com/xxxxx.git
git push -u origin "master" 在推送的同时绑定远端库的分支。 使用一次 -u,就代表永久绑定,后续就可以直接使用git push了

如果在公司电脑上遇到如下问题时:
fatal: unable to access 'https://gitee.com/xxxxx.git/': SSL certificate problem: unable to get local issuer certificate

切换成ssh的方式:
git remote set-url origin git@gitee.com:xxxxx.git
再重新push就可以了。 但前提是先在公司电脑上生成ssh key并配置到git远端仓库服务器里。

在git命令行里,显示的文件名里的中文是unicode转义字符,如何显示成中文。
以在windows系统中使用windows terminal,并且标签显示Windows Powershell。使用如下命令:

# 1. 确保 Git 不转义路径
**git config --global core.quotepath false**

# 2. 在 PowerShell 配置文件中添加(永久生效)
**[Console]::OutputEncoding = [System.Text.Encoding]::UTF8**

gitignore文件介绍
总结:
git仓库里可以在不同层级目录里存在.gitignore文件。仓库中的文件同时受不同层级的.gitignore文件的影响,但离文件越近的.gitignore文件的优先级越高。
.gitignore 文件只对未跟踪的文件生效。如果文件已经被 Git 跟踪,需要先用 git rm --cached 停止跟踪。

模式前面不加"/"的,代表匹配所有层级目录,加"/"的,表示从根目录还始匹配。(注意,这里的根目录指的是.gitignore文件所在的目录)。简写的路径模式可以省略前面的"/"。例如foo/bar等价于/foo/bar
模式后面加"/"的,只匹配目录,不匹配文件。 模式后面不加"/"的,可以同时匹配文件和目录。
"*"为通配符。foo不能匹配foo.txt,可以通过foo.*来匹配所有文件名为foo,不考虑扩展名的文件。
"**"为多层级匹配符。 **/foo 等价于 foo, 因为git对单层模式默认递归匹配。 **/foo/bar 不等价于 foo/bar。 对于路径模式默认不做递归匹配,因此foo/bar只能匹配根目录下的foo文件夹里的bar。 
 以"/**"结尾时,代表匹配目录下的所有内容。比如 foo/**,代表匹配foo目录里所有内容,其实等价于 foo/
**注意**: foo/ 是单层模式,代表foo文件夹。(不是带/就是路径模式) 。而foo/bar则是路径模式,匹配根目录下的bar

foo :可以匹配foo文件名,foo文件夹,但不能匹配foo.txt, foo.log等。
foo.* :可以匹配foo.txt, foo.log等,但不能匹配foo文件名,foo文件夹
foo* : 可以匹配foo.txt, foo.log等,同时也能匹配foo文件名,foo文件夹名, 还能匹配footest文件名或文件夹,footest.txt, footest.log等文件名
foo/ :可以匹配foo文件夹,但不能匹配foo文件名
foo*/ : 可以匹配foo文件夹,但不能匹配foo文件名。 可以匹配footest文件夹,但不能匹配footest文件名,以及footest.txt, footest.log等文件名
*foo : 可以匹配abcfoo文件夹或文件名,foo文件夹或文件名, 但不能匹配abcfoo.txt, abcfoo.log等文件名
!testfoo : 否定规则。 不匹配testfoo。

git默认主分支
git社区从2020年开始就将主分支由原先的master改为main了,但windows安装的git默认还沿用master这个旧的名称。
可以使用下面命令配置全局设置,下次在使用git创建仓库时主分支就是main了。

# 立即执行,让您的 Git 跟上时代
git config --global init.defaultBranch main
# 可以将本地分支改名字 git branch -m <原分支名> <新分支名>
git branch -m master main
# 当我们无意间把本地master分支推送到远端,并在远端创建了同名的master分支后,我们最好将远端的master分支删掉。
git push origin-gitlab --delete mastet
# 上面可以删除远端分支的前提是 要删除的分支不能是远端库的默认分支。
git remote show origin  # 这个命令可以用于查看远端库的默认分支
# 如果远端库的默认分支就是master,则不能删除它。这个时候需要登录远端仓库,手工更改默认分支为main,然后再删除。

将本地分支与上游(远端仓库)分支绑定

# 完整的分支绑定或者说追踪语法
git branch --set-upstream-to=<remote>/<remote-branch> <local-branch>
# 举例:把本地master分支的上游设置为远端的main分支
git branch --set-upstream-to=origin-lab/main master

# 如果不指定本地分支名,则默认将本地的当前分支绑定到上游分支
# 举例,假设本地当前分支是master,下面命令将把master分支绑定到远端库main分支。
git branch --set-upstream-to=origin-lab/main
# 下面这种方式可以在推送的同时设置上游分支
git push -u origin master:main

git push的完整语法

git push <remote> <当前分支>:<上游分支>
# 举例:将本地master分支推送到远端main分支
git push origin master:main
# 用HEAD来代表本地当前发支
git push origin HEAD:main
# 当要推送的本地分支和远端分支同名时,可以简写
git push origin master  # 本地的master分支推送到远端master分支
# 当本地当前分支与远端分支已经绑定,但本地仓库添加了多个远端库时,需要指定远端库名
git push origin-gitlab  # 假设远端库叫origin-gitlab
# 当本地当前分支与远端分支已经绑定,并推送本地当前分支,可以简写。但前提条件是,本地分支绑定的远端分支必须同名,这个条件是git config里的默认配置push.default=simple
git push  # 这种也是我们一般情况下使用的方式

git pull的完整语法

git pull <远程名> <分支名>
# 举例: 将远端库origin的main分支合并到本地仓库的当前分支。注意,这个命令不能指定本地分支,而只是本地当前分支。这种情况下,本地分支和上游分支可以不同名,并且本地当前分支可以是未绑定到远端分支的状态。
git pull origin main 

git pull <远程名>
# 举例: 将与本地当前分支同名的远端分支合并到本地当前分支,前提是本地当前分支已经绑定到了远端同名分支。
git pull origin

git pull
# 举例: 若本地仓库只添加了一个远端库,并且本地当前分支已经绑定到了远端同名的上游分支,则可以简写成 git pull。 这其实也是最常用的场景。

git配置文件的三层分级结构
Git 的配置系统采用三层分级结构,每一层对应不同的作用范围和优先级。这种设计使得 Git 既灵活又安全,既能满足全局默认设置,又能为单个项目定制特殊行为。

## 📁 第一层:本地层(Local)——`.git/config`

### 📍 路径:
```bash
<你的项目目录>/.git/config

🎯 作用范围:

  • 仅对当前 Git 仓库生效
  • 每个仓库都有自己的 .git/config

✅ 常见配置项:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
[remote "origin"]
    url = https://gitee.com/user/repo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
    remote = origin
    merge = refs/heads/main

🔧 如何设置?

git config branch.main.remote origin

默认操作的就是本地层(不加 --local 也默认为此层)

🚫 注意:

  • 该文件不会被提交到远程仓库
  • 换一台机器 git clone 后,此配置不会自动继承

🌍 第二层:全局层(Global)——~/.gitconfig

📍 路径:

  • Linux/macOS: ~/.gitconfig~/.config/git/config
  • Windows: C:\Users\<用户名>\.gitconfig

⚠️ ~ 表示用户主目录

🎯 作用范围:

  • 当前用户的所有 Git 仓库生效

✅ 常见配置项:

[user]
    name = Your Name
    email = your.email@example.com
[core]
    editor = vim
    autocrlf = input
[color]
    ui = auto
[alias]
    co = checkout
    br = branch
    st = status
    last = log -1 HEAD

🔧 如何设置?

git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
git config --global core.editor "code --wait"

✅ 推荐设置:

  • user.nameuser.email:每次提交都会记录
  • alias:自定义快捷命令
  • pull.rebase:设置 git pull 使用 rebase 而非 merge

🖥️ 第三层:系统层(System)——/etc/gitconfig

📍 路径:

  • Linux: /etc/gitconfig
  • macOS: /usr/local/etc/gitconfig/etc/gitconfig
  • Windows: 通常在 Git 安装目录,如 C:\Program Files\Git\etc\gitconfig

🎯 作用范围:

  • 系统上所有用户、所有仓库生效

✅ 常见用途:

  • 企业或组织统一设置默认编辑器、换行符处理等
  • 设置代理、安全策略等

🔧 如何设置?

# 需要管理员权限
sudo git config --system core.editor "vim"
sudo git config --system init.defaultBranch main

⚠️ 注意:

  • 普通用户通常没有权限修改此文件
  • 修改会影响所有用户,需谨慎

🔍 如何查看各层配置?

1. 查看所有生效配置(合并后)

git config --list

2. 查看某一配置的最终值

git config user.name

3. 查看某一层的配置

命令 说明
git config --local --list 查看本地层
git config --global --list 查看全局层
git config --system --list 查看系统层
git config --show-origin --list 显示配置值及其来源文件

✅ 推荐使用最后一个命令,它能清晰告诉你每个配置来自哪个文件:

git config --show-origin --list

输出示例:

file:/home/user/.gitconfig      user.name=Your Name
file:/home/user/.gitconfig      user.email=you@example.com
file:.git/config                branch.main.remote=origin
file:/etc/gitconfig             init.defaultBranch=main

🎯 各层配置的典型使用场景

配置项 建议设置层级 说明
user.name / user.email --global 个人身份信息
core.editor --global 个人偏好
alias.* --global 个人快捷命令
pull.rebase --global 统一合并策略
branch.<name>.remote --local 项目特定的远程绑定
remote.pushdefault --global--local 根据场景选择
init.defaultBranch --system--global 组织规范

✅ 实际案例:从 mastermain 的迁移

# 系统层(管理员设置组织规范)
git config --system init.defaultBranch main

# 全局层(您个人设置)
git config --global init.defaultBranch main

# 本地层(某个项目特殊需求,比如必须用 master)
cd old-project
git config init.defaultBranch master

此时:

  • 新项目默认创建 main 分支
  • old-project 仍使用 master

✅ 总结

层级 文件 作用范围 优先级 推荐用途
本地(Local) .git/config 当前仓库 ⭐⭐⭐ 高 项目特定配置
全局(Global) ~/.gitconfig 当前用户所有仓库 ⭐⭐ 中 个人偏好、身份信息
系统(System) /etc/gitconfig 所有用户所有仓库 ⭐ 低 组织统一策略

💡 口诀

  • 个人设置用 --global
  • 项目特殊用 --local(默认)
  • 统一规范用 --system

即:如果同一配置在多层中出现,优先使用优先级高的层的值。

git的三区思想

Git 实际上维护三个主要状态(常被称为“三棵树”):

名称 说明
1. HEAD 上一次提交的快照(即当前分支的最新 commit)
2. Index / Staging Area(暂存区) 下一次 commit 将要包含的内容(是 HEAD 的“修改版”)
3. Working Directory(工作区) 你磁盘上实际看到的文件

Index 到底存了什么?
Index(.git/index)是一个二进制文件,它保存的是:

  • 一组文件路径
  • 每个文件对应的 blob 对象 ID(即内容的 SHA-1 哈希)
  • 文件元数据(如权限)
    ✅ 所以 Index 本质上是一个 “文件名 → 内容快照” 的映射表。

当你执行以下命令时,手动或半自动地更新了 Index:
git add → 把工作区文件加入 Index(新增或修改)
git rm → 从 Index 和工作区都删除(删除)
git rm --cached → 只从 Index 删除(停止跟踪)
git add -u → 自动 add 所有已跟踪文件的修改和删除
git add . → add 所有新文件 + 修改(但不包括删除)

你完全可以做到在工作区中(你能看得到的文件)修改任何文件,并且不把它add到暂存区(Index/Staging Area), 这样你对这个文件的更改(包括新增文件)就不会被提交。

💡 git status 的作用就是对比三者:

工作区 vs Index → 显示“未暂存的更改”
Index vs HEAD → 显示“已暂存的更改”

在英文表述里,工作区中的文件发生了更改,或新增,或者从已提交的文件列表中删除,等等这些情况,在没有被添加到暂存区时,就称为unstaged状态,如果已被添加到暂存区,则被称为staged状态。staged状态的内容就是提交时会更新到仓库中的内容。

posted @ 2025-03-17 22:31  RolandHe  阅读(128)  评论(0)    收藏  举报