前言

最近,有敌人私信让我就git 应用做篇文章分享,分享一下我在日常工作中是如何应用git的。我当场就免费两包辣条,最初讨价还价,敌人用1.5包辣条骗到了这篇文章,等他欣慰的走了我打算间接分享进去,气死这个吝啬鬼,当然最终还是心愿本文对你有所帮忙。

根底概念

首先咱们简略的概述一下gitgit有三个分区,别离是:

  • 工作区(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 statusOn branch developChanges 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.mdno 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.mddiff --git a/README.md b/README.mdindex 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 developSwitched to a new branch 'develop'jere@JereMBP GitTest (develop) $ git branch* develop  main

放弃工作区所作的批改,相似git restore <file>...,比方:我当初想放弃README.md中的批改

jere@JereMBP GitTest (develop) $ git statusOn branch developChanges 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.txtno changes added to commit (use "git add" and/or "git commit -a")jere@JereMBP GitTest (develop) $ git checkout README.mdUpdated 1 path from the indexjere@JereMBP GitTest (develop) $ git statusOn branch developChanges 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.txtno 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-1jere@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 statusOn branch developChanges 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.mdno changes added to commit (use "git add" and/or "git commit -a")jere@JereMBP GitTest (develop) $ git add README.mdjere@JereMBP GitTest (develop) $ git statusOn branch developChanges to be committed:  (use "git restore --staged <file>..." to unstage)    modified:   README.mdjere@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 statusOn branch developnothing to commit, working tree cleanjere@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 threadsCompressing 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 -> developjere@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 0Unpacking objects: 100% (3/3), done.From https://github.com/JereChen11/GitTest   30f049e..d6ff31d  main       -> origin/mainjere@JereMBP GitTest (develop) $ git fetch jere@JereMBP GitTest (develop) $ 

git merge

合并分支,如:在上一步中,咱们通过git fetch发现近程 mian 分支有了新提交,所以以后本地main分支是落后的,所以这时候咱们就应该将近程 mian 分支合并到咱们的本地main分支,来实现两端同步。

jere@JereMBP GitTest (develop) $ git checkout mainSwitched 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..d6ff31dFast-forward README.md | 2 ++ 1 file changed, 2 insertions(+)jere@JereMBP GitTest (main) $ 

git pull

拉取近程仓库,如果近程仓库有更新,则会将更新下载下来并合并到以后分支上,相当于git fetchgit merge的结合体。 如:跟上一步同样,这次咱们应用git pull来拉取近程 mian 分支上的新提交。

jere@JereMBP GitTest (main) $ git pullremote: 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 0Unpacking objects: 100% (3/3), done.From https://github.com/JereChen11/GitTest   55e808c..4a1a531  main       -> origin/mainUpdating 55e808c..4a1a531Fast-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.mdCONFLICT (content): Merge conflict in README.mdAutomatic merge failed; fix conflicts and then commit the result.jere@JereMBP GitTest (main) $ git statusOn branch mainYour 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.txtUnmerged paths:  (use "git add <file>..." to mark resolution)    both modified:   README.mdjere@JereMBP GitTest (main) $ 

正是README.md文件产生了抵触,咱们须要关上该文件来查看具体抵触内容。

# GitTestFor git command practice<<<<<<< HEADchagne README file on the main branch //内容1=======do something on develop branch //内容2>>>>>>> develop

抵触的内容会被<<<<<<<>>>>>>>所突围,两头用=======隔离开,也就如我所正文的分成了内容1内容2两块。

  • 内容1:是以后所在分支节点的内容,也就是mian
  • 内容2:要合并进来分支的内容,也就是develop

抉择你要的内容,将<<<<<<<>>>>>>>=======这些隔离符删除掉,并保留,而后执行git addgit commit实现合并。

jere@JereMBP GitTest (main) $ vim README.md jere@JereMBP GitTest (main) $ git statusOn branch mainYour 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.txtUnmerged paths:  (use "git add <file>..." to mark resolution)    both modified:   README.mdjere@JereMBP GitTest (main) $ git commit -am "解决README抵触"[main 8e08c23] 解决README抵触jere@JereMBP GitTest (main) $ 

组员间同步开发进度

在理论我的项目中,咱们都是多人配合协同开发,会将一些需要进行拆分,而后大家同时开发,开发实现后,各自将本人的代码合并到develop分支上。 在这过程中,如果某个组员曾经开发完了并且将代码合并到了develop分支,而你还没开发完,然而这时你想同步这个组员的代码,这时应该怎么做呢?

这里咱们就能够应用git rebase来做到。

git rebase操作,称之为变基操作,也就是挪动你的分支的根节点。

举个例子:

  1. feature-1feature-2 都是基于 develop 同一节点开进去的分支。
  2. 随着开发的进行,feature-1先开发实现,并合并到develop分支。
  3. 此时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.txtjere@JereMBP GitTest (feature-2) $ 

这三个状态的节点分支状况如下图所示:

初始状态feature-1合并到developfeature-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.txt8561ef3 再次批改feature-3.txt,当初咱们要将这两个提交进行合并

  1. 执行 git rebase -i HEAD~2
  2. 这是会主动进入vim,显示如下内容:
pick 598cc68 批改feature-3.txtpick 8561ef3 再次批改feature-3.txt...省略...

这里咱们要合并这两个提交,所以将第二个pick更改为s,如下:

pick 598cc68 批改feature-3.txts 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) $
  1. 此时,你本地分支曾经实现了合并,你尝试将其推送到仓库中时,会发现被回绝。通过提醒可知,回绝理由是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 behindhint: 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 -fEnumerating objects: 5, done.Counting objects: 100% (5/5), done.Delta compression using up to 12 threadsCompressing 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 --continues, 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 --softgit 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 statusOn branch feature-5Changes 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.txtno changes added to commit (use "git add" and/or "git commit -a")jere@JereMBP GitTest (feature-5) $ git stashSaved working directory and index state WIP on feature-5: 9bd4e1f 增加 feature-5.txtjere@JereMBP GitTest (feature-5) $ git statusOn branch feature-5nothing to commit, working tree cleanjere@JereMBP GitTest (feature-5) $ git stash popOn branch feature-5Changes 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.txtno 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.0jere@JereMBP GitTest (feature-5) $ git tagv1.0v1.0.1

