@[toc]
一、Git配置
使用 Git Bash 控制台操作
- 初始化
git init
-
.git文件夹下的文件含义
- HEAD 文件指示目前被检出的分支
- description 用来显示对仓库的描述信息
- config 文件包含项目特有的配置选项,本项目的配置,全局的在
对应系统相应用户的文件夹/.gitconfig
- info 目录包含一个全局性排除文件
- hooks 目录包含客户端或服务端的钩子脚本
- index 文件保存暂存区信息
- objects 目录存储所有数据内容
- refs 目录存储分支的提交对象的指针
- branches 新版本已经废弃无须理会
查看用户名与邮件配置(查看改动记录非常方便)
git config user.name
git config user.email
- 设置(修改)用户名与邮件
git config --global user.name "hahadasheng"
git config --global user.email "liuchnegdage@sina.com"
- 修改配置信息(低版本)
git config --global --replace-all user.name "lc"
可以直接修改全局配置文件,在用户主目录下;比如Windows的在当前用户的用户文件夹下
C:\Users\administrator\.gitconfig
- 允许命令超长路径
# git 设置支持超长路径
git config --system core.longpaths true
- 配置代理 一般正规点的公司都有防火墙,上网需要代理服务器
git config --global http.proxy http://some.name.you.know:80
二、鉴权 拉取代码
1). SSH 推荐
- 生成非对称加密密钥对
ssh-keygen
将
~/.ssh/id_rsa.pub
的内容拷贝到托管平台克隆代码
git clone
- 拉去代码
git pull
2). HTTP(S) 不方便,不推荐
- 直接 clone (指定文件可选,建议不写) 输入托管平台的用户名密码
git clone <url> [localDirName]
- 缓存用户名密码
# 默认15分钟
git config –-global credential.helper cache
# 设置为一个小时
git config credential.helper ‘cache –timeout=3600’
# 永久记住秘密
git config --global credential.helper store
~/.gitconfig 全局配置文件下会记录此配置
[credential]
helper = store
三、提交代码一般流程
工作区:正在编辑的文件夹下的文件,没有通过
git add
添加的文件
暂存区:通过git add
添加但是没有git commit
的文件所在的区域
- 拉取远程代码
git pull
- 如果拉取失败, 一般是本地未提交的修改的文件与与服务器提交记录的文件有重合
git stash
git stash list
可以查看当前本地stash的栈中有哪些修改,栈中可以存放多个分支的本地修改
git pull
git stash pop
注意,需要stash栈中栈顶对应的分支修改与当前一致,否则可能导致本地修改丢失
git stash list //查看本地stash栈中的记录
git stash apply stash@{0} //选中对应的记录应用到当前工作区域,记录不会被删除
检查是否有冲突,如果有则手动解决
检查改动文件 (可选),显示为红色
git status
* Untracked: 未跟踪,一般为新增文件,此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged.
* Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作.
* deleted: 文件已删除,本地删除,服务器上还没有删除.
* renamed:文件名称被改变
- 如果发现无意编辑了一个文件,可以将其还原到修改前的状态
# 还原指定文件
git checkout -- <fileName>
# 还原所有文件
git checkout .
- 将文件添加到暂存区
# 添加工作区指定修改文件到暂存区
git add <file>
# 添加所有修改文件到暂存区(忽略文件除外)
git add .
此时
git status
时在暂存区的文件显示为绿色
- 如果想取消添加到暂存区
git rm --cached <fileName>
--cached
作用为指定暂存区;不写默认则为工作区
- 提交到本地仓库
git commit . -m "commit message"
.
标识选择暂存区所有文件,如果只需要指定文件换成对应文件名即可。
- 最简单的提交方式
git push
四、diff 比较不同
1). 同个分支下的比较
- 查看工作区与暂存区文件的修改情况
# 查看所有文件
git diff
# 查看指定文件
git diff <fileName>
红色的-号代表删除的内容;绿色的加号表示添加的部分
- 查看暂存区与本地版本库的对比
# 查看所有文件
git diff --cached
# 查看指定文件
git diff --cached <fileName>
- 查看历史提交记录的哈希值
git log
commit 后面的哈市值则为对应的提交哈希值
- 工作区与对应的历史提交对比
git diff hash值 [<fileName>]
- 暂存区与提交记录对比
git diff --cached hash值 [<fileName>]
- 将工作区和暂存区文件与最新的版本库比较
git diff HEAD
HEAD代表当前所在的分支名,如果想比较其他分支可以将其改为其他分支名
- 比较两个历史记录
git diff hash值1 hash值2
- 工作区与历史版本进行比较
# 指定比较的历史版本
git diff <commit_hash>
# 比较最近的一次提交
git diff
- 比较两个历史版本
git diff <commit_hash1> <commit_hash2>
2) 不同分支下的比较
- 查看两个不同的分支有哪些文件不一样
git diff branch1 branch2 --stat
- 显示文件具体修改
git diff branch1 branch2 filename
- 显示全部文件修改(如果文件多则会眼花缭乱)
git diff branch1 branch2
- 查看一个分支有而另一个没有
# 查看dev有的记录但是master没有的记录
git log dev ^master
- 单纯比较差异,显示所有记录
git log branch1..branch2
有绿色显示的表示只在哪个分支上有,另一个没有
- 查看各个记录存在于哪些分支上
git log --left-right develop...test
commit后面有
<
表示develop;>
表示为test分支的提交记录
- 显示当前分支与其他分支最新版本进行比较
git diff <orher branch>
- diff可以跨分支进行对比
# 当前最新与其他分支的历史版本进行对比 `git log`查找commit_hash
git diff <other_commit_hash>
# diff 可以比较任意分支任意提交之间的差异
git diff <commit_hash1> <commit_hash2>
五、Git忽略文件权限问题
- Git会记录文件的权限,如果本地与版本库同一个文件需要合并,如果存在权限不一致则会产生冲突,实际工作中是几乎不会让Git记录文件的权限,可以配置一下让Git忽略文件的权限
# 项目局部配置
git config core.filemode false
# 全局配置
git config --global core.filemode false
六、忽略指定文件或目录
项目中的一些编译文件,或者不想提交的配置文件等可以过滤掉
- 在项目的工作区创建一个
.gitignore
的文件,Win下建议使用notepad++的另存为进行创建,直接创建文件会失败 - 每行代表一个忽略的文件,支持通配符,支持文件夹,支持文件
# 文件的忽略方式
.jeckins.ini
# 文件夹以及其下的所有文件
target/
.idea/
# 通配符
*.iml
# 防止通配符导致向提交的文件被忽略(如果是直接忽略则无效)
!want.jar
- 添加忽略的文件
.gitignore
配置有误的检查
git check-ignore -v <fileName>
- 强制添加被忽略的文件
git add -f haha.iml
- 保留忽略的文件夹下部分文件写法
# 忽略的文件夹
test/*
# 过滤的被忽略的文件夹下的文件
!test/index.html
上述的
*
号通配符必须得保留才能生效
- 忽略已经提交
commit
的文件(夹),先在.gitignore
中设置该文件(夹)为忽略,然后从暂存区中删除
# 移除缓存中的文件
git rm --cached <fileName>
# 如果是文件夹则需要在加一个参数
git rm -r --cached <dirName>
# 提交此次修改,由于忽略文件中已经忽略了此文件夹和文件,需要强制添加 -f
git add -f <dirName>
七、分支管理
- 查看本地分支 绿色表示当前分支
git branch
- 查看本地和远程所有分支
git branch -a
- 查看远程仓库信息
git remote show origin
- 切换到远程或者本地分支(远程或者本地已经存在的分支)
git checkout <exist branch>
- 新建本地分支 (将当前分支的版本拷贝过去)
git checkout -b <new branch>
- 将本地新建的分支推送到服务器
git push --set-upstream origin <new branch>
- 合并分支
git merge <other branch>
查看合并的结果
git log
哈希值后面有个(HEAD -> branch1,branch2) 就是合并的记录
- 普通删除分支,可避免数据丢失
git branch -d <branch name>
- 如果普通无法删除,使用强制删除分支
git branch -D <branch name>
- 恢复删除的分支
git branch <branch name> <hash value>
八、回滚提交,不会滚代码
工作中,有时提交的代码审核没有过(CI/KW等),被abandon了;后续可以在本地进行追加提交(中途不能有自己的新提交),但是有时候就想放弃此次提交,或者本地提交后想要丢弃,可以使用reset命令
- 查看需要回滚的提交节点,拷贝对应的哈希值(推荐直接在idea工具中操作)
git log
- 进行回滚
git rebase //将自己的提交放在前面,这样下方的reset就只回到上个版本就可以了
git reset 哈希值
- 如果想撤销最近的一次提交
git reset HEAD^
- 如果想撤销修改的代码
# 撤销某个文件并查看状态
git checkout filename && git status
# 撤销所有的修改到上次提交的位置
git checkout .
九、删除过期的分支,清理无意义数据
清理不需要的分支数据,提高响应速度
- 查看所有分支列表
git branch -a
红色的为远程分支
- 删除远程分支
git push origin --delete <remote branch>
控制台显示 deleted 表示删除成功
- 将远程分支与本地分支进行对比
git remote prune origin
- 查看本地分支的标注情况
git branch -vv
对应分支后面如果有
:gone
的标识则表示远程分支已经被删除,该分支可以被清理
- 删除本地分支
git branch -d <branchName>
十、配置多个远端仓库:把代码推送到不同的服务器
1) 每个仓库分别对应一个远程地址
配置多个远程仓库
- 查看当前地址
git remote -v
默认的仓库为origin; 显示的信息有
push
和fetch
两种
执行git push
会调用对应的push地址,执行git fetch
则会调用fetch地址;拉取代码默认情况下会产生一个远程仓库origin,
并且对应的push地址也只有一个。
补充:
git fetch
为只拉取更新,不进行合并git pull = git fetch && git merge
# 将某个远程主机的更新全部取回本地
git fetch <remoteAddr>
# 取回特定分支的更新
git fetch <remoteAddr> <branchName>
# 查看取回的信息
git log -p FETCH_HEAD
- 添加多个仓库
一般默认的仓库名为origin
git remote add <新的仓库名> <远程仓库地址>
- 提交代码时选择仓库
# review 提交方式
git push origin head:refs/for/master
# 直接提交方式
git push github master
# 不写仓库则push到默认仓库
git push
- 修改默认指定仓库
git push -u github
- 删除仓库
# 删除指定的仓库
git remote remove <仓库名称>
2) 一个仓库对应多个远程地址
执行一条命令,将代码往两个地址同时推送
- 向origin仓库中添加多个地址
git remote set-url --add origin <remoteAddr>
十一、代码覆盖
1) 本地覆盖远端
如果不小心提交了错误的信息到远程,可以用新的提交来覆盖,但是如果是敏感信息,这种方式显然有缺点,因为提交记录中还是可以查看到;不推荐使用此种方式;
- 查看需要回滚提交的哈希值
git log
- 回滚本地提交,不会滚代码改动
git reset <哈希值>
- 强制推送到远程
git push origin -f
此类命令比较危险,一般在托管品台比如GitLab上会对类似的操作进行权限设置
2) 远端覆盖本地
- 拉取远程最新代码,但是不进行合并
git fetch
- 将当前工作的差异部分丢弃掉,完全与目标保持一致
git reset --hard origin/master
这里origin/master则是目标比较分支
十二、恢复已删除的分支,文件等
前提是没有执行
git gc
清除信息,一般如果不手动执行此命令,git会对那些无用的object保留很长的时间
1) 恢复已删除的分支
- 显示分支管理命令 找到要恢复分支的某次提交前面的 commit_id
git reflog show
- 建立新的分支并进行恢复
git checkout <新取一个分支名称> <commit_id>
通过此种方式则重建的删除的分支
2) 回滚reset操作
如果想找回
git reset
之前的提交记录
- 查看操作历史
git reflog
- 找到reset之前的commit_id并回退到那个id即可
git reset --hard <commit_id>
3) 从历史版本中找回删除的文件
- 查看操作历史
git reflog
- 找到需要找回对应的commit_id
git checkout <commit_id> <需要找回的文件名称>
十三、单独回滚代码 记录不变只回滚代码
reset命令会回滚记录,如果远程由此记录,并禁止强制提交;则此时可以
使用revert命令只回滚代码
- 查询需要回滚代码的分支commit_hash(比如向撤销此次提交的代码修改)
git log
- 回滚需要撤销的提交
git revert <对应的commit_hash>
注意,撤销对饮的提交,revert后面的hash就是对应的那次提交
命令执行后会弹出一个合并代码的提示框,编辑好信息后
esc
:x
进行保存退出
再通过git log
发现多了一条Revert的记录,说明已经成功;此时可以用git diff <被回退的提交hash>
可以发现被回退的提交修改已经被放弃了。提交代码
git push
在使用 revert 去恢复某个版本代码时,Git 只会撤销指定版本的代码,对指定版本后的所有版本不会有任何影响。
比如说你提交了 1、2、3 三个版本,当你撤销版本2的时候,会生成版本4,但是不会对版本3产生影响。
git reset 与 git revert的比较
- git reset: 会改变之前的版本记录,可能会导致不能提交到远程仓库;
- git revert: 只会撤销某个版本的代码,然后在当前分支增加一条版本新记录;
- git revert: 只会撤销指定版本的代码,而不是指定版本后的所有版本。
十四、合并分支merge
1) 全部进行合并,不过滤特定文件
- 切换到需要合并的分支,比如将dev合并到test分支
git checkout test
- 将dev合并到test分支
git merge dev
如果出现冲突,建议使用工具手动解决冲突,(比如使用IEDA的Git解决冲突)
将解决后的冲突文件添加到暂存区并提交一个新的版本 (工具可能会自动执行这一步)
git add . && git commit -a
解决冲突后的提交需要使用
-a
选项
2) 忽略有冲突文件的合并
- 上述案例中的dev项目工作区添加一个文件
.gitattributes
写入内容
<忽略冲突文件的文件名> merge=ours
- 按照上述合并操作进行合并
合并后的test分支中对应文件如果和dev有冲突则保留原来的内容,如果没有冲突也会进行合并
十五、钩子事件
Git进一步学习可以研究哈,目前只是了解
1) 客户端钩子事件
- 钩子事件在一些特定命令执行时触发
- 钩子函数脚本在
.git/hooks
下面 - 钩子语法使用的为shell脚本,部分混杂了Perl代码,可以Pytho或者其他脚本语言编写
- 钩子触发的脚本文件需要正确命名,以.sample结尾的脚本文件,
- 一般情况下钩子触发的钩子名称
钩子名字 | 触发时间 |
---|---|
pre-commit | 执行git commit命令完成前被执行。 |
prepare-commit-msg | 在执行完pre-commit钩子之后被调用。 |
commit-msg | git commit执行完成后被调用。 |
post-commit | post-commit钩子在commit-msg钩子之后立即被运行 。 |
post-checkout | post-checkout钩子在使用git checkout命令时候会被调用。 |
pre-rebase | pre-rebase钩子在使用git rebase命令发生更改之前运行 |
pre-receive | pre-receive钩子在有人用git push向仓库推送代码时被执行。 |
update update | 钩子在pre-receive之后被调用,分别被每个推送上来的引用分别调用。 |
post-receive | 在成功推送后被调用,适合用于发送通知。 |
2) 服务端钩子使用 服务端接受推送时事件处理
- 服务端的钩子同样在
.git/hooks
下 - 服务端的钩子配置一般是在托管平台进行管理
十六、合并代码保留提交记录:rebase功能的使用
rebase与merge功能类似,但有所不同
-
git rebase
会将另外一个分支提交的所有新版本记录复制到当前分支中
2.切换到合并的分支,比如test
git checkout test
git rebase dev
merge与rebase的相似点:代码层面没有什么变化
-
merge与rebase的区别: 版本记录的变化
-
git merge
命令合并代码之后,版本记录会按照时间顺序排序,并自动产生一个Merge branch的版本;撤销操作会很麻烦 -
git rebase
命令合并代码之后,版本记录会将目标分支的版本放在后面,然后再将当前分支的版本记录放在前边,不会产生其他类似Merge branch的版本。撤销操作会相对容易
-
十七、复制指定记录到当前分支: cherry-pick
将另外一个分支中的某个版本单独复制到当前的分支中来; 建议在类似IDEA工具中进行操作,如果出现冲突可以很方便解决
- 在对应分支确定需要cherry-pick的提交
git log
- 切换到需要合并的分支
git cherry-pick <commit_hash>
十八、工作区暂存 stash解决提示代码未提交问题
git stash
命令会将当前工作区未提交的改动放在一个stash栈中,此时代码会与最新的提交保持一致,如果切换到
其他分支或者有改动再次执行,此时栈顶的元素会变成最新stash的记录
还有种场景;在
git pull
时发现本地未修改未提交的文件与在服务器最新提交的记录中也有修改导致pull失败;
此时可以使用git stash && git pull && git stash pop
合并修改,如果有冲突则解决冲突。
- 执行stash命令
git stash
- 查看stash栈中存放的记录
git stash list
- 从stash栈中恢复栈顶的的提交,并保持栈顶的记录
git stash apply
- 从stash栈中恢复指定的提交,并保持对应的记录
git stash apply <编号如stash@{0}>
- 从stash栈中弹出栈顶的元素,栈中被弹出的则不会保留
git stash pop
- 清除stash栈中指定的提交
git stash drop <提交的id比如stash@{1}>
- 清空stash栈中的信息
git stash clear
十九、解决临时紧急任务的开发思路
场景复现:dev分支正在开发下一个迭代版本,预计2个月;test分支为当前发布线上版本;
先有一个必须在一周上线的紧急任务!-
设计思路:
- 从test中新建一个分支 temp,并在temp中完成紧急开发。
- 将temp中新的提交记录通过
git rebase
的方式经提交记录复制到test版本中进行测试上线 - 为了避免将来代码合并产生冲突,将temp中的新提交
git rebase
到dev开发分支中
二十、代码冲突解决总结
-
git merge
和git pull
命令导致的冲突,处理完冲突后使用git commit -a
; -
git rebase
命令导致的冲突,处理完冲突之后使用git rebase --continue
或git rebase --skip
; -
git stash apply
命令导致的冲突,处理完冲突之后使用git add .
即可。 - 终极解决方案:使用IDEA或者乌龟git处理冲突,直观、大气、方便、效率高
二十一、Git瘦身方案
1) 克隆最后一个版本,避免Git拉去所有的历史版本导致缓慢
- 本地克隆
git clone <remoteAddr> --depth==1
代码不会改变,只是历史提交记录只有一条
2) 清空版本记录
- -新建本地干净分支,只保留最后一次版本信息
git checkout --orphan <new_branch_name>
- 删除久的分支
git branch -D <branch_name>
- 将新的分支重命名为原有分支
git branch -m <branch_name>
- 强制推送到远程服务器(临时关闭强制推送限制)
git push -f origin <branch_name>
3) 清理大文件(比较高级)
使用
git branch-filter
可以遍历 Git 的版本历史信息
- 找出大文件对应的hash值,这里一找出前5个为例
git verify-pack -v .git/objects/pack/pack-*.idx | sort -k 3 -g | tail -5
- 根据hash值找到对应文件名
git rev-list --objects --all | grep <hash_value>
- 执行删除文件命令
git filter-branch --index-filter 'git rm --cached --ignore-unmatch <file_name>'
- 删除无用的记录信息
rm -rf .git/refs/original/ && git reflog expire --expire=now --all
- 重新建立文件与 Git 仓库的关联关系
git fsck --full --unreachable
- 重新压缩代码,减少仓库体积
git repack -A -d
- 执行GC,清理垃圾
git gc --aggressive --prune=now
- 强制推送到远程
git push --force origin master
二十二、Docker快速搭建GitLab
1) 快速搭建Docker环境
Linux环境Docker安装略
- 拉去镜像
docker pull gitlab/gitlab-ce
- 创建本地持久化卷
mkdir -p ~/config/gitlab/config
mkdir -p ~/config/gitlab/logs
mkdir -p ~/config/gitlab/data
假设默认用户为ubuntu 则
~ = /home/ubuntu
- 运行容器
docker run --detach --publish 8443:443 \
--publish 8090:80 --publish 2222:22 \
--name gitlab --restart always
-v /home/ubuntu/config/gitlab/config:/etc/gitlab \
-v /home/ubuntu/config/gitlab/logs:/var/log/gitlab \
-v /home/ubuntu/config/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce
进入
http://localhost:8090
即可进入Gitlab页面
- 查找容器ID
docker ps |grep gitlab/gitlab-ce
- 进入容器
docker exec -it <容器ID> sh
- GitLab配置文件路径
/opt/gitlab/embedded/service/gitlab-rails/config/gitlab.yml
- GitLab容器内总开关命令
gitlab-ctl restart // 重启
gitlab-ctl stop // 停止
gitlab-ctl start // 启动
二十三、补充
- git tag标签的使用
- 远端分支强制覆盖本地对应分支
git fetch --all
git reset --hard origin/<branch_name>
git pull