Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

git

廖雪峰

  • 跟踪文本文件的改动

  • 不要使用Windows自带的记事本编辑任何文本文件。原因是Microsoft开发记事本的团队使用了一个非常弱智的行为来保存UTF-8编码的文件,他们自作聪明地在每个文件开头添加了0xefbbbf(十六进制)的字符

基础用法

1.git init

把当前目录变成Git可以管理的仓库:

$ mkdir learngit
$ cd learngit
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/

2.git add commit

  • git add
$ git add readme.txt
  • git commit
$ git commit -m "wrote a readme file"
[master (root-commit) eaadf4e] wrote a readme file
 1 file changed, 2 insertions(+)
 create mode 100644 readme.txt

-m后面输入的是本次提交的说明

查看 git status diff log

查看工作区状态

$ git status

查看文件变化

$ git diff readme.txt 
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
 Git is free software.

查看日志

git log命令显示从最近到最远的提交日志

$ git log
$ git log --pretty=oneline
1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL
e475afc93c209a690c39c13a46716e8fa000c366 add distributed
eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file

一大串类似1094adb...的是commit id(版本号),Git的commit id是一个SHA1计算出来的一个非常大的数字,用十六进制表示

版本切换git reset

  • 在Git中,用HEAD表示当前版本,也就是最新的提交,上一个版本就是HEAD^,上上一个版本就是HEAD^^,往上100个版本写成HEAD~100

回退到上一版本

$ git reset --hard HEAD^
HEAD is now at e475afc add distributed
  • 提供版本号(比如刚刚回退之前的最新版本的版本号开头是1094a,想到那个版本)

版本号没必要写全,前几位就可以了,Git会自动去找

$ git reset --hard 1094a
HEAD is now at 83b0afe append GPL
  • 原理

Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向append GPL

┌────┐
│HEAD│
└────┘
   │
   └──> ○ append GPL
        │
        ○ add distributed
        │
        ○ wrote a readme file

改为指向add distributed

┌────┐
│HEAD│
└────┘
   │
   │    ○ append GPL
   │    │
   └──> ○ add distributed
        │
        ○ wrote a readme file

然后顺便把工作区的文件更新了。

git reflog

git reflog查看你的每一次命令:

$ git reflog
e475afc HEAD@{1}: reset: moving to HEAD^
1094adb (HEAD -> master) HEAD@{2}: commit: append GPL
e475afc HEAD@{3}: commit: add distributed
eaadf4e HEAD@{4}: commit (initial): wrote a readme file

第一列是版本号

丢弃修改git checkout reset

  • git checkout -- file 用版本库里的版本替换工作区的版本(让这个文件回到最近一次git commitgit add时的状态)
$ git checkout -- readme.txt

命令git checkout -- readme.txt意思就是,把readme.txt文件 用版本库里的版本替换工作区的版本,这里有两种情况:

一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;

一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

  • git reset HEAD <file>可以把暂存区的修改撤销掉(unstage),重新放回工作区:
$ git reset HEAD readme.txt
Unstaged changes after reset:
M	readme.txt

删除文件

$ rm test.txt

把工作区文件删除之后(test.txt是已经提交了的),

用命令git rm删掉,并且git commit

$ git rm test.txt
rm 'test.txt'

$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 test.txt

现在,文件就从版本库中被删除了。

远程仓库

设置user name和email

如果你是第一次使用,或者还没有配置过的话需要操作一下命令,自行替换相应字段。

git config --global user.name "Luke.Deng"
git config --global user.email  "xiangshuo1992@gmail.com"

git config –list 查看当前Git环境所有配置,还可以配置一些命令别名之类的。

远程仓库地址操作

添加远程仓库:进入本地仓库执行:origin是给远程源的一个命名,你可以随便取

git remote add origin <远程仓库git的地址> 

修改远程仓库地址:

git remote set-url origin <remote-url>

仓库路径查询查询:

git remote -v

删除指定的远程仓库:

git remote rm origin

git push 本地仓库推送到远程仓库(已关联)

将本地当前分支 推送到 远程指定分支上(分支名字方向是 按**数据传输方向 ->**):

git push <远程仓库“名字”,在remote add的时候取的名字> <本地分支名>:<远程分支名> #若两个分支名字只写一个,则默认这俩分支名都是它

比如:

git push origin master # 将当前仓库的master分支推送到origin的master分支
git push origin main baseline # 将当前仓库的main分支推送到origin的baseline分支

-f强制推送到远程仓库,且覆盖远程代码库

git push -f origin master

git pull 从远程获取代码并合并本地的版本

分支名字方向是 按**数据传输方向 ->**:

git pull <远程仓库“名字”,在remote add的时候取的名字> <远程分支名>:<本地分支名>

比如:

git pull origin master

git clone远程仓库

进入本地目录:

git clone <远程仓库git地址>

这样执行git clone的目录下fork来的那个目录就是一个git目录了,并且自动关联远程仓库

克隆指定分支

git clone -b <指定分支名> <远程仓库git地址>

gitignore

在项目开发过程中个,一般都会添加 .gitignore 文件,规则很简单,但有时会发现,规则不生效。
原因是 .gitignore 只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。
那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交。

git rm -r --cached .
git add .
git commit -m "update .gitignore"

本地仓库关联git服务器上的.git

