git学习笔记

73 阅读13分钟

一、git工作区、暂存区以及版本库

        在初始化git版本库之后会生成一个隐藏的文件.git ,可以将该文件理解为git的版本库 repository,而我们自己建立的项目文件夹即工作区 working directory ,在.git 文件夹里面还有很多文件,其中有一个index文件就是暂存区 ,git还为我们自动生成了一个分支master以及指向该分支的指针HEAD,三个的关系具体如下图所示:

1.工作区

就是你在电脑里能看到的目录。

2.暂存区

临时保存修改文件的地方。一般存放在.git下的index文件(.git/index)中。

git add 修改文件 ---- 就是把修改文件放到暂存区中

3.版本库

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

git commit -m “...” ---- 就是把文件存到git仓库

二、配置git

用户名和邮箱地址是本地git客户端的一个变量,每次commit都会用用户名和邮箱纪录。

1.设置用户名

git config --global user.name xxx

2.设置邮箱

git config --global user.email xxx@example.com

三、初始化

1.仓库创建

创建仓库目录

mkdir git_exam

进入仓库目录

cd git_exam

初始化仓库

git init

# Initialized empty Git repository in /data00/home/xxxxxx/go/src/git_exam/.git/

之后会在根目录下生成.git文件夹

2.设置忽略

在根目录下创建.gitignore文件

touch .gitignore

添加忽略名单,如忽略output文件夹,output文件夹在我们现有工程里面都是默认忽略的

echo output .gitignore

将.gitignore文件加入版本管理并提交

四、git基本操作

1.添加文件

工作修改之后,添加文件到暂存区

(1)添加单个文件

git add README.md

(2)添加所有文件

git add .

2.提交文件

从暂存区提交到仓库

(1)提交单个文件

git commit -m "commit message" README.md

(2)提交所有文件

git commit -m "commit message" -a

(3)默认提交所有文件

git commit -m "commit message"

3.查看提交记录

git log

commit 18104a7dc1ff27b90d7342dccd814c4408b8c303
Author: xxxxx <xxxxx@bytedance.com>
Date:   Fri Feb 22 19:21:16 2019 +0800     
        commit message 3 

commit b75344f419bf2305354be525da69330f039ed9f0
Author: xxxxx <xxxxx@bytedance.com>    
Date:   Fri Feb 22 19:10:03 2019 +0800
        commit message 2 

commit 1edf8527a85c66642313d6a5d5db16f40c833259
Author: xxxxx <xxxxx@bytedance.com>
Date:   Mon Feb 18 15:12:25 2019 +0800         
        commit message 1

git log指令不加其他参数,可以列出所有历史提交,分析如下:

(1)按照提交的时间顺序排列,上层的是更新的提交。

(2).commit后面是经过SHA-1加密算法对此次提交计算的结果,可以唯一标识此次提交,后续成为commit-id。

(3)Author后面分别是提交的用户名和电子邮件地址,它们之间用空格分隔。

(4)Date后面是提交的时间日期。

(5)Date垂直的下方中间以空格分隔的是提交信息说明。

4 查看文件修改状态

列出被修改的文件

git status

和暂存区的内容比较

git diff

和上次提交的内容比较

git diff HEAD

和上上次提交的内容比较

git diff HEAD^

和历史提交(commit-id)的内容比较

git diff commint-id

5.分支操作

(1)列出所有本地分支

git branch

(2)列出所有远程分支

git branch -r

(3)列出所有本地和远程分支

git branch -a

(4)显示本地分支的提交状态

git branch -v

(5)显示本地分支与远程分支的对应关系

git branch -vv

(6)创建分支

git branch 分支名

(7)切换分支

git checkout 分支名

(8)基于当前分支创建并切换分支

git checkout -b 分支名

(9)基于远程分支创建

git checkout -b 本地分支名 远程分支名

(10)强制删除分支

git branch -D 分支名

6.取消工作区的修改

有两种方式:(1)用版本库里面的内容。(2)用暂存区的内容

  • 用版本库里面的内容取消文件修改:

(1)单个文件

git checkout HEAD README.md

(2)多个文件

git checkout HEAD README.md SUMMARY.md

(3)所有文件

git checkout HEAD .

关于checkout,除了切换分支、撤销修改以外,还有一个很好的用法,就是快速查看项目旧版本,比如

git checkout commitId

通过传入历史提交的 id,将 HEAD 移动到相应的历史提交处,方便查看历史代码

  • 用暂存区的内容取消文件修改:

(1)单个文件

git reset HEAD README.md

(2)多个文件

git reset HEAD README.md SUMMARY.md

(3)所有文件

git reset HEAD .

(4)取消暂存并撤销工作区的修改,以所有文件为例

