git入门笔记

参考文献https://mp.weixin.qq.com/s/Km5KuXPETvG0wCGHrvj9Vg

众所周知,Git是目前世界上最先进的分布式版本控制系统(没有之一),同时github是世界上最大的同性交友平台。

通俗的讲git是这样一个软件,不但能自动帮我记录每次文件的改动,还可以让同事协作编辑,这样就不用自己管理一堆类似的文件了,也不需要把文件传来传去。如果想查看某次改动,只需要在软件里瞄一眼就可以,岂不是很方便?

git的基本操作大致如下

image.png

mac下安装git:

需要先安装Homebrew并且推荐换源成国内镜像
命令行下输入

brew install git

2.创建ssh key

1、设置username和email(github每次commit都会记录他们)

git config --global user.name "USERNAME"
git config --global user.email "EMAIL"

2 、创建ssh key
ssh-keygen -t rsa -C "EMAIL"
由于我之前创建过了,所以不再创建了。
命令行下输入

cat /Users/inf/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDkDRqRUlT75L3AbcfcOd8ReTxGfo6yQttj8unlD6nClSsgWs7LwQYPAjirHlR+u4eqklyUEWv807UHPAt1k36av/IwWBZgkQA
...

这里面的内容就是你的公钥

3、复制这里面的内容(包括ssh-rsa 和最后面你的邮箱),登陆github,点击settings,左侧找到SSH and GPG keys点击右边的添加
image.png
将你的公钥粘贴进去

4、验证连接
命令行输入

$ ssh -T git@github.com
Hi WhyCyrils! You've successfully authenticated, but GitHub does not provide shell access.

说明连接成功
接下来用几个场景来说明git的用法

场景一:git本地版本库的基本用法

通常有两种获取 Git 项目仓库的方式:

  1. 将尚未进行版本控制的本地目录转换为 Git 仓库;
  2. 从其它服务器 克隆 一个已存在的 Git 仓库。

git init方法

在此我创建了一个AdvancedSE文件夹

cd cd project/AdvancedSE

输入

$ git init
Initialized empty Git repository in /Users/inf/project/AdvancedSE/.git/

该命令将创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。
便成功在此目录下初始化了一个git的本地版本库。
如何删除?只需输入命令
rm -rf .git

git clone方法

或者,我在github上新建一个远程库,AdvancedSE

同时进入到AdvancedSE文件夹的上一级,删除AdvancedSE

如果我在当前文件夹即AdvancedSE文件夹下输入git clone 命令,这会在当前目录下创建一个名为 “AdvancedSE” 的目录,并在这个目录下初始化一个 .git 文件夹, 从远程仓库拉取下所有数据放入 .git 文件夹,然后从中读取最新版本的文件的拷贝。
这样看起来文件结构就会变成/AdvancedSE/AdvancedSE/。

输入

git clone git@github.com:WhyCyrils/AdvancedSE.git

进入该文件夹AdvancedSE,输入ls查看

$ ls
LICENSE   README.md

显示了两个文件LICENSE 和README.md都是创建远程仓库创建好的
项目目录下执行git status命令即可查看Git本地版本库当前 workspace 的状态。

$git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

因为是刚拉取的版本所以显示nothing to commit, working tree clean

  1. 修改README.md文件的内容,添加一行test1
# AdvancedSE
高级软件工程

test1

如果使用的是vscode,这时候点击版本控制按钮

可以看到相比上一个版本比项目的所有更改,即当前 workspace 的状态。

  1. 输入git add .
    输入git add .或者git add README.md将当前目录或者指定文件添加到暂存区(Index)。

如果需要从暂存区删除,使用

  • git reset HEAD FILES # 指定文件或文件列表 或者
  • git reset HEAD
    这两个命令是取消将特定文件(FILES)或者所有文件添加到暂存区(Index),即从暂存区(Index)中删除;只有在暂存区登记的文件才会在提交代码时存入版本库。

如果需要放弃特定文件(FILES)或者所有文件的修改,实际上重新检出特定文件(FILES)或者所有文件到工作区(workspace),使用

  • git checkout -- FILES # 不要忘记“--” ,不写就把FILES当分支名了
  • git checkout

注意会覆盖掉已修改未暂存的内容,不希望被覆盖的文件可以先使用git add将其添加到暂存区。

  1. 输入git commit -m "test1"
    将暂存区的文件提交到仓库,可以看到vscode里面工作树显示的已经是统一了

  2. 再增加一行test2并添加到暂存区,再用commit命令提交到仓库。

  3. 输入git log查看提交记录,按q退出

