Loading

v

Git 简单介绍 + 实战

本文基于孟宁老师的公众号文章:五⼤场景玩转 Git,只要这一篇就够了!

1. Git基础

1.1 安装Git

各个版本的操作系统安装Git的方式不尽相同,以Ubuntu为例:

sudo apt install git

1.2 创建仓库

init —— 创建一个Git仓库

首先选择一个位置。

$ cd ~
$ mkdir hello-git
$ cd hello-git/

使用git init命令可以创建一个本地的git仓库。

$ git init
Initialized empty Git repository in /home/fzh/hello-git/.git/

创建后,当前目录下会自动生成一个.git隐藏目录,该目录下保存了git的所需信息,如非必要尽量不要手动修改。

$ ls -a
.  ..  .git

clone —— 从远程克隆一个Git仓库

首先,在Github上创建一个仓库。

点击复制地址

$ git clone https://github.com/fzhovo/hello-github.git
Cloning into 'hello-github'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 586 bytes | 48.00 KiB/s, done.

$ ls hello-github/
README.md

1.3 修改与提交

首先创建一个文件用于示范。

$ cd hello-git

$ echo This is the first version. > code.txt

$ cat code.txt
This is the first version.

add —— 将修改添加到暂存区

修改文件后,利用add命令将工作区修改后的文件添加到暂存区。

$ git add code.txt

此时使用git ls-files可以看到我们刚才添加的文件。

$ git ls-files
code.txt

除了单个文件,git add命令还可以一次添加多个文件,或者添加整个目录。

commit —— 提交已经暂存的修改

$ git commit -m "initial commit"
[master (root-commit) 2d383ab] initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 code.txt

执行commit命令会将之前添加到暂存区中的全部修改提交到版本库。

使用-m参数可以为这次提交添加一段描述。

如果是首次使用,可能会出现以下提示:

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

这时只需按照提示配置下邮箱和姓名即可。

提交完成后可以使用git log命令查看版本记录。

$ git log
commit 2d383ab81f8048dbb377eb88d1ff43a94d49d8d8 (HEAD -> master)
Author: fzh <fzhovo@163.com>
Date:   Sun Oct 4 13:46:02 2020 +0800

    initial commit

1.4 穿越时空

reset —— 回到过去

首先我们对code.txt做一点点修改,之后再提交上去。

$ sed -i 's/first/second/g' code.txt

$ cat code.txt
This is the second version.

$ git add .

$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   code.txt
        
$ git commit -m "second commit"
[master cf8d20c] second commit
 1 file changed, 1 insertion(+), 1 deletion(-)

这时,使用git log查看一下提交历史,使用--oneline参数可以将每次提交的简略信息在一行内显示.

$ git log --oneline
cf8d20c (HEAD -> master) second commit
2d383ab initial commit

假如我们现在想要回到初始的版本,可以使用reset命令

$ git reset --hard HEAD^
HEAD is now at 2d383ab initial commit

$ cat code.txt
This is the first version.

可以看到文件已经回到了初始的版本。这里的HEAD^是指当前版本的上一个版本,同理,当前版本的上一个版本的上一个版本可以表示成HEAD^^,或者HEAD~2,以此类推。

除此之外,我们还可以使用版本号进行切换,例如我们可以通过版本号回到第二个版本,如果忘记了可以使用git reflog命令查看。

$ git reset --hard cf8d20c
HEAD is now at cf8d20c second commit

$ cat code.txt
This is the second version.

现在我们就又穿越回来啦。

2. 远程版本库

回到第一章里我们在Github中创建的仓库。在本地创建两个目录user1和user2,来模拟两个用户。使用git clone命令克隆两份到本地。

$ mkdir user1 user2

$ ls
hello-git  hello-github  user1  user2

$ cd user1
$ git clone https://github.com/fzhovo/hello-github.git
Cloning into 'hello-github'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 586 bytes | 39.00 KiB/s, done.
$ cd ../user2/
$ git clone https://github.com/fzhovo/hello-github.git
Cloning into 'hello-github'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 586 bytes | 117.00 KiB/s, done.

push —— 推送

假设现在用户1使用vim编辑一下README文档,并在本地提交修改。

$ cat README.md
# hello-github
- 这里是用户1添加的部分

$ git add README.md

$ git commit -m "user1"
[main 01d9143] user1
 1 file changed, 2 insertions(+), 1 deletion(-)

之后可以使用git push将本地的版本推送到远程仓库

$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 282 bytes | 282.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/fzhovo/hello-github.git
   c02f188..01d9143  main -> main

在Github界面就可以看到提交的修改啦。

pull —— 拉取

这时用户2想要从远程仓库获取最新的版本,就可以使用git pull

$ cat README.md
# hello-github

$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 262 bytes | 20.00 KiB/s, done.
From https://github.com/fzhovo/hello-github
   c02f188..01d9143  main       -> origin/main
Updating c02f188..01d9143
Fast-forward
 README.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
 
$ cat README.md
# hello-github
- 这里是用户1添加的部分

拉取成功后即可看到用户1添加的部分。

3. 分支

3.1 创建分支

使用git branch branchName创建一个分支。

$ git branch newBranch

$ git branch
* main
  newBranch

可以用git branch查看现有的分支,前面用“*”标注的是当前分支。使用git checkout可以切换分支。

$ git checkout newBranch
Switched to branch 'newBranch'

$ git branch
  main
* newBranch

还可以使用git checkout -b branchName一键创建切换分支

$ git checkout -b newBranch

3.2 合并分支

$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.

$ git merge newBranch
Already up to date.

4. 团队合作

4.1 基本流程

假如在实际工作中,用户2在自己的新分支上修改了代码,以VSCode为例,如下图:

修改后,在源代码管理界面会提示添加并提交修改。

提交完成后,先切换回主分支

再从远程仓库拉取代码

执行下面命令合并分支

git merge --no-ff newBranch

$ git merge --no-ff newBranch
Merge made by the 'recursive' strategy.
 README.md | 5 +++++
 1 file changed, 5 insertions(+)

4.2 处理冲突

当发生冲突时,VSCode会提供如下图的交互界面,可以手动处理冲突后,重新提交。

5. Rebase

$ git log --oneline
d75bd55 (HEAD -> main) 4
05592ee 3
3b1cf19 2
0e447c5 1

使用rebase命令

$ git rebase -i HEAD^^^

这时会打开文本编辑界面

pick 3b1cf19 2
pick 05592ee 3
pick d75bd55 4

# Rebase 0e447c5..d75bd55 onto 0e447c5 (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

删除掉3号版本

$ git rebase -i HEAD^^^
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: could not apply d75bd55... 4
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply d75bd55... 4

此时打开VSCode,可以看到冲突

处理好冲突后,使用git add将文件添加到暂存区后,执行git rebase,根据提示提交新的commit message

$ git rebase --continue
[detached HEAD 611a631] new
 1 file changed, 5 insertions(+)
Successfully rebased and updated refs/heads/main.

$ git log --oneline
611a631 (HEAD -> main) new
3b1cf19 2
0e447c5 1

可以使用下面的命令撤销rebase操作。

$ git rebase --abort

6. Fork + PR

在Github中选择一个项目,点击Fork,将该项目fork到自己的仓库中。

对项目进行修改后,点击Pull Request

再点击New Pull Request按钮提交PR,等待处理。

参考文献

[1] https://mp.weixin.qq.com/s/Km5KuXPETvG0wCGHrvj9Vg

posted @ 2020-10-04 16:26  fzhovo  阅读(196)  评论(0)    收藏  举报