git reset --hard HEAD .

(5)复位到上上次提交(HEAD代表上次提交)

git reset --hard HEAD^^

(6)复位到历史某一次提交

git reset --hard commitId

7.关联远程远程分支到本地

(1)clone 远程仓库到本地

git clone url

(2)remote 添加远程仓库

git remote add origin url

(3)remote 删除远程仓库

git remote rm origin

(4)remote 查看远程仓库地址

git remote -v

(5)remote 修改远程仓库地址,有三个选项:--add、--delete、--push

git remote origin set-url [url]

(6)push 推送更改到远程仓库

git push

(7)若本地分支和远程分支没有对应上,则可以

git push --set-upstream origin master

git push -u origin master

将本地分支和远程分支关联

(8)pull 拉取远程更改到本地并合并

git pull --rebase

五、git实用操作

1.revert撤销某次提交(gitlab把分支合入master后会看到这个命令)

有时候你可能想撤销某次提交,但不想改变提交历史,这时候可以用revert,撤销一个提交的同时会创建一个新的提交。这是一个安全的方法,因为它不会重写提交历史。

(1)先查看提交日志

git log

commit 18104a7dc1ff27b90d7342dccd814c4408b8c303
Author: xxxxx <xxxxx@bytedance.com>
Date:   Fri Feb 22 19:21:16 2019 +0800

     commit message 3

commit b75344f419bf2305354be525da69330f039ed9f0
Author: xxxxx <xxxxx@bytedance.com>
Date:   Fri Feb 22 19:10:03 2019 +0800

        commit message 2 

commit 1edf8527a85c66642313d6a5d5db16f40c833259
Author: xxxxx <xxxxx@bytedance.com>
Date:   Mon Feb 18 15:12:25 2019 +0800

         commit message 1

如果相对最后一次提交进行revert,可以执行如下命令:

git revert HEAD

再次查看git log

commit 545952fd83fe0c6ec320bd1e004f4e518967142bAuthor: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:35:26 2019 +0800Revert "commit message 3"commit 18104a7dc1ff27b90d7342dccd814c4408b8c303Author: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:21:16 2019 +0800commit message 3commit b75344f419bf2305354be525da69330f039ed9f0Author: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:10:03 2019 +0800commit message 2commit 1edf8527a85c66642313d6a5d5db16f40c833259Author: xxxxx <xxxxx@bytedance.com>Date: Mon Feb 18 15:12:25 2019 +0800commit message 1

2.git rebase master

我们在作分支合并的时候最常用的就是merge操作,但是执行merge之后,会产生一个新的commit,例如:Merge branch 'branch-1'。这个commit把两个branch合并到一起并作了一次新的提交。但是,如果使用rebase的话就会避免这个问题。我们来看一个例子,下边是我分别用merge和rebase之后的git log。

如果我们有一个分支master,现在master上有两个提交:c1、c2,如下图所示:

       master          /c1 - c2

如果此时我们基于master新建一个分支:

git checkout -b git_exam master

此时git的commit记录指向如下:

        master          /c1 - c2      \        git_exam

我们在git_exam上提交了更改:c3、c4,另外一个同事在master上提交了更改:c5、c6,此时分支结构如下:

                  master                  /        c5 - c6        /c1 - c2       \         c3 - c4              \               git_exam

如果我们想把c5 c6更改线性的合入我们的分支,可以执行如下命令:

git checkout master          #切换到master分支
git pull --rebase            # 拉取master的最近更新,并线性合并
git checkout git_exam        # 切换到我们自己的分支
git rebase master            # 把git_exam的提交历史和master的提交历史线性合并

在git_exam分支执行git rebase master,git具体完成的操作主要有下:

git会先把你的git_exam分支里的每个提交(commit)取消掉,并且把它们临时保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把git_exam分支更新 为最新的master分支,最后把保存的这些补丁应用到git_exam分支上。

以上命令执行完以后具体的分支指向大体如下:

                  master                  /c1 - c2 - c5 - c6 - c3 - c4                          \                           git_exam

3.解决rebase过程中的冲突

在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决 冲突;在解决完冲突后,执行如下命令去更新内容的索引(index):

git add  解决冲突后的文件

然后,你无需执行 git commit,只要执行:

git rebase --continue

这样git会继续应用(apply)余下的补丁。

在任何时候,你可以用--abort参数来终止rebase的行动,并且git_exam分支会回到rebase开始前的状态。

git rebase --abort

4.git rebase 和 git merge的区别

git merge 是用来合并两个分支的。

git merge b        # 将b分支合并到当前分支

同样

git rebase b       # 也是把 b分支合并到当前分支

