Git常见零碎问题汇总


这里主要记录在日常使用 Git 时,遇到的一些零碎问题。不易写成独立文章,所以统一记录于此。

Git常见零碎问题汇总


1. Git 分支已经删除

远程获取分支最新代码,提示远程分支已经不存在了

  • 问题描述:下拉代码的时候提示分支不太对。
# 获取最新代码报错git pull
Your configuration specifies to merge with the ref 'refs/heads/ipo_user'
from the remote, but no such ref was fetched.
  • 解决方法:后面发现该分支已经在远程仓库中删除了,所以需要切换到其他分支。
# 切换到dev分支git checkout dev

2. LFS 提交方式不对

LFS 获取文件的时候,获取的文件状态不太对

  • 问题描述:查看仓库状态的时候,发现有文件已经删除了,但是 checkout 的时候,提示操作不当。
# 当前仓库状态git status
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:    data/model/app1.zip
        deleted:    data/model/app2.zip

# 执行checkout命令没有效果git checkout -- data/model/app1.zip
Encountered 1 file(s) that should have been pointers, but weren't:
        data/model/app1.zip
  • 解决方法: 清除缓存并执行硬重置。
# 操作需谨慎git rm --cached -r .git reset --hard
  • 解决方法: 如果执行上述操作之后还是提示有其他文件存在上述报错问题,就需要按照如下操作在执行下就可以了(主要还是因为 lfs 导致,.gitattributes 中存在的内容没有被回滚,所以需要删除之后在回滚就可以了)。
git rm .gitattributes
➜ git reset --hard HEAD

3. LFS 撤销历史提交

修改历史提交的操作需要谨慎处理

  • 问题描述:在仓库修改 lfstrack 文件的时候,本应该会添加 "*.iso" 号结果修改成了错了 ".iso",导致 push 上去发现参数文件没有使用 lfs 文件。现在的需要,将这一次关于 lfs 的提交 rewrite 掉。
# 普通文件的处理方式
$ git reset –hard ^HEAD
$ git push origin master
  • 解决方法:lfs 工具提供了 migrate 命令来处理这个问题。
# 使用migrate命令
$ git lfs migrate import --include="data/app_mold/*" --everything

# 推送报错表示分支有保护机制,去掉之后在推送即可
$ git push --force
Locking support detected on remote "origin". Consider enabling it with:
......
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to '[email protected]:xxx/app.git'

4. LFS 需要输入密码

多为本地秘钥的缓存时间已经过去

  • 问题描述:提送 lfs 信息,提示需要输入密码。
# 提示信息如下所示
Authentication failed for 'https://______.git'
  • 解决方法:添加本地公私钥并设置缓存时间。
# [1] 使用SSH连接
$ cd ~/.ssh
$ ssh-keygen -t rsa -C "[email protected]"
$ ssh -T [email protected]

# [2] 修改缓存时间
$ git config --global credential.helper 'cache --timeout=3600'

# [3] 本地储存起来
$ git config --global credential.helper store

5. LFS 无法获取文件

使用新版本的 LFS 工具

  • 问题描述:某个环境发现如下报错,排除原因发现是对应仓库的 lfs 文件并没有从远程仓库拉下来。服务更新都是使用的 CI/CD 工具,但是其他服务器获取 lfs 文件并没有任何问题,而且登录服务器手动执行 git lfs pull 也是可以正常执行的,这就很奇怪了。排除了自动部署工具的默认参数和对应的 git 工具配置并没有发现任何有用的信息,无奈 🤷‍♀️ !