commit ec3b1a448e7a01f8bbafd8016d1e15541e4ba54e (HEAD -> main)
Author: inf <14718249608@163.com>
Date:   Sun Oct 11 23:05:39 2020 +0800

    test2

commit 669462f8e5c496e5ab2139a9202b9d4185362393
Author: inf <14718249608@163.com>
Date:   Sun Oct 11 23:00:53 2020 +0800

    test1

commit deb72321528df01022480b1e4376fd259509ba45 (origin/main, origin/HEAD)
Author: WhyCyrils <14718249608@163.com>
Date:   Sun Oct 11 22:01:58 2020 +0800

    Initial commit
(END)
  1. 输入git reset --hard HEAD^
$ git reset --hard HEAD^
HEAD is now at 669462f test1

git reset --hard XXX 可以让HEAD回退到任意一个版本,比如HEAD^表示HEAD的前一个版本、HEAD^^表示HEAD的前两个版本、HEAD~100表示HEAD的前100个版本,也可以用版本号字符串来指定任意一个版本。

  1. 输入git reflog 按q退出
669462f (HEAD -> main) HEAD@{0}: reset: moving to HEAD^
ec3b1a4 HEAD@{1}: commit: test2
669462f (HEAD -> main) HEAD@{2}: commit: test1
deb7232 (origin/main, origin/HEAD) HEAD@{3}: clone: from git@github.com:WhyCyrils/AdvancedSE.git
(END)

值得注意的是HEAD只是一个指向特定版本的指针,通过git reset —hard 回退之后,HEAD指向的不是最新的版本,而git log只能查看HEAD及其之前(时间更早)的提交记录。
git reflog命令可以查看HEAD指向的版本之后的提交记录

8.输入git reset --hard ec3b1a4

$ git reset --hard ec3b1a4
HEAD is now at ec3b1a4 test2

总结

git init # 初始化一个本地版本库
git status # 查看当前工作区(workspace)的状态
git add [FILES] # 把文件添加到暂存区(Index)
git commit -m "wrote a commit log infro” # 把暂存区里的文件提交到仓库
git log # 查看当前HEAD之前的提交记录,便于回到过去
git reset —hard HEAD^^/HEAD~100/commit-id/commit-id的头几个字符 # 回退
git reflog # 可以查看当前HEAD之后的提交记录,便于回到未来
git reset —hard commit-id/commit-id的头几个字符 # 回退

场景二:Git 远程版本库的基本用法

上面已经使用git clone克隆了github上创建的项目
在平时的合作项目中,我们对远程库一般有几种操作
git pull、git push、git merge等

  • git clone 克隆一个远程库到本地目录。
  • git fetch 下载一个远程存储库数据对象等信息到本地存储库。
  • git push 将本地存储库的内容推送到远程存储库。
  • git merge 合并两个或多个开发历史记录。
  • git pull 从其他存储库或分支抓取并合并到当前存储库的当前分支。
  1. git remote
$ git remote
origin

默认的远程库名称为origin

  1. git remote -v查看更详细的远程库信息
origin	git@github.com:WhyCyrils/AdvancedSE.git (fetch)
origin	git@github.com:WhyCyrils/AdvancedSE.git (push)
  • fetch(抓取)的远程存储库URL
  • push(推送)的远程存储库URL
  1. git pull
$ git pull
Already up to date.

由于远程仓库一开始拉取之后就没变化,因此显示Already up to date.

  1. git push
$ git push
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 573 bytes | 573.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:WhyCyrils/AdvancedSE.git
   deb7232..ec3b1a4  main -> main


可以看到test1 和test2都在README.md中更新了。

更新的文件必须由暂存区提交到仓库
即需要 add -> commit->push的顺序

场景三:团队项目中的分叉合并

我们建议团队项目的每一个开发者都采用的工作流程大致如下:

  1. 克隆或同步最新的代码到本地存储库;
  2. 为自己的工作创建一个分支,该分支应该只负责单一功能模块或代码模块的版本控制;
  3. 在该分支上完成某单一功能模块或代码模块的开发工作;
  4. 最后,将该分支合并到主分支。

如果我们足够细心,那么就会发现克隆到本地仓库的默认分支不叫master了,而是main了。

in ~/project/AdvancedSE on git:main o [23:38:46]

这是因为国外的政治因素,这里不再详细展开

  1. git branch
* main
(END)

2.git checkout -b mybranch

$ git checkout -b mybranch
Switched to a new branch 'mybranch'

创建一个新的分支
3. git branch

  main
* mybranch
(END)

*号表示当前工作区处于mybranch分支

  1. README.md中新增一行test3,addcommit
$ cat README.md
# AdvancedSE
高级软件工程