step1 git服务器上操作

下文用表示git服务器的外网ip地址

附:root如何创建用户:

例如创建“张三”用户:

useradd zhangsan
passwd hnuzs 
  • [可选]ssh免登陆操作

此步骤是为了在本地服务器连接远程git服务器时免于输入用户密码,具体操作如下:

将本地服务器的公钥id_rsa.pub传入远程git服务器的/home//.ssh/authorized_keys认证文件中

cat id_rsa.pub >> authorized_keys #pwd:/home/<user_name>/.ssh
  • 创建并初始化git仓库

首先创建一个目录作为git仓库并赋予所属用户

cd /home/<user_name>
mkdir zsgitrepo 
chown <user_name>:<user_name> zsgitrepo/  

接着使用git命令创建一个裸仓库,服务器上的git仓库通常以.git结尾,并更改仓库所属用户

cd zsgitrepo
git init --bare zsrepo.git 
chown -R <user_name>:<user_name> zsrepo.git 

step2 本地服务器上操作

  • 添加远程版本库
git remote add origin git@<git_server_ip>:/home/<user_name>/xxrepo/xx.git # git@<git_server_ip>:<absolute path to your .git on git server> 

关联后举例:git clone克隆仓库

注意clone的.git的地址

$ git clone <user_name>@<git_server_ip>:/home/<user_name>/zsgitrepo/zsrepo.git 
Cloning into 'zsrepo'... 

公匙

解决 remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.

解决方法:

本地服务器生成公匙并上传到远程服务器上,具体操作:

然后remote用ssh的地址,不用http的地址

linux下公匙私匙生成

公匙上传github

windows下公匙私匙生成

SSH-key 在Windows下如何生成公钥和私钥

在centos上搭建git服务器并自动同步代码 - 云+社区 - 腾讯云 (tencent.com)

git安装好后

右键选择Git GUI Here->Help->Show SSH Key

就能得到私钥和公钥

公钥上传远程git服务器的认证文件中

cat id_rsa.pub >> authorized_keys #pwd:/home/<user_name>/.ssh/

如果没有~/.ssh/authorized_keys就新建一个

cd /home/<user_name>
mkdir .ssh
chmod 700 .ssh
touch .ssh/authorized_keys
chmod 600 .ssh/authorized_keys

git原理

暂存区

工作区(Working Directory):比如刚刚git init所在的那个目录

版本库(Repository):工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库

Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

把文件往Git版本库里添加的时候,是分两步执行的:

第一步是用 git add把文件添加进去,实际上就是把文件修改添加到暂存区

第二步是用 git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。

因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。现在改成main了

gitflow

流程概念

错误示范:

不知道他怎么搞的,直接 pushmaster 分支去了,直接跨过开发分支测试分支,直接合到 master 发布分支上去了(一般来说,master都是有保护的!)。

这还不算什么。。。如果只是这样就还好,关键是他看有写代码冲突就直接在 master 分支上对已经成功发版的代码增删改!!!

一般来说,团队合作开发的话,每个人都需要在自己的功能分支 feat/XXX 上开发,最后一起合并到总的开发分支 dev 上,然后将开发分支 dev 合并到测试分支上,最后将测试分支合并到正式发布分支上。

其中总的开发分支一般叫做 dev 分支,正式发布分支一般是叫 main/master/release 分支。

一般的开发流程:

比如说有 A、B、C 三个人协助进行功能开发:

1、首先 A、B、C 三位小伙伴从总开发分支 Dev 上开辟自己的功能分支,分别是 feat/AXXX、feat/BXXX、feat/CXXX,也就是图中 feat/AXXX、feat/BXXX、feat/CXXX 的三条线;

2、然后在自己的开发机上进行开发,这里的开发机可以是本地环境也可以是一些云端的开发机。开发完毕后,再分别合到总开发分支 dev 上,也就是图中蓝色的三条线,在这个过程中可能会产生一些代码冲突,挨个 solve 即可;

3、接着在 dev 分支上确认所有功能开发完毕,进行简单自测,fix 一些 bug 后再向测试分支上进行合并;

4、这个时候就可以艾特测试组的同学来进行测试,测试通过后再合到 master 分支进行发布。

GitFlow流程 - 简书 (jianshu.com)

img

git提交-m规范

type (scope): message

参数介绍:

1、type:指的代码的提交类型,不同的提交类型表示对应不同的代码改动,比如:

  • feat:新功能的开发
  • fix:bug的修复
  • docs:文档格式的改动
  • style:代码格式改变
  • refactor:对已有的功能进行重构
  • perf:性能优化
  • test:增加测试
  • build:改变了build工具
  • revert:撤销上一次的commit提交
  • chore:构建过程或辅助工具的变动

2、scope:用于说明commit影响的范围,比如:权限模块、还是首页

3、message: 对提交的代码做一个简短的说明,不能过长。

fix(系统菜单图标):添加缺少的图标

问题

git: Failed to connect to 127.0.0.1 port 1080: Connection refused

在git init顶层目录下

git config --global --unset http.proxy  
git config --global --unset https.proxy

OpenSSL SSL_read: Connection was reset, errno 10054

git config --global http.sslVerify "false"

Failed to connect to github.com port 443 after 21114 ms: Timed out

用ssh的那个地址

评论