# 报错信息如下
2020-xx-xx xx:xx:xx: I tensorflow/stream_executor/platform/default/dso_loader.cc:28]
Traceback (most recent call last):
  File "/usr/lib/python3.6/runpy.py", line 113, in _run_module_as_main
    "__main__", mod_spec)
  ......
  File "/data/app_test/.../hhkc/.../network.py", line 54, in <module>
    from transformers.modeling_hhkc import (
ImportError: cannot import name 'HhkcLayerNorm'
  • 解决方法:最后,发现是因为 git-lfs 工具的版本太低导致其默认参数和新版的不一致,这才导致自动部署工具获取 lfs 文件异常。这几台出问题的服务器,当时安装 lfs 工具都是使用 apt 来安装的,所以默认的仓库对应的软件版本号比较低,所以按照官方网站的更新方式部署更新之后,一切都变得正常了。
# 老版本的lfs工具(git-lfs/2.3.4)
$ git lfs env | grep "dTransfers"
DownloadTransfers=basic
UploadTransfers=basic

# 新版本的lfs工具(git-lfs/2.12.0)
DownloadTransfers=basic,lfs-standalone-file
UploadTransfers=basic,lfs-standalone-file

# git-lfs-standalone-file
为文件URL(本地路径)提供独立传输适配器
https://github.com/git-lfs/git-lfs/blob/master/docs/man/git-lfs-standalone-file.1.ronn
# 官方提供的更新方式
$ curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
$ sudo apt-get install git-lfs
$ git lfs install

6. Git 切换分支不存在

查看 git 的 config 信息获取远程信息细节

  • 问题描述: 在一个测试仓库上面需要临时切换分支,但是切换分支的时候提示如下错误,提示没有找到匹配的分支。但是登陆远程仓库,发现对应的分支是存在的。想到有可能是因为没有更新代码导致无法获取远程仓库的分支信息,随即执行这个 git fetch 命令,但是报错依旧,且通过 git branch -a 也看不到对应的分支信息。
# 报错提示
$ git checkout bugfix_login_error
error: pathspec 'bugfix_login_error' did not match any file(s) known to git.
  • 解决方法: 后来,排查了一下 .git 目录文件夹里面的信息,随即发现了问题原因。即远程仓库的获取只是对标于 master 分支,所以我们通过执行 git fetch 命令之后也是无法获取远程仓库的分支信息的,按照如下修改即可解决。
# 发现远程仓库的获取只是对标于master分支
$ cat .git/config
[remote "origin"]
    url = [email protected]/EscapeLife/app-demo.git
    fetch = +refs/heads/master:refs/remotes/origin/master
[branch "master"]
    remote = origin
    merge = refs/heads/master

# 应该为带 * 的匹配方式
[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
  • 问题原因: 我们正常克隆仓库的时候,对应的 config 配置就是带 * 的样式,但是为什么这个环境的配置会修改了呢?后来发现是因为这个环境是通过 CI 进行自动更新的,而 CI 配置了只获取指定分支的代码,即拉去代码的时候就指定了,这也就导致配置文件也就跟着 变更 了。
# 让Git每次只拉取远程的master分支,而不是远程的所有分支
$ git fetch origin master:refs/remotes/origin/master

7. Git 显示中文乱码

Git 命令显示中文和解决中文乱码

  • 问题描述:使用 git status 命令查看文档或者目录改动时,显示不出中文文件名和中文文件名称,非常不方便。
# 显示中文乱码git status
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    deleted:    234\123\234\654\234/954\236\952/.vscode/settings.json
  • 解决方法:在默认设置下,中文文件名在工作区状态输出,中文名不能正确显示,而是显示为八进制的字符编码。将 git 配置文件 core.quotepath(引用路径) 项设置为 false,即可显示中文。要注意的是,这样设置后,你的 git bash 终端也要设置成中文和 utf-8 编码,才能正确显示中文。
# [修改方式一] 临时修改git config core.quotepath false

# [修改方式二] 全局配置git config --global core.quotepath false

# [修改方式三] 编辑/etc/gitconfig文件
➜ vim /etc/gitconfig
[core]
quotepath = false        # 引用路径不再是八进制

8. Git 恢复丢失数据

使用 Git 工具管理仓库的时候,意外删除文档,重置仓库,如何快速恢复丢失的数据呢?

  • 问题描述:重置数据,一般都是使用了 reset 命令导致的,因为其命令用于改变当前的仓库状态。下面是常见的 Git 重置操作,一旦执行之后,我们又后悔了,那该怎么办呢?
# 暂存区 <- 本地仓库
$ git reset HEAD <file>   # 本地仓库文件内容覆盖暂存区文件内容

# 工作区 <- 本地仓库
$ git reset [commit]         # 本地仓库覆盖到工作区(保存回退文件内容修改);默认就是--mixed参数
$ git reset [commit]         # 重置当前分支的指针为指定commit;同时重置暂存区但工作区不变
$ git reset --soft [commit]  # 本地仓库覆盖到工作区(保留修改并加到暂存区)
$ git reset --soft [commit]  # 回退为指定版本(不删除回退文件的修改)
$ git reset --hard [commit]  # 本地仓库覆盖到工作区(不保留修改直接删除掉)
$ git reset --hard [commit]  # 重置当前分支的HEAD为指定commit;同时重置暂存区和工作区;谨慎使用

# 工作区 <- 本地仓库
$ git reset --keep [commit]   # 重置当前HEAD为指定commit,但保持暂存区和工作区不变
$ git reset --mixed [commit]  # 本地仓库覆盖到工作区(保存回退文件内容修改)
  • 解决方法:当我们操作进行了版本回退,现在又需要回退之前的文件信息,此时分为三种情况:
    • [情况一] -> 之前的修改进行了 commit 提交,即执行了 git commit
    • [情况二] -> 之前的修改未进行 commit 提交,即执行了 git add
    • [情况三] -> 之前的修改未进行 commit 提交,即也没有执行 git add
# 针对第一种情况
$ git reflog               # 获取hash值
$ git reset --hard [hash]  # 回退到之前修改的状态

# 针对第二种情况可以执行如下恢复步骤
# 因为会重置暂存区和工作区且没有提交记录,所以不好恢复
# 可以利用fsck命令查找到之前丢失文件(在.git/lost-found目录)
# other  -> .git/lost-found/other  -> 添加信息
# commit -> .git/lost-found/commit -> 提交信息
$ git fsck --lost-found

# 针对第三种情况可以执行如下恢复步骤
因为根本就没有被Git接管,所以恢复就无从谈起了!
但是如果你使用的是JB(jetbrains)家的IDE工具,可以通过自带的文件历史功能成功恢复!=> 右键菜单本地历史功能
想了想,JB(jetbrains)家的东西真香呀!

9. Git 忽略冗余文件

使用过苹果电脑的话,肯定只有默认会给目录生成的 .DS_Store 文件。

  • 问题描述:macOS 系统上面,我们会看到每个目录都会存在一个名为 .DS_Store 的隐藏文件。其作用就是以告诉 Finder 应该如何显示它,但是 99% 的时间我们都不关心它,尤其是在代码库中,我们更不愿意或者关注它。虽然,可以在代码库里面使用 .gitignore 文件进行忽略,但是每个项目都要来一遍,也挺麻烦的。
ls -lh
-rw-r--r--@   1 escape  staff    22K Jan 16 15:39 .DS_Store
drwx------   48 escape  staff   1.5K Jan 16 16:05 .Trash
  • 解决方法: 如果做到一次配置,全局忽略 .DS_Store 呢,就是我们继续要解决的问题。Git 中可以通过设置 core.exclusudesfile 变量来指定全局的 gignore 文件。
# 忽略你需要忽略的文件

# Logs
*.log

# OS generated files
.DS_Store
$ cat .gitignore_global
.DS_Store
.Spotlight-V100
.Trashes
Thumbs.db
# 创建全局配置文件 => gitignore
$ ln -s /Users/escape/fuckcode/dotfiles/.gitignore_global /Users/escape/.gitignore

# 设置Git配置对应文件
$ git config --global core.excludesfile ~/.gitignore

# 或者在配置文件里面添加对应内容
$ cat .gitconfig
excludesfile = ~/.gitignore

10. Git 分支切换异常

使用 clean 命令的时候需要谨慎,不然容易丢失数据!

  • 问题描述: 在代码仓库中切换分支,提示如下错误,导致无法正常切换。
git checkout stable
error: The following untracked working tree files would be overwritten by checkout:
  • 解决方法: 通过错误提示可知,是由于一些 untracked working tree files 引起的问题,只要解决了这些 untracked 的文件就能解决这个问题。
# 清理所有没有报错的文件和目录
# -n 显示将要删除的文件和目录
# -d 删除未被添加到git的路径中的文件(需谨慎使用)
# -f 强制运行
# -x 删除忽略文件已经对git来说不识别的文件git clean -n
➜ git clean -df
➜ git clean -d -fx

11. Git 无法拉取代码

使用 clean 命令的时候需要谨慎,不然容易丢失数据!

  • 问题描述:Windows 上使用 git clone 代码的时候抛出了异常,提示如下错误。源代码是在 MacOS 上编写的,但是在 Windows 上拉取代码却出现了问题。
git clone [email protected]:app/xxx.git
Cloning into 'xxx'...
Resolving deltas: 100% (7376/7376), done.
error: invalid path 'abc.js '
  • 解决方法: 根据提示可以看出代码 clone 是成功的,但是 checkout 的时候出现了错误,搜索了下发现是因为 NTFS 保护机制配置导致的。Windows 系统下默认值是 true,也就是说不符合 NTFS 策略的文件不会被签出,设置为 false 后可以关闭保护机制。
# 临时设置git config core.protectNTFS false

# 永久设置git config --global core.protectNTFS false

12. Git 无法推送代码

使用 clean 命令的时候需要谨慎,不然容易丢失数据!

  • 问题一: 如果出现这样的问题,可以发现根据提示是,本地存储库本地就有问题(损坏),可以重拉一遍或者执行。可以执行 git repack 看看。
error: remote unpack failed: unpack-objects abnormal exit
To http://example.com;
! [remote rejected] HEAD -> master (n/a (unpacker error))
error: failed to push some refs to 'http://example.com'
  • 问题二: 原因是由于单个文件过大,导致推送失败,把大文件使用 git-lfs 管理就可以了。
remote: fatal: pack exceeds maximum allowed size

13. Git 分支保护提交

在分支保护的情况,如何合理合法的提交和合并代码!

  • 问题描述: 今天推送本地分支代码到 GitLab 远程 stable 分支上,报错了,报错信息如下所示:
# 普通文件的处理方式
$ git cherry-pick -x 123456
To git.xxx.com:repo/app.git
 ! [remote rejected] stable -> stable (pre-receive hook declined)
error: failed to push some refs to 'git.xxx.com:repo/app.git'
  • 解决方法: 原因为 stable 为受保护分支,无法强推代码到 stable 分支上,排除了发现是因为没有权限导致,加了就正常可以使用了。当然,可以将分支保护去掉,但是并不推荐这种处理方式,有很大安全隐患。
    • 添加可用分组权限给该用户即可
    • 除去分支保护:Settings -> Repository -> Protected Branches -> Unprotect

Git常见零碎问题汇总 - 分支保护提交

Git常见零碎问题汇总 - 分支保护提交


文章作者: Escape
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Escape !
  目录