git 常见问题整理

2019-04-01 develop git

整理下常见的 git 问题。

refusing to merge

完整报错为 refusing to merge unrelated histories 信息,通过 pull 时会报上面的错误,可能性比较大的是远端仓库的历史被修改了,例如通过 --amend 重新提交。此时可以通过 --allow-unrelated-history 选项尝试解决,如果仍然报错 Not possible to fast-forward, aborting. 可以尝试如下方案。

----- 获取远端提交
$ git fetch --all

----- 强制覆盖本地分支,最后的参数为要拉取的远端分支名
$ git reset --hard origin/master

实际上 pull 命令是 fetchmerge 命令的组合,也就是先从远端仓库抓取内容,然后立即尝试将其合并进当前所在分支。

合并策略

这是一个在 Git 2.27 添加的 hint 提示,详细内容如下:

hint: Pulling without specifying how to reconcile divergent branches is
hint: discouraged. You can squelch this message by running one of the following
hint: commands sometime before your next pull:
hint:
hint:   git config pull.rebase false  # merge (the default strategy)
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.

使用 git pull 命令默认等价于 git fetch 以及 git merge FETCH_HEAD 命令,因为执行了合并动作,通常就需要创建一个 commit 请求,可以通过 git pull --ff-only 或者 git config --global pull.ff only 只执行 fast-forwarded 合并,这种模式不会创建新的提交。

Certificate Issuer

完整的报错是 Peer's Certificate issuer is not recognized. ,主要是由于 HTTPS 的证书无法识别导致,可以将无法识别的证书添加到根证书,或者直接忽略。

这里简单使用后者。

----- 可以通过环境变量设置忽略SSL校验
$ echo 'export GIT_SSL_NO_VERIFY=true' >> ~/.bashrc
$ source ~/.bashrc

----- 也可以在git中进行配置
$ git config http.sslVerify "false"
$ git config --global http.sslVerify false
$ git config http.sslCAinfo /your/path/to/cacert-client.pem

Push.default

对于 2.0 以后的版本,默认安装之后会有如下的警告信息。

warning: push.default is unset; its implicit value is changing in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the current behavior after the default changes, use:

  git config --global push.default matching

To squelch this message and adopt the new behavior now, use:

  git config --global push.default simple

See 'git help config' and search for 'push.default' for further information.
(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode
'current' instead of 'simple' if you sometimes use older versions of Git)

在 git 中 push 代码时,会有些固定的策略:

  • nothing 什么都不干 (要它干嘛! 测试用的?)。
  • matching 本地所有的分支都push上去。
  • upstream 当本地分支有upstream (也就是有对应的远程分支) 时 Push 到对应的远程分支。
  • simple 和 upstream 一样,但不允许将本地分支提交到远程不一样名字的分支。
  • current 把当前的分支 push 到远程的同名分支.

git 1.x 的默认策略是 matching,在 git 2.0 之后 simple 会成为新的默认策略。

matching 不友好之处在于,我们大部分情况都是同步本地的当前分支到远程,如果本地有二三十个分支,那么就会看到大量的刷屏,而且如果其它分支也有更新的话就可能会出现大量的 push fail 信息。

相比来说,simple 这个选项是非常安全的选项,至少能阻止新手误操作覆盖远程分支,所以 git 会在 2.0 时将其作为默认策略。但是需要保证远程与本地的分支名称相同。

大部分情况想要做的只是 push 当前的分支,那么最适合的就是 upstream 。

可以通过如下方式查看、修改全局的配置,相关的配置文件保存在 ~/.gitconfig 中。

$ git config --global --list
$ git config --global push.default upstream

agent refused operation

完整的报错如下。

sign_and_send_pubkey: signing failed: agent refused operation

一般是在服务器添加完公钥后报错,可以通过执行如下命令方式解决。

$ eval "$(ssh-agent -s)"
$ ssh-add

HEAD detached at

git 中的 HEAD 可以理解为一个指针,保存在 .git/HEAD 文件中,如果 git checkout <BranchName> 那么就指向该分支的最新一次本地提交,那么 HEAD 文件的内容会是 ref: ref/heads/develop;当通过 git checkout <CommitID> 指定某个提交时,就会处于 Detach 状态,文件的内容就成了对应的 CommitID

其它

快速复制

当提交仓库过大时,可以在 clone 时通过 --depth=1 指定拉取最新提交,如果后续要获取全部提交,那么可以通过 git fetch --unshallow 即可。

PreCommit

在提交之前可以执行一些操作检查,比如代码打包、代码检测,称之为钩子;如果执行成功继续提交,否则失败就阻止提交。

----- 直接复制示例代码
$ cp .git/hooks/pre-commit.sample .git/hooks/pre-commit