Skip to content

git常见问题及解决

yulilong edited this page Jan 22, 2019 · 19 revisions

目录

[TOC]


1. 不同操作系统使用git时,CRLF的处理换行问题

WX20170524-183615.png

错误信息类似于:

# https://git-scm.com/book/zh/v2/自定义-Git-配置-Git
~ git diff > tmp.patch
warning: LF will be replaced by CRLF in src/app/theme/components/menuItem/menuItem.component.css.
The file will have its original line endings in your working directory.
warning: LF will be replaced by CRLF in config/webpack.dev.js.

1.1 什么是CRLF和LF

CRLF 是 carriage return line feed的缩写。中文意思是回车换行。
LF是line feed的缩写,中文意思是换行。
CRLF->Windows-style
LF->Unix Style
CR->Mac Style
CRLF表示句尾使用回车换行两个字符(即我们常在Windows编程时使用"\r\n"换行)
LF表示表示句尾,只使用换行.
CR表示只使用回车.

1.2 在Git中设置自动转换

在Git通过下面的命令配置:

$git config --global core.autocrlf true
# Configure Git on Windows to properly handle line endings

设置为true,添加文件到git仓库时,git将其视为文本文件。他将把crlf变成lf。
设置为false时,line-endings将不做转换操作。文本文件保持原来的样子。
设置为input时,添加文件git仓库石,git把crlf编程lf。当有人Check代码时还是lf方式。因此在window操作系统下,不要使用这个设置。

  1. true: x -> LF -> CRLF
  2. input: x -> LF -> LF
  3. false: x -> x -> x
  • 其他的命令
# AutoCRLF
#提交时转换为LF,检出时转换为CRLF
git config --global core.autocrlf true   
#提交时转换为LF,检出时不转换
git config --global core.autocrlf input   
#提交检出均不转换
git config --global core.autocrlf false

# SafeCRLF
#拒绝提交包含混合换行符的文件
git config --global core.safecrlf true   
#允许提交包含混合换行符的文件
git config --global core.safecrlf false    # 设置这个命令会把警告取消
#提交包含混合换行符的文件时给出警告
git config --global core.safecrlf warn


2. 多个仓库相同代码推送被拒绝

当添加一个仓库后,推送文件上去不允许,错误信息类似于:

git push github master 
To https://github.com/user/my_wiki.wiki.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'https://github.com/user/my_wiki.wiki.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

如果远程仓库的代码没用了,不要了,则可以选择强推代码解决问题:

~ git push -u github master -f

3. 由于Mac电脑升级导致 git不能用

使用git的时候出现类似下面的信息:

xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

解决方法,终端下输入下面命令:

xcode-select --install

需要安装一会就可以了。

4. git使用vi编辑器时候报错:Swap file "./.git/.COMMIT_EDITMSG.swp" already exists!

非正常关闭vi编辑器时会生成一个.swp文件。
使用vi,经常可以看到swp这个文件,那这个文件是怎么产生的呢,当你打开一个文件,
vi就会生成这么一个.(filename)swp文件 以备不测(不测下面讨论),如果你正常退出,那么这个这个swp文件将会自动删除 。
swp文件的来历,当你强行关闭vi时,比如电源突然断掉或者你使用了Ctrl+ZZ,vi自动生成一个.swp文件,
下次你再编辑时,就会出现一些提示。

比如你正在使用vi编辑file.txt文件,然后强制关闭终端,这个时候就会产生.file.txt.swp文件。
当再次使用vi打开file.txt文件就会出现提示, 这个时候可使用下面的命令来恢复未保存的操作:

vi -r file.txt 

这个时候保存中断之前的操作后,.swp文件不会自动删除,需要自己手动删除:

rm .file.txt.swp

5. Git中文乱码的问题

在使用git命令的时候,如果文件名是中文的,就会出现如\200\273\347\273\223.png的乱码。 解决方法,在终端中输入如下命令:

git config --global core.quotepath false

core.quotepath设为false的话,就不会对0x80以上的字符进行quote。中文显示正常。

参考链接: http://blog.csdn.net/tyro_java/article/details/53439537

6. GIT不识别大小写文件夹解决

在mac电脑下,git仓库中有文件夹首字母大写,修改成首字母小写后,git没有识别出文件夹的修改, 可使用如下命令设置为大小写敏感:

git config core.ignorecase false

7. 同一个文件跟踪两次

由于修改了文件名,仅仅是文件名首字母大小写修改了,然后就导致git同时把这一个文件跟踪了两次,比如我修改了文件夹名字,由Settings 改成 settings,导致文件夹下的文件重复出现:

modified:   src/views/Settings/TagSet/TagDialog.jsx
modified:   src/views/settings/TagSet/TagDialog.jsx

此时可使用git rm --cached来取消对重命名之前的文件跟踪

git rm --cached src/views/Settings/TagSet/TagDialog.jsx
rm 'src/views/Settings/TagSet/TagDialog.jsx'

取消跟踪后,使用git status查看,就会发现这个文件自动添加到删除中了:

~ git rm --cached src/views/Settings/TagSet/TaDialog.jsx
rm 'src/views/Settings/TagSet/TagDialog.jsx'

~ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	deleted:    src/views/Settings/RuleSet/RuleDialog.jsx
	deleted:    src/views/Settings/TagSet/TagDialog.jsx
	modified:   src/views/settings/RuleSet/RuleDialog.jsx
	modified:   src/views/settings/TagSet/TagDialog.jsx

8. gitlab保护分支,导致本地git push -f报错

产生原因:服务器提交了错误或者无用的代码,本地回滚代码,然后把代码强推到服务器上,由于gitlab上有分支保护导致代码推送失败:

git push origin master -f
Total 0 (delta 0), reused 0 (delta 0)
remote: GitLab: You are not allowed to force push code to a protected branch on this project.
To http://git.baijiahulian.com/yunying/bi-fe.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'http://git.baijiahulian.com/yunying/bi-fe.git'
  • 在gitlab上查看保护的分支

    在gitlab上打开项目,点击Repository, 然后点击Branches,就能看见所有分支,在分支名字后面有个绿色的protected就是保护分支。

  • 关闭gitlab上的保护分支(需要项目的master或者Owner)

    点击项目右上角(用户logo下面)的小齿轮,选择Protected Branches,在打开的页面里面就能看见保护的分支了,然后点击保护分支右边的Unprotect,就能删除对这个分支的保护了。

  • 开启gitlab上的保护分支(需要项目的master或者Owner)

    点击项目右上角(用户logo下面)的小齿轮,选择Protected Branches, 在Protect a branch中输入分支名字,选择对应权限,然后点击Protect,就会立刻添加一个保护分支了。

9. 代码回滚到以前的版本

改完代码匆忙提交,上线发现有问题,怎么办? 赶紧回滚.

改完代码测试也没有问题,但是上线发现你的修改影响了之前运行正常的代码报错,必须回滚.

回滚分两种情况

9.1 代码还没有push到远程仓库,回滚使用git reset

当代码还在本地仓库,在add、commit后发现代码有问题,想回退到以前的提交点,此时可用reset命令:

git reset option 历史提交点
  • option:reset的操作选项可用命令有:

    --hard: 移动HEAD,更新index,更新工作目录(working Directory)

    --mixed: 移动HEAD,更新index, 此选项是reset的默认选项,也就是不写option默认就是此操作。

    --soft: 只移动HEAD,

  • 历史提交点: commit标识代码, 也就是git log命令中的一串字符串,如:d42a68c81, 通常前8位以上就可以

reset命令会以特定的顺序重写这三棵树,在你指定以下选项时停止:

  1. 移动 HEAD 分支的指向 (若指定了 --soft,则到此停止)
  2. 使索引看起来像 HEAD (若未指定 --hard,则到此停止)
  3. 使工作目录看起来像索引

使用例子:

git reset --hard 9e53f30b7ab56e

HEAD is now at 9e53f30 开始页面:添加提交按钮。

此时所有历史commit记录可使用git reflog来查找:

git reflog

26c5d5a (HEAD -> test, origin/test) HEAD@{0}: reset: moving to 26c5d5a
9e53f30 HEAD@{1}: reset: moving to 9e53f30b7ab56e
26c5d5a (HEAD -> test, origin/test) HEAD@{2}: commit: 添加测试包
9e53f30 HEAD@{3}: commit: 提交信息

如果回退错了,可使用上面命令把最早的提交在回退回来。