另外,对于tag的一些其它操作有:

# 查看所有标签$ git tag# 删除指定tag$ git tag -d 标签名

批改最近提交的文本信息

很多时候,咱们提交的时候,可能会输错提交的文本信息,而后想批改一下。

这时,你能够通过git commit --amend来批改最近的提交的文本音讯

当然,你也能够通过刚刚介绍的撤销本地提交做到,这边就不再次展现了。

git config 一些配置

通过git config --list来查看你的git配置信息

配置别名

每次输出咱们都须要输出残缺的checkoutcommit,很麻烦,咱们能够通过设置别名来实现。

$ 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=checkoutalias.br=branchalias.ci=commitalias.st=status

之后你就能够通过git co <branch>git st来切换分支、查看状态了..

配置代理

因为一些非凡网络起因,咱们很多时候上github很不稳固,有时候咱们推送一些代码会403失败。这时咱们就能够通过设置代理来解决。

比方:咱们设置一个本地代理。

git config --global http.proxy http://127.0.0.1:1080git config --global https.proxy https://127.0.0.1:1080git 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:1080https.proxy=https://127.0.0.1:1080

设置代理胜利后,某天,你想勾销该代理,这时咱们能够通过unset来勾销代理设置。

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

结尾:

OK,文章到此也就完结啦。

倡议对git命令还不太纯熟的同学多上手试试,遇到问题不要慌,留神看它给的提醒,置信很快就能把握啦。

其实分享文章的最大目标正是期待着有人指出我的谬误,如果你发现哪里有谬误,请毫无保留的指出即可,虚心求教。 另外,如果你感觉文章不错,对你有所帮忙,请给我点个赞,就当激励,谢谢 ~Peace~!

转自:Jere_Chen