test1

test2

test3%

注意这一切都发生在mybranch分支

  1. git checkout main
    切换回main分支
$ cat README.md
# AdvancedSE
高级软件工程

test1

test2

发现没有test3

  1. git merge mybranch
$ git merge mybranch
Updating ec3b1a4..b7a01b3
Fast-forward
 README.md | 2 ++
 1 file changed, 2 insertions(+)

检查一下

$ cat README.md
# AdvancedSE
高级软件工程

test1

test2

test3
  1. 使用git merge --no-ff mybranch
    切换到mybranch并在README.md新增test4,并add后commit
git checkout mybranch
git add .
git commit -m "test4"
git checkout main
git merge --no-ff mybranch

最后一句话会弹出vi界面,按一下esc输入:wq(冒号+wq)
使用--no-ff参数后,会执行正常合并,保留mybranch分支为一段独立的分支线段,在Master分支上生成一个新节点。合并后大致如下示意图。

场景四:Git Rebase

场景四实际就是在场景三团队项目工作流程中增加一步Git Rebase,即在mybranch分支上完成自己的工作之后,为了让 log 记录将来更容易回顾参考,用 git rebase 重新整理一下提交记录。注意不要通过rebase对任何已经提交到远程仓库中的commit进行修改。
Rebase命令git rebase -i [startpoint] [endpoint]

  1. 切换到mybranch分支,在README.md添加两行test5 test6,每添加一行就add-commit一次。

2.切回main分支git checkout main,执行一次git push把之前的test3 test4更新到远程仓库。这时候的commit是test4

  1. main分支下README.md添加一行test7,并add-commit-push。
    执行 git log
commit 213d6918f37d753fcdb973406b98fb00f1d64089 (HEAD -> main)
Author: inf <14718249608@163.com>
Date:   Mon Oct 12 00:46:20 2020 +0800

    test7

commit b1921585db6ddbde285b408ccacecc1dc9371c40 (origin/main, origin/HEAD)
Author: inf <14718249608@163.com>
Date:   Mon Oct 12 00:01:29 2020 +0800

    test4

commit b7a01b3f13df096e6ea9d0468e07df6e06ab668a
Author: inf <14718249608@163.com>
Date:   Sun Oct 11 23:55:11 2020 +0800

    test3
...

(commit "test4"由于我rebase了一次,所以精简了一下)

4.切换回mybranch,执行git log

commit 5e5bdc5cd0a0796cb6d044e537bac2cac12fc56a (HEAD -> mybranch)
Author: inf <14718249608@163.com>
Date:   Mon Oct 12 00:36:47 2020 +0800

    test6

commit f321f464f3511758137ba7e9a467a8dc81c6d7bb
Author: inf <14718249608@163.com>
Date:   Mon Oct 12 00:36:13 2020 +0800

    test5

commit b1921585db6ddbde285b408ccacecc1dc9371c40 (origin/main, origin/HEAD)
Author: inf <14718249608@163.com>
Date:   Mon Oct 12 00:01:29 2020 +0800

    test4
...
  1. git rebase -i HEAD^^
pick f321f46 test5
pick 5e5bdc5 test6
  1. git rebase main解决冲突

    我这里选择保留双方更改
    点采用当前更改,就是保留test7,会好一点

  2. git add .

  3. git rebase --continue
    这是候仍然要解决冲突

9.继续git add .git rebase --continue

$ git rebase --continue
Applying: test6
  1. git checkout main
$ cat README.md
# AdvancedSE
高级软件工程

test1

test2

test3

test4

test7

11.git merge mybranch

$ git merge mybranch
Updating 213d691..b1f5702
Fast-forward
 README.md | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
(base)

冲突解决完毕

  1. git push

  2. 发现我们在这个过程中解决了两次冲突
    应该是git rebase -i命令出现了问题,mybranch重新运行git rebase -i HEAD~3
    将下面两个pick 改为s

pick 213d691 test7
s e6ddc8b test5
s b1f5702 test6

最后添加一个commit,完成了wq保存退出
输入git log

commit 57837179707bb1f98060483d8e7d81b671cf2921 (HEAD -> mybranch)
Author: inf <14718249608@163.com>
Date:   Mon Oct 12 00:46:20 2020 +0800

    combines test

    test7

    test5

    test6

总结

git rebase 作用:

  1. 将多次commit合并为一次
  2. 合并分支时只需要解决一次冲突
    两次解决冲突是因为git rebase -i命令出错,并没有将test5 和test6合并为一次提交
posted @ 2020-10-12 01:20  狄杰斯特拉  阅读(126)  评论(0编辑  收藏  举报