9.2 代码已经push到远程仓库

9.2.1 代码刚push,还没有扩散

代码刚push,还没有被其他开发人员拉取,或者还没有用于自动部署工具拉取(如Jenkins)。

此时使用git reset 回退后,然后使用git push -f 来强推代码到仓库即可:

git reset --hard 9e53f30b7
HEAD is now at 9e53f30 开始页面:添加提交按钮。
git push -f

Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: Create merge request for tt:
remote:   http://git.github.com/finance-system/zi-fe/merge_requests/new?merge_request%5Bsource_branch%5D=tt
remote:
To http://git.github.com/finance-system/zi-fe.git
 + 26c5d5a...54ebaf8 tt -> tt (forced update)

注意,如果推送的分支是保护分支(gitlab仓库有保护分支设置),那么只能是master权限才能强推代码,或暂时把保护分支关闭才能正确推送代码。

9.2.2 代码已经被其他开发拉取或已经被自动部署工具拉取了

由于此时代码已扩散了,如果在使用reset回退然后强推则会导致被人在拉取你代码的时候导致冲突,拉取失败。

此时可使用git revert来回退了:

git revert用于反转提交,执行evert命令时要求工作树必须是干净的.

git revert用一个新提交来消除一个历史提交所做的任何修改.

revert 之后你的本地代码会回滚到指定的历史版本,这时你再 git push 既可以把线上的代码更新.(这里不会像reset造成冲突的问题)

revert 使用,需要先找到你想回滚版本唯一的commit标识代码:

git revert 26c5d5a7ce5b

[tttt 5774123] Revert "哈勃包名更改测试。"
3 files changed, 3 insertions(+), 5 deletions(-)

git revert 26c5d5a7ce5b命令会回把26c5d5a7ce5b的提交回退,并生成一次提交记录。

如果想一次revert多个提交点:

git revert 2c71073d2..b688116bde

注意:

2c71073d2 :是旧提交点,也就是比 b688116bde提交时间早

提交点是两个点之间的,每一个提交都会生成已给提交记录。

使用2c71073d2..b688116bde其实比单独一个2c71073d2是一样的,如果回退5个提交,则会出现5次提交记录。

9.2.3 代码已经扩散,麻烦别人删除分支,然后从新拉取代码

如果别人已经拉取你的分支代码了,还可以然他删除这个分支,然后从新拉取代码。

  1. 本地使用git reset回退到一个历史版本中。

  2. 使用git push -f强推到服务器仓库。

  3. 别人要做如下操作:

    git checkout master  	// 切换到其他分支
    git branch -d tt		// 删除有问题的分支
    git fetch -a			// 提取所有git信息到本地
    git checkout tt			// 此时你的新分支代码就没问题了
    git pull
    
  4. 如果是Jenkins构建的,可在Jenkins配置里面的脚本先执行下面代码:

    git checkout master && git branch -d $branch && git fetch -a && git checkout $branch && git pull"
    

    $branch是Jenkins里面的分支名字变量。

10. 使用git log统计你在项目中的工作量

10.1 按提交记录时间段来统计

此方法统计从提交的开始时间到结束这一段时间所有的提交代码

git log --since=2018-01-01 --until=2018-12-31 --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }'

added lines: 36874, removed lines: 12214, total lines: 24660

上面的git命令按照2018-01-012018-12-31这段时间来统计你的代码提交量

10.2 按照提交用户名来统计

此方法可以统计项目中,该用户的工作量

git log --author="username" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }'

added lines: 29146, removed lines: 7457, total lines: 21689

注意把username改成真正的用户名。

10.3 按照用户名和时间段来统计

此方法过滤一段时间内,某个用户的代码量

git log --author="username" --since=2018-10-01 --until=2018-12-31 --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }'

added lines: 2068, removed lines: 953, total lines: 1115

注意把username改成真正的用户名。

10.4其他的统计方法

查看仓库提交者排名前 5

git log --pretty='%aN' | sort | uniq -c | sort -k1 -n -r | head -n 5

贡献值统计

git log --pretty='%aN' | sort -u | wc -l

提交数统计

git log --oneline | wc -l

添加或修改的代码行数:

git log --stat|perl -ne 'END { print $c } $c += $1 if /(\d+) insertions/'
Clone this wiki locally