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 # 删除远程标签:必须先从本地删除,然后再推送到远程

设置忽略文件

操作:

  1. 在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去

  2. .gitignore文件提交到Git,Git就会自动忽略这些文件。

  3. # gitignore文件里内容的格式
    .* # 排除所有.开头的隐藏文件
    *.class # 排除所有.class文件
    !.gitignore # 不排除.gitignore
    !App.class # 不排除App.class:
    

原则是:

  1. 忽略操作系统自动生成的文件,比如缩略图等;
  2. 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
  3. 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

配置命令的别名

每个仓库的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的图),保存当前最新的一次提交的哈希值,文件指示目前被检出的分支

image

index:暂存区(stage),一个二进制文件,文件保存暂存区信息

ORIG_HEAD:HEAD指针的前一个状态

packed-refs:当更新一个引用时,git不会packed-refs,而是会在refs/heads下写入一个新文件。当查找一个引用时,git首先在refs目录下查找,如果未找到则到packed-refs文件中去查找。

五、安装Gitlab服务器

六、 特殊问题

问题1

git status 查看状态时出现中文乱码

解决:

  1. 执行git config --global core.quotepath false
  2. 步骤1没成功。在git bash的空白处右键,选择 Options。将 Text(中文 是 文本) 下的 Local 设置为 zh_CN,字符集选中为 UTF-8,点击Save保存设置
posted @ 2022-08-02 22:15  fengqiyunyouyong  阅读(88)  评论(0)    收藏  举报