git
git
一、简介
官网:https://git-scm.com/
github:https://github.com/git/git
二. 安装
windows
linux
apt 安装
apt install git
apt remove git
git --version
yum 安装
yum install git
yum remove git
git --version
源码包安装
# 1. 安装依赖
apt install make gcc wget libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev
# 2. 下载源码包
cd /opt/git/source
wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.37.1.tar.gz
# 3. 解压、编译、安装
cd /opt/git/source
tar -zxvf git-2.37.1.tar.gz
mkdir /opt/git/git-2.37.1
cd /opt/git/source/git-2.37.1
make prefix=/opt/git/git-2.37.1 all
make prefix=/opt/git/git-2.37.1 install
# 4. 配置环境变量
echo 'export GIT_HOME=/opt/git/git-2.37.1' >> /etc/profile
echo 'export PATH=$GIT_HOME/bin:$PATH' >> /etc/profile
source /etc/profile
三、命令
关键词
repository:仓库
Working Directory:工作区
stage(index):暂存区
stash:贮藏区
commit:提交
merge:合并
checkout:检出
branch:分支
commit id:版本号,每次提交的uuid
HEAD:当前版本
HEAD^:上一个版本
HEAD^^:上上一个版本
HEAD~100:不算自己,上数第100个版本
remote:远程
origin:起源,这里可以代指远端
remote origin:远程原点,远点
版本库:./git隐藏文件
match:般配,匹配
detached:独立的
discard:丢弃
Untracked:未被跟踪的
基础操作
创建仓库
# 创建仓库
git init # 当前文件夹成为根目录
git init <repository> # 指定文件夹成为根目录
添加文件
# 添加
git add <file1> <file2> ... # 添加1个或多个文件从工作区到暂存区
git add --all # 将工作区所有未被添加的文件添加到stage中
git add -A # 同上
提交
# 提交
git commit -m "提交的信息" # 提交当前所有在暂存区的文件到本地仓库
git commit -m "提交的信息" [<file1> <file2> ...] # 提交指定暂存区的文件到本地仓库
推送
# 推送
git push origin <branch> # 将某个分支<branch>推送到远端
查看状态
# 查看状态相关命令
git status # 查看当前仓库中中所有文件的状态
git log # 查看当前分支相关的所有commit日志
git log --pretty=oneline # 查看当前分支相关的所有commit日志,用一行展示
git log --graph --pretty=oneline --abbrev-commit # # 查看当前分支相关的所有分支合并情况
git reflog # 查看执行过的每一次命令
git branch # 查看当前所在分支,并列出所有分支,当前分支前有 * 号
git branch -a # 查看所有分支
git diff HEAD -- readme.txt # 查看工作区和版本库里面最新版本的区别
查看文件的变化
# 查看文件的变化
git diff <file> # 查看文件的变化,Git命令中的diff采用的格式就是UNIX的合并格式
git diff -u <更改之前的文件名> <更改之后的文件名> # 命令格式
# 例子:1.txt为1先提交一次,再修改一次不add和commit
git diff -u 1.txt 1.txt
hello
world
nihao
world
diff --git a/1.txt b/2.txt
index 9db7df0..e5168f2 100644 # 以上两行显示两个文件的基本信息,文件名和时间,其中“---”表示更改之前的文件,“+++”表示更改之后的文件
-- a/1.txt
++ b/1.txt
@@ -1,2 +1,2 @@ # 前面的”-1,2″分成三个部分:减号表示第一个文件(即f1),”1″表示第1行,”2″表示连续7行。合在一起,就表示下面是第一个文件从第1行开始的连续7行。同样的,”+1,2″表示变动后,成为第二个文件从第1行开始的连续2行。
-hello # -:修改后的文件删除的内容
+nihao # +:修改后的文件增加的内容
word # 空:修改后的文件无变动
\ No newline at end of file
删除OR还原
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file。
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,就回到了场景1,第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,使用版本回退,不过前提是没有推送到远程库。
# 删除OR还原
# 版本回退
git reset --hard HEAD^ # 回退到上一个版本
git reset --hard 1094a # 回到原来的某个版本,版本号没必要写全,前几位就可以了,Git会自动去找
# 撤销修改
git checkout -- <file> # 把<file>文件在工作区的修改全部撤销,这里有两种情况:一种是<file>自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;一种是<file>已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。就是把文件返回到最近一次git commit或git add时的状态。
git reset HEAD # 把暂存区的修改撤销掉(unstage),重新放回工作区:
git reset HEAD [<file1> <file2> ...] # 把暂存区的修改撤销掉(unstage),重新放回工作区:
# git reset 既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
# 删除文件
git rm <file> # 删除版本库里的文件,已在working directory中删除文件后,再从版本库中删除文件(删除完记得commit),git rm <file>和git add<file>效果是一样的,从来没有被添加到版本库就被删除的文件,是无法恢复的!
git restore <file> # 还原版本库里的文件
远程操作
remote
# 远程操作
git remote add origin <远程仓库地址> # 绑定远程仓库
git remote add origin git@github.com:zhangguanghuicn/learngit.git # 例子
git push -u origin master # 将本地masterpush到远程仓库
git checkout -b dev origin/dev # 创建远程分支
# 创建dev分支,并切换到dev分支上,最后将本地分支推送到远端
git switch -c dev && git push origin dev
git clone git@server-name:path/repo-name.git # 如果在远端创建好仓库,本地不需要创建仓库,直接克隆仓库
git remote -v # 查看远程库信息
pull多人协作冲突
# pull多人协作冲突
git branch --set-upstream-to=origin/dev dev # 指定本地`dev`分支与远程`origin/dev`分支的链接
git pull # 拉取远程仓库内容到本地,会出现冲突
git status # 查看冲突
修改冲突
git push origin master|dev
rebase解决远程多人协作冲突
# rebase解决远程多人协作冲突,可用于本地,也可用于提交远程前的准备
git rebase dev
修复冲突
git add 冲突文件
git commit -m "提交修复文件"
git rebase --abort # 如果不想rebanse了,在任何时候,可以用--abort参数来终止rebase的操作,并且”mywork“ 分支会回到rebase开始前的状态。
git rebase --continue # 修复完所有文件后执行,继续rebase
git switch dev
git merge --no-ff -m "提交信息" mywoork # 建议使用--no-ff,会保留被合并分支的提交信息,否则使用fast-forward会导致丢失合并分支的commit信息,比如在使用cherry-pick的时候会用到issue的提交信息,否则如果删除了issue后,就无法获取issue的commit id了,自然使用不了cherry-pick
# 可用git log --graph --pretty=oneline --abbrev-commit查看当前版本的信息
分支操作
创建分支
# 创建分支
git branch <branch> # 基于当前分支创建新分支,只能创建一个分支
git branch <branch> <basebranch> # 基于basebranch分支创建新分支,只能创建一个分支
git checkout <branch> # 切换分支
git switch <branch> # 切换分支,git2.23版本发布的,建议使用,checkout会有歧义
git checkout -b <branch> # 基于当前分支创建新分支并切换到新分支,-b:branch;相当于 git branch <branch> && git checkout <branch>
git switch -c <branch> # 同上,-c:checkout;相当于 git branch <branch> && git switch <branch>
git checkout -b <targetBranch> <baseBranch> # 基于<baseBranch>分支创建新分支并切换到新分支,-b:branch
git switch -c <targetBranch> <baseBranch> # 同上,-c:checkout
删除分支
# 删除分支
git branch -d <branch> # 删除分支,根据当前分支自动监测是否已经merge,会有提示;如果当前分支是被删除分支的base分支,会自动监测是否已经merge,如果已经merge,则删除,否则提示需要merge;如果当前分支不是被删除分支的base分支,会自动监测是否已经merge,即使已经merge到base分支,也会提示需要merge
git branch -D <branch> # 强删,不管是否merge,直接强删
合并分支
# 合并分支
git merge <branch1> <branch2>... # 只能将多个分支合并到当前分支,不能指定合并到哪个分支;默认使用的是fast-forward合并,主分支不会保留被合并分支的提交信息
git merge --no-ff -m "合并的信息" <branch1> <branch2>... # 只能将多个分支合并到当前分支,不能指定合并到哪个分支;--no-ff:强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息
当在feature上工作时,紧急需要修复dev上的bug
# 当在feature上工作时,紧急需要修复dev上的bug
git stash # 将当前至上一次提交后的所有修改都贮藏到贮藏区中,可以贮藏多次,比如贮藏一次后又有新增,可以再次贮藏;进入贮藏区后的内容是所有分支都共享的,比如在feature上的贮藏,在dev上也能看得和恢复;贮藏区实际就是个栈结构
git stash list # 查看贮藏区内所有贮藏
git stash apply # 恢复贮藏的内容,但是不会将其在贮藏区删除;恢复贮藏栈中第一项
git stash drop # 删除贮藏栈中第一项
git stash pop # 弹出贮藏栈中第一项,相当于git stash apply && git stash drop
git cherry-pick <commit id> # 当issue分支修复后合并到dev后,需要自己在feature上也修复,可以在feature上改代码手动修复,也可以将其用git cherry-pick <commit id> 来合并进行修复;这个commit id可以在issue上看到,但前提是不能合并到dev后就将其删除,这样就找不到commit id了。另外一种方式就是,dev合并issue时,使用--no-ff进行合并,commit id可以用git log --graph --pretty=oneline --abbrev-commit来查到
标签操作
创建标签
# 创建标签
git tag <name> # 打新标签;默认标签是打在最新提交的commit上的
git tag v1.0
# 忘记打标签,找到历史提交的commit id,然后打上就可以了
git log --pretty=oneline --abbrev-commit # 找到历史提交的commit id
git tag v0.9 f52c63 # 给指定commit打标签
git tag -a v0.1 -m "version 0.1 released" 1094adb # 创建带有说明的标签,用-a指定标签名,-m指定说明文字
git tag # 查看所有标签; 标签不是按时间顺序列出,而是按字母排序的。
git show <tagname> # 查看标签信息;可以看到说明文字
操作标签
git tag -d v0.1 # 删除打错了的标签;创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。
git push origin <tagname> # 推送某个标签到远程
git push origin --tags # 一次性推送全部尚未推送到远程的本地标签
git tag -d v0.9 && git push origin :refs/tags/v0.9 # 删除远程标签:必须先从本地删除,然后再推送到远程
设置忽略文件
操作:
-
在Git工作区的根目录下创建一个特殊的
.gitignore文件,然后把要忽略的文件名填进去 -
将
.gitignore文件提交到Git,Git就会自动忽略这些文件。 -
# gitignore文件里内容的格式 .* # 排除所有.开头的隐藏文件 *.class # 排除所有.class文件 !.gitignore # 不排除.gitignore !App.class # 不排除App.class:
原则是:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的
.class文件; - 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
配置命令的别名
每个仓库的Git配置文件都放在
.git/config文件中当前用户的Git配置文件放在用户主目录下的一个隐藏文件
.gitconfig中
# 配置命令的别名,--global参数是全局参数,
git config --global alias.st status # git st git status
git config --global alias.co checkout # git co : git checkout
git config --global alias.ci commit # git ci : git commit
git config --global alias.br branch # git br : git branch
git config --global alias.unstage 'reset HEAD' # git unstage : git reset HEAD
git config --global alias.last 'log -1' # git last : gitlog -l
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
四、.git里文件的结构
.git
├── HEAD #文本文件,当前工作区所在的分支
├── branches
├── config #gi相关配置,比如远程地址、分支指、策略、模式等
├── description
├── hooks #钩子,在不同生命周期git暴露出了相关钩子
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ └── update.sample
├── index #暂存区,索引文件,可以用gitls-fles查看
├── info
│ └── exclude
├── logs #提交日志,各个分支都有,这也就是git离线之后可以log原因
│ ├── HEAD
│ └── refs
│ ├── heads
│ │ └── master
│ └── remotes
│ └── origin
├── objects #带文件存储最重要的一个目录
│ ├── 92 #松散文件存储文件夹,文件夹名来自SHA1前2个字符
│ │ └── f6defe4087f19b967167338695086988db5ad6
│ ├── 97
│ │ └── 85a9ee96bdddcf9c29a546980d68b308ef4144
│ ├── c2
│ │ └── bd9b83d94207ac0df37e7352760543a4c2c7d1
│ ├── c4
│ │ └── b1e1e776fa5895cd11ce26f93d3a50e7ae052d
│ ├── info #目录info,比如打包文件名是什么等
│ └── pack #松散文件打包之后会生成相关*.idx+".pack文件
├── packed-refs #将refs下文件进行打包到一个文件,一般是每个分支最后一个修改集
└── refs #每个分支最后一个修改集,分支其实就是一个快照,快照体现就是修改集
├── heads
│ └── master
├── remotes
│ └── origin
│ └── HEAD
└── tags
hooks :包含客户端或服务端的钩子脚本,存放一些shell脚本
(可以自定义在代码提交过程中应该做的事,比如在代码提交前检测代码格式是否符合规范)
info:exclude:存放仓库的一些信息,包含一个全局性排除文件(记录不需要git进行管理的文件)
logs:保存日志信息,保存所有更新的引用记录
objects :存放所有的git对象,存储所有数据内容
refs:heads:保存当前最新的一次提交的哈希值,存储指向数据(分支)的提交对象的指针
COMMIT_EDITMSG:最新提交的一次Commit Message,git系统不会用到,给用户一个参考
config:git仓库的配置文件,文件包含项目特有的配置选项
description:仓库的描述信息,主要给gitweb等git托管系统使用
FETCH_HEAD:是一个版本链接,指向着目前已经从远程仓库取下来的分支的末端版本
HEAD:映射到ref引用,能够找到下一次commit的前一次哈希值(看上面logs的图),保存当前最新的一次提交的哈希值,文件指示目前被检出的分支

index:暂存区(stage),一个二进制文件,文件保存暂存区信息
ORIG_HEAD:HEAD指针的前一个状态
packed-refs:当更新一个引用时,git不会packed-refs,而是会在refs/heads下写入一个新文件。当查找一个引用时,git首先在refs目录下查找,如果未找到则到packed-refs文件中去查找。
五、安装Gitlab服务器
六、 特殊问题
问题1
git status 查看状态时出现中文乱码
解决:
- 执行
git config --global core.quotepath false - 步骤1没成功。在git bash的空白处右键,选择 Options。将 Text(中文 是 文本) 下的 Local 设置为 zh_CN,字符集选中为 UTF-8,点击Save保存设置

浙公网安备 33010602011771号