一、git常用流程
主要就是push代码到远程仓库,不会pull不会的话每次删除clone就是了(大项目可能会比较慢)
0. Git安装与配置
(1) linux服务器上安装git:sudo wget https://github.com/git/git/archive/v2.8.0.tar.gz
(2) 解压安装:sudo tar -zxvf v2.8.0.tar.gz -C /app/git
(3) 安装依赖:sudo yum -y install zlib-devel openssl-devel cpio expat-devel gettext-devel curl-devel perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker
(4) 编译:
make prefix=/app/git all
make prefix=/app/git install
(5) 配置/etc/profile文件
GIT_HOME=/app/git
path=$GIT_HOME/bin:$path
(6) 配置git
git config --global user.name "ChronousZhang"
git config --global user.email "1276298750@qq.com"
git config --global core.autocrlf false
git config --global gui.encoding utf-8
(7) 生成ssh key:ssh-keygen -t rsa -C "1276298750@qq.com"
,一直回车即可
(8) 查看ssh key:cat ~/.ssh/id_rsa.pub
(9) 去github依次下拉头像,Setting,SSH and GPG Keys, SSH Keys中New SSH key,输入Title和linux中cat查看的密钥
(9) 测试配置是否成功:ssh -T git@github.com
(10) 出现Hi ChronousZhang! You've successfully authenticated, but GitHub does not provide shell access.
表示配置成功
1. 拉取
假设远程仓库为:https://github.com/用户名/仓库名.git
- 拉取master分支:
git clone https://github.com/用户名/仓库名.git
- 拉取指定分支:
git clone -b 分支名 https://github.com/用户名/仓库名.git
- 拉取指定tag:
git clone -b 标签名 https://github.com/用户名/仓库名.git
- 进入仓库所在目录(clone下来的文件有.git隐藏文件记录版本操作)
- 注意远程仓库如果有软链,就去linux下clone,win下clone好像会丢失所有软链
2. 分支操作
- 查看已有分支:
git branch
- 创建新分支:
git branch 新分支名
- 切换分支:
git checkout 分支名
3. 本地修改代码
愉快的写代码吧!
4. 查看修改信息
git status
5. 将新增、修改、删除记录到本地仓库
git add .
# 有删除就用git add -A
或git add -all
git commit -m "描述本次修改"
6. tag操作【可选】
- 查看已有tag:
git tag
- 查看+利用|grep过滤tag:
git tag |grep 过滤条件
- 增加tag:
git tag -a tag名 -m "相关描述"
7. push到远程仓库
- push所有tag:
git push origin --tags
- push到master分支:
git push origin master
- push到指定分支:
git push origin 分支名
8. 修改脚本后发现跑不起来了,想恢复到上一个版本
- 从本地仓库的上一次
commit
中恢复main.py
:git checkout HEAD main.py
9. git回退到某个历史版本
先使用git log
命令查看所有的历史版本,并根据commit msg
定位某个历史版本的id
,假设查到历史版本的id
是139dcfaa558e3276b30b6b2e5cbbb9c00bbdca96
,然后执行 git reset --hard 139dcfaa558e3276b30b6b2e5cbbb9c00bbdca96
就可以把本地恢复到该历史版本;需要推到远程服务器的话则git push -f -u origin master
二、一些特殊情况处理
1. 一些常见出错情况
case I:error: failed to push some refs to 'https://github.com/syb666/Django-admin.git'
$ git push origin master
Fatal: HttpRequestException encountered.
Username for 'https://github.com': syb666
To https://github.com/syb666/Django-admin.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/syb666/Django-admin.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
出错原因是远程仓库和本地仓库不一致,在hint
中也有提示把远程库同步到本地库就可以了
解决办法:
$ git pull --rebase origin master
$ git push origin master
# 该命令的意思是把远程库中的更新合并到(pull=fetch+merge)本地库中,–-rebase的作用是取消掉本地库中刚刚的commit,并把他们接到更新后的版本库之中。出现如下图执行pull执行成功后,可以成功执行git push origin master操作。
## 或者强制push本地仓库到远程 (这种情况不会进行merge, 强制push后远程文件可能会丢失 不建议使用此方法)
$ git push -u origin master -f
$ git push origin master
## 再或者避开解决冲突, 将本地文件暂时提交到远程新建的分支中
$ git branch [name]
# 创建完branch后, 再进行push到该分支
$ git push -u origin [name]
case II: fatal: Unable to create '/xxx/xx/.git/index.lock': File exists.
在git
没有运行完成之前强制关闭,下次提交的时候会产以下生错误,或者类似的报错:
fatal: Unable to create '/xxx/xx/.git/index.lock': File exists.
If no other git process is currently running, this probably means a
git process crashed in this repository earlier. Make sure no other git
process is running and remove the file manually to continue.
原因是在你进行某些比较费时的git
操作时自动生成,操作结束后自动删除,相当于一个锁定文件,目的在于防止对一个目录同时进行多个操作。有时强制关闭进行中的git
操作,这个文件没有被自动删除,之后你就无法进行其他操作,必须手动删除,进入.git
文件中删除,打开显示隐藏文件。如果没有看见.git
文件夹,可以直接用命令rm -f ./.git/index.lock
。之后就可以正常使用。
case III:项目中空的
文件夹无法添加到远程仓库
git
不支持提交空文件夹,所以需要在空文件夹里面随便添加一个什么文件才行
case IV:项目中非空
文件夹也无法添加到远程仓库
原因未知,但可以通过git rm --cached folder
后git add folder
,然后commit
和push
即可,其中folder
是无法提交的那个文件夹。
case V:warning: LF will be replaced by CRLF in ...
原因是存在符号转义问题。windows
中的换行符为 CRLF
, 而在linux
下的换行符为LF
,所以在执行git add .
时出现提示,解决办法:git config --global core.autocrlf false
2. 代码量统计
git log --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 }' -
3. 代码贡献量统计
# 每个user
git log --format='%aN' | sort -u | while read name; do echo -en "$name\t"; git log --author="$name" --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 }' -; done
# 前三user
git log --pretty='%aN' | sort | uniq -c | sort -k1 -n -r | head -n 3
# 某个user
git log --author="用户名" --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 }'
# 代码`commit`统计
git shortlog -s | sort -rn | head
4. 代码合并问题
假设存在两个分支main
和dev
分支,分别是项目上线用的主分支
和本地开发使用的开发分支
。
那现实世界存在的几种生产环境有哪几种?
- 远程
dev
分支没修改,但远程main
被队友修改了,如何将远程main
合并到本地的dev
并推到远程的dev
# 首先切换到本地仓库的main分支
git checkout main
# 将远程仓库的main分支合并(更新/拉取)本地的main分支
git pull
# 本地仓库切换到dev分支
git checkout dev
# 将本地main分支合并到本地的dev分支
git merge main # git merge branch1 branch2 将branch1分支合并到branch2, 而branch2省略则表示将branch1合并到当前分支
# 本地dev分支推送到远程dev分支
git push -u origin dev
- 远程
main
分支没修改,但自己本地的dev
修改了,如何将本地dev
合并到远程的main
并推到远程的main
# 首先切换到本地仓库的dev分支
git checkout dev
# 将远程仓库的dev分支合并(更新/拉取)本地的dev分支【可选,一般dev权限自己有,这时一般就不用pull了,而main分支未必有权限】
git pull
# 本地仓库切换到main分支
git checkout main
# 将本地dev分支合并到本地的main分支
git merge dev
# 本地main分支推送到远程main分支
git push -u origin main
# 那没有main的权限咋整?可以选择在远程仓库合并。这种情况的处理居多:
git checkout dev
git push -u origin dev
远程提合并,别人审核后就合并到main分支了
- 最重要和常见的是:远程
main
分支修改了,且自己本地的dev
也修改了,如何将远程main
合并到本地的dev
并推到远程的main
方法一
# 首先切换到本地仓库的main分支
git checkout main
# 将远程仓库的main分支合并(更新/拉取)本地的main分支
git pull
# 本地仓库切换到dev分支
git checkout dev
# 将本地main分支合并到本地的dev分支
git merge main
# 这种情况下merge后就没那么舒服了,由于main和dev的修改不一致,所以merge会引发冲突,比如得到如下结果显示:
Auto-merging main.txt
CONFLICT (content): Merge conflict in main.txt
Automatic merge failed; fix conflicts and then commit the result.
# 被强制合并后可以会发生以下冲突(即上面提到的main.txt):
this is the command of main branch
<<<<<<< HEAD
this is the command of dev branch
=======
this is the another command of main branch
>>>>>>> main
其含义为:
this is the command of main branch
是共有的;<<<<<<< HEAD
到=======
中间的内容this is the command of dev branch
是dev
分支的内容;而=======
到>>>>>>>
之间的内容this is the another command of main branch
是main
分支的内容;
然后对照上面的冲突提示
将本地main
的结果修改到本地dev
的结果(苦力活)。
此外,还可以使用git diff dev main
来查看两个分支的差别。
最后将修改后的本地dev
分支推送到远程dev
分支,再合并到远程main
分支。
方法二:
远程main
分支提merge request
合并到dev
分支,(当然你权限比较大直接远程dev
合并到远程main
也行,这样做的话直接远程合并的时候审核合并内容,然后pull到本地dev
并推送到远程dev
即可),然后dev
审核合并冲突后pull到本地dev
,再本地merge
到本地main
,并push到远程main
(需要比较大的权限)。也可直接远程dev
审核合并结果后反向合并到main
中。
这种方法比较乱,主要依托远程操作,可能多人协助成分大,还是方法一实在。
【参考博客】:https://blog.csdn.net/qq_27905183/article/details/78575247
5. 一些其他git使用函数
- 前面提到了
git merge br1 br2
,其实git rebase br1 br2
也有类似效果,但不要轻易使用,容易出问题。 git pull
有时候可能都会出现冲突Automatic merge failed; fix conflicts and then commit the result.
,这种情况下可以选择git fetch --all
然后git reset --hard origin/branch_name
来pull,这种就会将本地仓库中的内容强制替换为远程分支的内容。