对与git rebase master一节中,如果使用git merge master,会生成一个新的commit用来表示合并操作,具体的分支指向结构图如下:

                  master                  /        c5 - c6        /c1 - c2 - c5 - c6       \           \         \            c7  -  git_exam                   \          /            c3 - c4  

5.git的变基/把多次提交合并为一个

当你想对历史某一次提交进行修改,又不想增加新的提交时,可以使用变基操作。

比如:你正在进行开发,你发现有个参数名写错了,属于小问题,而这个参数正是你历史提交中某一次引入的,你想修改这个参数名而不产生新提交,这时候可以使用变基:

git rebase -i commit-id
# commit-id 是最后一次不需要合并的提交id

执行git log命令

commit 545952fd83fe0c6ec320bd1e004f4e518967142bAuthor: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:35:26 2019 +0800Revert "commit message 3"commit 18104a7dc1ff27b90d7342dccd814c4408b8c303Author: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:21:16 2019 +0800commit message 3commit b75344f419bf2305354be525da69330f039ed9f0Author: xxxxx <xxxxx@bytedance.com>Date: Fri Feb 22 19:10:03 2019 +0800commit message 2commit 1edf8527a85c66642313d6a5d5db16f40c833259Author: xxxxx <xxxxx@bytedance.com>Date: Mon Feb 18 15:12:25 2019 +0800commit message 1

如果我想把以下三个分支合为一个提交,毕竟commit message 3的提交最后被revert 了

b75344f419bf2305354be525da69330f039ed9f0 --- commit message 218104a7dc1ff27b90d7342dccd814c4408b8c303 --- commit message 3545952fd83fe0c6ec320bd1e004f4e518967142b --- Revert "commit message 3"

那么最后一次不需要合并的commit-id就是

1edf8527a85c66642313d6a5d5db16f40c833259 --- commit message 1

可以执行如下命令:

git rebase -i 1edf8527a85c66642313d6a5d5db16f40c833259

执行完上述命令会弹出编辑框:

pick b75344f commit message 2pick 18104a7 commit message 3pick 545952f Revert "commit message 3"# 变基 4220233..545952f 到 42202333 个提交)## 命令:# p, pick <提交> = 使用提交# r, reword <提交> = 使用提交,但修改提交说明# e, edit <提交> = 使用提交,进入 shell 以便进行提交修补# s, squash <提交> = 使用提交,但融合到前一个提交# f, fixup <提交> = 类似于 "squash",但丢弃提交说明日志# x, exec <命令> = 使用 shell 运行命令(此行剩余部分)# b, break = 在此处停止(使用 'git rebase --continue' 继续变基)# ...

采用融合到前一个提交的方式:

修改如下:

pick b75344f commit message 2s 18104a7 commit message 3s 545952f Revert "commit message 3"# 变基 18104a7..545952f 到 b75344f(3 个提交)## 命令:# p, pick <提交> = 使用提交# r, reword <提交> = 使用提交,但修改提交说明# e, edit <提交> = 使用提交,进入 shell 以便进行提交修补# s, squash <提交> = 使用提交,但融合到前一个提交# f, fixup <提交> = 类似于 "squash",但丢弃提交说明日志# x, exec <命令> = 使用 shell 运行命令(此行剩余部分)# b, break = 在此处停止(使用 'git rebase --continue' 继续变基)# ...

保存后会弹出编辑框:

# 这是一个 3 个提交的组合。# 这是第一个提交说明:commit message 2Change-Id: b75344f419bf2305354be525da69330f039ed9f0# 这是提交说明 #2commit message 3Change-Id: 18104a7dc1ff27b90d7342dccd814c4408b8c303# 这是提交说明 #3:Revert "commit message 3"This reverts commit 545952fd83fe0c6ec320bd1e004f4e518967142b.# 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交# 说明将会终止提交。## 日期: Tue Mar 5 09:50:59 2019 +0800## 交互式变基操作正在进行中;至 4220233# 最后的命令已完成(3 条命令被执行):# squash 18104a7 remove commit message 3# squash 545952f Revert "commit message 3"# 未剩下任何命令。# 您在执行将分支 'working' 变基到 '4220233' 的操作。

把没有注释的删除,改成你想要的提交提示语,保存即可

# 这是一个 3 个提交的组合。# 这是第一个提交说明:commit message 2# 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交# 说明将会终止提交。## 日期: Tue Mar 5 09:50:59 2019 +0800## 交互式变基操作正在进行中;至 4220233# 最后的命令已完成(3 条命令被执行):# squash 18104a7 remove commit message 3# squash 545952f Revert "commit message 3"# 未剩下任何命令。# 您在执行将分支 'working' 变基到 '4220233' 的操作。