共计 14000 个字符,预计需要花费 35 分钟才能阅读完成。
前言
最近,有敌人私信让我就 git 应用
做篇文章分享,分享一下我在日常工作中是如何应用 git
的。我当场就免费两包辣条,最初讨价还价,敌人用 1.5 包辣条骗到了这篇文章,等他欣慰的走了我打算间接分享进去,气死这个吝啬鬼,当然最终还是心愿本文对你有所帮忙。
根底概念
首先咱们简略的概述一下 git
,git
有三个分区,别离是:
- 工作区(Working Directory):开发者间接编辑的中央,只有文件产生了更改,在这就会显示进去,蕴含追踪与未追踪文件。通过
git add
将工作区文件增加到暂存区。 - 暂存区(Stage | Index):数据临时寄存的区域,通过
git commit
将暂存区文件增加到本地版本库。 - 本地版本库(Local Commit History):寄存所有曾经提交的数据,通过
git push
推送到近程仓库。
根底命令
git status
查看工作区状态,如果跟踪的文件有做任何批改,都能够通过该命令来发现。如:这里通过 git status
就发现在 develop
分支上,README.md
文件产生了更改。
jere@JereMBP GitTest (develop) $ git status
On branch develop
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
git diff
查看具体批改内容,比方在上一步中,咱们通过 git status
发现 README.md
文件发现了更改,这时咱们能够通过 git diff <file>
来查看具体的批改内容:
jere@JereMBP GitTest (develop) $ git diff README.md
diff --git a/README.md b/README.md
index 7eb4917..3d6d2a4 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,5 @@
# GitTest
For git command practice
+
+do something on develop branch
+
jere@JereMBP GitTest (develop) $
另外,你也能够间接应用git diff
,这样就会显示所有文件的所有批改内容。
git checkout
切换分支,比方我在 feature-1
分支上切换到 develop
分支上:
jere@JereMBP GitTest (feature-1) $ git checkout develop
Switched to branch 'develop'
jere@JereMBP GitTest (develop) $
在以后分支节点上 新建
一个分支 并且切换过来
,比方我在 main
分支上创立一个develop
新分支并且切换过来:
jere@JereMBP GitTest (main) $ git checkout -b develop
Switched to a new branch 'develop'
jere@JereMBP GitTest (develop) $ git branch
* develop
main
放弃工作区所作的批改,相似 git restore <file>...
,比方:我当初想放弃README.md
中的批改
jere@JereMBP GitTest (develop) $ git status
On branch develop
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
modified: dev-file.txt
no changes added to commit (use "git add" and/or "git commit -a")
jere@JereMBP GitTest (develop) $ git checkout README.md
Updated 1 path from the index
jere@JereMBP GitTest (develop) $ git status
On branch develop
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: dev-file.txt
no changes added to commit (use "git add" and/or "git commit -a")
jere@JereMBP GitTest (develop) $
另外,如果你想放弃所有工作区中的批改,能够应用 git checkout .
来放弃所有批改。
git branch
查看 本地
分支状况:
jere@JereMBP GitTest (main) $ git branch
* main
查看 近程仓库
分支状况:
jere@JereMBP GitTest (develop) $ git branch --remote
origin/HEAD -> origin/main
origin/main
在以后节点上 创立一个新分支
,比方我在 develop
上创立一个feature-1
新分支:
jere@JereMBP GitTest (develop) $ git branch feature-1
jere@JereMBP GitTest (develop) $ git branch
* develop
feature-1
main
另外,对于创立分支还有一些罕用的操作能够理解一下,比方:
# 基于某个分支上开出新分支
$ git branch <new-branch> <base-branch>
# 基于某个提交开出新分支
$ git branch <new-branch> commit_hash
# 基于某个 tag 开出有新分支
$ git branch <new-branch> v1.1
删除分支
- 删除本地分支:
git branch -d <branch-name>
。 - 删除近程分支:
git push -d origin <branch-name>
。
git add
将工作区所作的批改增加到暂存区,如将 README.md
文件增加到暂存区:
jere@JereMBP GitTest (develop) $ git status
On branch develop
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
jere@JereMBP GitTest (develop) $ git add README.md
jere@JereMBP GitTest (develop) $ git status
On branch develop
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
jere@JereMBP GitTest (develop) $
另外,你也能够通过 git add .
命令,这会将工作区所有的批改内容都增加到暂存区。
git commit
将暂存区中的内容保留到本地工作区,如上一步咱们曾经将 README.md
文件增加到了暂存区,接下来就将它保留到本地工作区:
jere@JereMBP GitTest (develop) $ git commit -m "更改 README 文件"
[develop b18e4f1] 更改 README 文件
1 file changed, 3 insertions(+)
jere@JereMBP GitTest (develop) $ git status
On branch develop
nothing to commit, working tree clean
jere@JereMBP GitTest (develop) $
另外,你也能够通过 git commit -am
来进行疾速操作,其实它就是 git add . & git commit -m
的结合体。
git push
将本地文件推送到近程仓库中,如:将上一步曾经保留到本地的 README.md
文件推送到近程仓库:
jere@JereMBP GitTest (develop) $ git push origin develop
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 371 bytes | 371.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/JereChen11/GitTest.git
1f7fb80..b18e4f1 develop -> develop
jere@JereMBP GitTest (develop) $
git fetch
查看近程仓库有没有更新,有更新就下载下来,如果没有更新就没有任何反馈,如:这里通过 git fetch
发现近程仓库中 main
分支有了新提交,所以将其下载了下来。
jere@JereMBP GitTest (develop) $ git fetch
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/JereChen11/GitTest
30f049e..d6ff31d main -> origin/main
jere@JereMBP GitTest (develop) $ git fetch
jere@JereMBP GitTest (develop) $
git merge
合并分支,如:在上一步中,咱们通过 git fetch
发现 近程 mian 分支
有了新提交,所以以后 本地 main 分支
是落后的,所以这时候咱们就应该将 近程 mian 分支
合并到咱们的 本地 main 分支
,来实现两端同步。
jere@JereMBP GitTest (develop) $ git checkout main
Switched to branch 'main'
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
jere@JereMBP GitTest (main) $ git merge origin/main
Updating 30f049e..d6ff31d
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)
jere@JereMBP GitTest (main) $
git pull
拉取近程仓库,如果近程仓库有更新,则会将更新下载下来并合并到以后分支上,相当于 git fetch
与git merge
的结合体。如:跟上一步同样,这次咱们应用 git pull
来拉取 近程 mian 分支
上的新提交。
jere@JereMBP GitTest (main) $ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/JereChen11/GitTest
55e808c..4a1a531 main -> origin/main
Updating 55e808c..4a1a531
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)
业务场景
除了下面几个根底命令,当初我依据咱们平时的业务场景,配合案例再介绍几个指令。
解决抵触
对于抵触,一旦波及分支合并,且这两个分支有对同一个中央做更改,就会呈现抵触。
比方:在上一步中咱们将 近程 mian 分支
拉取了下来,发现他是对 README.md
文件做了更改,而咱们一开始的时候曾经在 develop
分支上对 README.md
文件雷同地位上做了更改,这时候,如果咱们尝试将 develop
合并到 main
分支上时,就会呈现抵触。
jere@JereMBP GitTest (main) $ git merge develop
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
jere@JereMBP GitTest (main) $ git status
On branch main
Your branch is up to date with 'origin/main'.
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Changes to be committed:
new file: dev-file.txt
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README.md
jere@JereMBP GitTest (main) $
正是 README.md
文件产生了抵触,咱们须要关上该文件来查看具体抵触内容。
# GitTest
For git command practice
<<<<<<< HEAD
chagne README file on the main branch // 内容 1
=======
do something on develop branch // 内容 2
>>>>>>> develop
抵触的内容会被 <<<<<<<
与>>>>>>>
所突围,两头用 =======
隔离开,也就如我所正文的分成了 内容 1
与 内容 2
两块。
内容 1
:是以后所在分支节点的内容,也就是mian
。内容 2
:要合并进来分支的内容,也就是develop
。
抉择你要的内容,将 <<<<<<<
、>>>>>>>
、=======
这些隔离符删除掉,并保留,而后执行 git add
、git commit
实现合并。
jere@JereMBP GitTest (main) $ vim README.md
jere@JereMBP GitTest (main) $ git status
On branch main
Your branch is up to date with 'origin/main'.
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Changes to be committed:
new file: dev-file.txt
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README.md
jere@JereMBP GitTest (main) $ git commit -am "解决 README 抵触"
[main 8e08c23] 解决 README 抵触
jere@JereMBP GitTest (main) $
组员间同步开发进度
在理论我的项目中,咱们都是多人配合协同开发,会将一些需要进行拆分,而后大家同时开发,开发实现后,各自将本人的代码合并到 develop
分支上。在这过程中,如果某个组员曾经开发完了并且将代码合并到了 develop
分支,而你还没开发完,然而这时你想同步这个组员的代码,这时应该怎么做呢?
这里咱们就能够应用
git rebase
来做到。
git rebase
操作,称之为变基操作,也就是挪动你的分支的根节点。
举个例子:
feature-1
与feature-2
都是基于develop
同一节点开进去的分支。- 随着开发的进行,
feature-1
先开发实现,并合并到develop
分支。 - 此时
feature-2
利用git rebase origin develop
来同步feature-1
的代码。
jere@JereMBP GitTest (feature-2) $ git rebase origin/develop
First, rewinding head to replay your work on top of it...
Applying: 增加 feature-22.txt 文件
Applying: 批改 feature-22.txt
jere@JereMBP GitTest (feature-2) $
这三个状态的节点分支状况如下图所示:
初始状态 | feature- 1 合并到 develop | feature- 2 同步 develop 代码 |
---|---|---|
整顿合并提交
有时候,咱们想对本人的提交进行合并操作。
咱们能够通过 git rebase -i HEAD~x
来合并(这里 i
的意思为interactive
交互,HEAD~x
代表要合并 HEAD
到前 x
个历史提交,如:HEAD~2
为历史的前两个提交,HEAD~4
就是历史的前四个提交)。
举个例子:咱们在 feature- 3 分支
上对 feature-3.txt
进行了两次提交批改,别离是 598cc68 批改 feature-3.txt
与8561ef3 再次批改 feature-3.txt
,当初咱们要将这 两个提交进行合并。
- 执行
git rebase -i HEAD~2
。 - 这是会主动进入
vim
,显示如下内容:
pick 598cc68 批改 feature-3.txt
pick 8561ef3 再次批改 feature-3.txt
... 省略...
这里咱们要合并这两个提交,所以将第二个 pick
更改为s
,如下:
pick 598cc68 批改 feature-3.txt
s 8561ef3 再次批改 feature-3.txt
... 省略...
保留退出,将主动关上另外一个 vim
文件,用来批改提交文本信息,如下:
# This is a combination of 2 commits.
# This is the 1st commit message:
批改 feature-3.txt
# This is the commit message #2:
再次批改 feature-3.txt
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
这里咱们将其批改为 最终版本,批改 feature-3.txt
,保留退出。
jere@JereMBP GitTest (feature-3) $ git rebase -i HEAD~2
[detached HEAD 18296c5] 最终版本,批改 feature-3.txt
Date: Wed Dec 1 10:21:05 2021 +0800
1 file changed, 2 insertions(+)
Successfully rebased and updated refs/heads/feature-3.
jere@JereMBP GitTest (feature-3) $
- 此时,你本地分支曾经实现了合并,你尝试将其推送到仓库中时,会发现被回绝。通过提醒可知,回绝理由是
our current branch is behind 你以后分支落后近程分支
,这时,咱们须要git push origin feature-3 -f
, 强制推送,实现合并。
jere@JereMBP GitTest (feature-3) $ git push origin feature-3
To https://github.com/JereChen11/GitTest.git
! [rejected] feature-3 -> feature-3 (non-fast-forward)
error: failed to push some refs to 'https://github.com/JereChen11/GitTest.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
jere@JereMBP GitTest (feature-3) $ git push origin feature-3 -f
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 356 bytes | 356.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/JereChen11/GitTest.git
+ 8561ef3...18296c5 feature-3 -> feature-3 (forced update)
这三个状态的节点分支状况如下图所示:
执行 git rebase -i HEAD~2 |
采纳 squash 合并提交,并批改文本信息 |
强制推送到仓库 |
---|---|---|
还记得咱们将 pick
改为 s
这一步吗?这里的 s
指的是squash
,意思是将该提交挤压合并到上一个提交。他还有一些其它选项操作能够理解一下:
p, pick <commit> = 应用提交
r, reword <commit> = 应用提交,然而会编辑提交文本信息
e, edit <commit> = 应用提交,在批改实现后,能够通过 git commit --amend 再次进行批改;批改称心后再应用 git rebase --continue
s, squash <commit> = 应用提交,挤压合并到上一个提交
f, fixup <commit> = 相似 "squash",会挤压合并到上一个提交,然而会疏忽批改提交文本信息这一步。
整顿提交的必要性 如果你的分支上存在这样的状况: 提交 1:finish login feature
,紧接着前面就是 提交 2:code review for login feature
。这样的操作其实很失常,也很正当,你在做好性能后,去做了code review
,但其实咱们齐全能够将这两个提交合并成一个提交,不便本人以及共事查看你的代码。
但 留神:
你要在你本人的分支进行操作。
撤销提交
这边撤销提交分为 撤销本地提交 与撤销近程提交。
撤销本地提交
当你提交了代码到本地,但此时,你想撤回这个提交,从新编辑批改一下。这时你能够通过 git reset
来实现。
这个撤销分为 是否保留批改。
- 保留批改:
git reset --soft
,你之前所作的更改都在,这也称为最平安的撤销。 - 舍弃批改:
git reset --hard
,你之前所作的更改都会隐没,所以要审慎应用。
举个例子:以后你处于 feature-4
分支上,你提了一个本地提交 第二次批改
,这时你想撤销回来持续批改。
jere@JereMBP GitTest (feature-4) $ git reset --soft HEAD~
如果,我间接不要这个 第二次批改
本地提交,则:
jere@JereMBP GitTest (feature-4) $ git reset --hard HEAD~
HEAD is now at 16960c7 第一次批改
这三个状态的节点分支状况如下图所示:
初始状态 | git revert --soft |
git revert --hard |
---|---|---|
撤销近程提交(回滚操作)
当你将你的本地提交推送到了近程仓库中,这时,你发现你齐全做错了,你想进行回滚操作。
这时你就须要用到 git revert
操作。
举个例子:我在 feature-4
分支上提了两个提交且都推送到了仓库,别离是 第一次批改
与第二次批改
,当初我想进行回滚操作,撤销 第二次批改
这个提交。
jere@JereMBP GitTest (feature-4) $ git revert HEAD
[feature-4 c73e361] Revert "第二次批改"
1 file changed, 1 deletion(-)
执行命令后,会主动关上一个 vim
文件来让你批改提交文本信息,默认在结尾加上revert
润饰,保留退出,操作完结。
撤销前后这两个状态的节点分支状况如下图所示:
撤销前 | 撤销后 |
---|---|
如图所示,回滚操作后,会多一个 revert xxx
提交,如果你不想要这个提交,不想让人晓得你进行了回滚,你能够应用下面介绍的 git rebase -i HEAD~x
进行整顿合并提交。
另外,你也能够通过 git revert <commit_hash>
来对指定提交进行回滚,如果遇到抵触就先解决抵触,而后执行 git revert --continue
持续。
留神
:执行回滚操作须要留神环境,如果他人拉了你的代码,这时你再执行回滚操作,那就不好了。
线上出 Bug 了,紧急修复
讲个故事吧。
通过一段时间的开发,你们的产品终于上线了,版本为 V1.0
,产品上线后你马上投入到了V1.1
版本的需要开发。某天,经营与产品同时过去找你,说刚刚发现线上存在一个很重大的 bug
,须要紧急修复一下。你马上投入修复工作,通过缓和的排查与测试,最终你修复了这个问题,筹备发版。而此时,你才留神到,你是在develop
分支上进行的修复工作,而 develope
分支曾经蕴含了 v1.1
的局部性能,这时,怎么把这个紧急修复提交给到 V1.0
呢?
能够通过 git cherry-pick
做到,翻译为筛选的意思,将某个提交筛选过去。
如:咱们当初要将 develop
分支上的 d818f10 紧急修复线上 bug
这个提交合并到咱们 main V1.0
上。先切换到 main
分支上,而后将 d818f10
这个提交筛选过去合并。
jere@JereMBP GitTest (develop) $ git co main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
jere@JereMBP GitTest (main) $ git cherry-pick d818f10
[main 55e808c] 紧急修复线上 bug
Date: Wed Dec 1 15:49:48 2021 +0800
1 file changed, 2 insertions(+)
这三个状态的节点分支状况如下图所示:
初始状态 | 在 develop 上修复 |
将这个修复提交筛选到main |
---|---|---|
临时保留手头工作
某天你正在认真的开发需要中,测试过去找你让你帮忙看一个线上问题。此时,你代码也刚写了一半,不想提交,这时怎么办?
此时咱们能够通过 git stash
来暂存咱们代码,而后切换到线上环境分支排查问题,解决后,切换回之前分支执行 git stash pop
持续开发。
如:我当初正在 feature-5
分支上开发新需要,此时我须要暂存所有更改,切换到 main
分支排查问题。排查完结,回到feature-5
,将暂存取出,持续开发。
jere@JereMBP GitTest (feature-5) $ git status
On branch feature-5
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: feature-5.txt
no changes added to commit (use "git add" and/or "git commit -a")
jere@JereMBP GitTest (feature-5) $ git stash
Saved working directory and index state WIP on feature-5: 9bd4e1f 增加 feature-5.txt
jere@JereMBP GitTest (feature-5) $ git status
On branch feature-5
nothing to commit, working tree clean
jere@JereMBP GitTest (feature-5) $ git stash pop
On branch feature-5
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: feature-5.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (1ec48d00e8d1bd5c0042d88d1209dbb9051815d4)
jere@JereMBP GitTest (feature-5) $
另外,git stash
还有一些罕用操作。
# 保留到 stash 栈中,并加上自定义 message 润饰
$ git stash save "message"
# 列出 stash 栈中所有元素
$ git stash list
# 利用 stash 栈中的第 x 个元素,pop 是利用的同时且从栈中删除,而 apply 则是只利用不删除
$ git stash apply stash@{x}
# 删除 stash 栈中的第 x 个元素
$ git stash drop stash@{x}
上线发版啦
当咱们产品开发实现,发现上线时,咱们须要打个标签来标注一下,以便下次更好的找它。
这时咱们就能够通过 git tag 标签名
来打标签。
举个例子:咱们的 1.0
版本上线了,所以打个v1.0
。
jere@JereMBP GitTest (feature-5) $ git tag v1.0
jere@JereMBP GitTest (feature-5) $ git tag
v1.0
v1.0.1
另外,对于 tag
的一些其它操作有:
# 查看所有标签
$ git tag
# 删除指定 tag
$ git tag -d 标签名
批改最近提交的文本信息
很多时候,咱们提交的时候,可能会输错提交的文本信息,而后想批改一下。
这时,你能够通过 git commit --amend
来批改 最近的提交的文本音讯。
当然,你也能够通过刚刚介绍的 撤销本地提交 做到,这边就不再次展现了。
git config 一些配置
通过 git config --list
来查看你的git 配置信息
。
配置别名
每次输出咱们都须要输出残缺的checkout
、commit
,很麻烦,咱们能够通过设置别名来实现。
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status
设置实现后,你在通过 git config --list
查看配置,就会发现:
alias.co=checkout
alias.br=branch
alias.ci=commit
alias.st=status
之后你就能够通过 git co <branch>
、git st
来切换分支、查看状态了..
配置代理
因为一些非凡网络起因,咱们很多时候上 github
很不稳固,有时候咱们推送一些代码会 403
失败。这时咱们就能够通过设置代理来解决。
比方:咱们设置一个本地代理。
git config --global http.proxy http://127.0.0.1:1080
git config --global https.proxy https://127.0.0.1:1080
git config --global http.proxy 'socks5://127.0.0.1:1080'
git config --global https.proxy 'socks5://127.0.0.1:1080'
设置实现后,你再通过 git config --list
查看配置,就会发现:
http.proxy=http://127.0.0.1:1080
https.proxy=https://127.0.0.1:1080
设置代理胜利后,某天,你想勾销该代理,这时咱们能够通过 unset
来勾销代理设置。
git config --global --unset http.proxy
git config --global --unset https.proxy
结尾:
OK,文章到此也就完结啦。
倡议对 git
命令还不太纯熟的同学多上手试试,遇到问题不要慌,留神看它给的提醒,置信很快就能把握啦。
其实分享文章的最大目标正是期待着有人指出我的谬误,如果你发现哪里有谬误,请毫无保留的指出即可,虚心求教。另外,如果你感觉文章不错,对你有所帮忙,请给我点个赞,就当激励,谢谢 ~Peace~!
转自:Jere_Chen