Git使用梳理教程

​ 最近重新梳理了这些年使用git的一些用法和问题,方便自己记忆查找。

Git 简介

定义

Git是一个开源的分布式版本控制系统,是 Linus Torvalds为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件,可以有效、高速地处理从很小到非常大的项目版本管理。

官网

https://git-scm.com/

下载安装

​ 很简单,不是本文重点。

配置

​ 初次使用,需要配置邮箱和用户名字

git config --global user.email "2312@l16.com"
git config --global user.name "xiaoyu"

Git 初体验

基本思想

在这里插入图片描述

基本命令

  • 初始化

    # cd /test
    git init
    
  • 添加一个文件

    vi test.txt
    

    ​ 添加内容,保存

  • 添加到本地暂存区

    git add test.txt
    
  • 提交文件到本地仓库

    $ git commit -m "first commit"
    [master (root-commit) 11fd92e] first commit
     1 file changed, 1 insertion(+)
     create mode 100644 test.txt
    
  • 查看工作区、暂存区的状态

    $ git status
    On branch master
    nothing to commit, working tree clean
    
  • 查看历史提交

    $ git log
    commit 11fd92e23dc8e436251d30bf8cfb0273b0668fd1 (HEAD -> master)
    Author: **** <z***4@163.com>
    Date:   Wed Nov 25 11:49:32 2020 +0800
    
        first commit
    
    

    ​ 再次修改test.txt

  • 查看状态

    $ git status
    On branch master
    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:   test.txt
    
    no changes added to commit (use "git add" and/or "git commit -a")
    

    ​ 红色粗体提示,test.txt文件有修改,但是没有提交的暂存区或者版本库,提示可用什么命令去操作

  • 再次添加到暂存区和本地仓库

    git add test.txt
    git commit -m "second commit"
    
  • 再次查看日志

    $ git log
    commit 58213db8d59163d8d0a380cce7d6da2e3ed03b51 (HEAD -> master)
    Author: **** <z***4@163.com>
    Date:   Wed Nov 25 13:12:19 2020 +0800
    
        second commit
    
    commit 11fd92e23dc8e436251d30bf8cfb0273b0668fd1
    Author: **** <z***4@163.com>
    Date:   Wed Nov 25 11:49:32 2020 +0800
    
        first commit
    
    
  • 怎么回退到第一次提交的内容呢,再次查看log

    $ git log
    commit 11fd92e23dc8e436251d30bf8cfb0273b0668fd1 (HEAD -> master)
    Author: **** <z***4@163.com>
    Date:   Wed Nov 25 11:49:32 2020 +0800
    
        first commit
    

    ​ 现在只有回退的那个版本的信息,之前的最新版本不见了,怎么回退到最新版本呢?

  • 使用reflog

    git reflog 可以查看所有分支的所有操作记录(包括已经被删除的commit 记录和 reset 的操作)

    $ git reflog
    11fd92e (HEAD -> master) HEAD@{0}: reset: moving to 11fd92e23dc8e436251d30bf8cfb0273b0668fd1
    58213db HEAD@{1}: commit: second commit
    11fd92e (HEAD -> master) HEAD@{2}: commit (initial): first commit
    
    
  • 再回退到最新版本

    $ git reset --hard 58213db
    HEAD is now at 58213db second commit
    
  • 再次查看全部记录

    $ git reflog
    58213db (HEAD -> master) HEAD@{0}: reset: moving to 58213db
    11fd92e HEAD@{1}: reset: moving to 11fd92e23dc8e436251d30bf8cfb0273b0668fd1
    58213db (HEAD -> master) HEAD@{2}: commit: second commit
    11fd92e HEAD@{3}: commit (initial): first commit
    

HEAD当前版本

​ 其实每次提交,串联起来,就是一个链表,HEAD就好比指向当前节点的指针,切换版本,也就是移动HEAD指针的感觉。

​ 这有助于理解后续的的git reset

git 命令详解

git clone

​ 克隆远程仓库代码到本地

git clone https://gitee.com/xiaoxiaoyunlu/mano-mall.git

功能:

  • 完整的克隆远程库为本地库
  • 为本地库新建origin别名
  • 初始化本地库

git status

初始
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
有文件未被跟踪

​ 新建一个文件

$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        test2.txt

nothing added to commit but untracked files present (use "git add" to track)
有文件需要被提交
$ git add test2.txt
warning: LF will be replaced by CRLF in test2.txt.
The file will have its original line endings in your working directory

dell@DESKTOP-IB48TPN MINGW64 /c/Mano/mano/study/test_git (master)
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   test2.txt
没有需要提交的
$ git commit -m "new file"
[master 94bc643] new file
 1 file changed, 1 insertion(+)
 create mode 100644 test2.txt

dell@DESKTOP-IB48TPN MINGW64 /c/Mano/mano/study/test_git (master)
$ git status
On branch master
nothing to commit, working tree clean
有文件被修改

​ 修改test2.txt 文件后,查看状态

$ git status
On branch master
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:   test2.txt

有文件被删除

​ 删除已经提交的文件,查看状态

$ rm -rf test2.txt

dell@DESKTOP-IB48TPN MINGW64 /c/Mano/mano/study/test_git (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    test2.txt

no changes added to commit (use "git add" and/or "git commit -a")
有文件需要被删除

​ 如果的确需要删除,提交呢

$ git add test2.txt

dell@DESKTOP-IB48TPN MINGW64 /c/Mano/mano/study/test_git (master)
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    test2.txt

git diff

比较工作区和暂存区的所有文件差异
git diff HEAD|HEAD^|HEAD~|哈希索引值 <file name>  #比较工作区跟本地库的某个版本的**指定文件**的差异
比较工作区和暂存区的指定文件差异
git diff <file name>
比较工作区和本地库的某个版本的指定文件的差异
git diff HEAD test.txt   # 当前版本
git diff HEAD^ test.txt  # 前一个版本
git diff HEAD~ test.txt  # 前一个版本
git diff 66a3fc5 test.txt   # 制定哈希值  版本

git add

​ 添加文件到暂存区

添加单个文件
git add test2.txt
添加目录
git add test2
添加当前所有文件夹
git add .

git checkout

​ 前提是,这个文件,已经被git管理了。

丢弃修改
未提交到暂存区

​ 比如,本地修改了文件,则查看状态

$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        test4.txt

nothing added to commit but untracked files present (use "git add" to track)

​ 这时候,应该要提交到暂存区的,但是不想修改了,就是当前修改的内容丢弃掉,也不用提交到暂存区了,怎么办呢?

$ git checkout -- test4.txt  # 注意,必须加 -- 不然就变成了切换分支了

​ 等价于

git restore test4.txt    # 修改当前修改,其实就是恢复到未修改前的状态
提交到暂存区

​ 如果已经提交到暂存区,则要使用如下命令:

# 默认是--mixed 模式,保留工作区,清空暂存区
$ git reset HEAD test4.txt
Unstaged changes after reset:
M       test4.txt

# 因为我们要丢弃修改,所以工作区的也要清空,继续使用这种命令
$ git checkout -- test4.txt
切换分支

​ 详情看下面的分支管理部分

git rm

​ 从暂存区删除

git rm --cached test.txt

git restore

从暂存区回复

​ 如果提交到暂存区(git add),但是发现问题,需要回退怎么办呢

git restore --staged test.txt  #表示从暂存区将文件的状态修改成 unstage 状态
git restore --staged *.txt #表示将所有暂存区的txt文件恢复状态
git restore --staged .    #表示将当前目录所有暂存区文件恢复状态

--staged 参数就是表示仅仅恢复暂存区的 ,也就是工作区的修改还在哦,修改并没有被丢弃

从版本库回复

​ 更严重点,比如已经提交到版本(git commit),但是发现问题,需要回退怎么办呢

$ git restore -s HEAD~1 test.txt  # 该命名表示将版本回退到当前快照的前一个版本
# 或者直接根据哈希索引恢复
$ git restore -s 91410eb9  test.txt  # 改命令指定明确的 commit id ,回退到指定的快照中

​ 也可以直接回退

$ git reset --soft HEAD^  # 该命令表示撤销 commit 至上一次 commit 的版本
直接回复删除的文件

git restore 命令,默认是带着 --worktree 参数的,意思是撤销工作区的修改

rm -rf test.txt
$ git restore test3.txt
error: pathspec 'test3.txt' did not match any file(s) known to git

​ 这是因为,还没有提交给git, 所以你本地删除了,就不能指望通过git restore回复文件了, 这就是真的删除,只能从物理层面恢复

​ 所以,起码要提交到暂存区,归git管理了才可以恢复

git add test.txt
rm -rf test.txt
git restore test.txt

git log

​ 查看git的日志信息

查看log
$ git log
commit 11fd92e23dc8e436251d30bf8cfb0273b0668fd1 (HEAD -> master)
Author: **** <z***4@163.com>
Date:   Wed Nov 25 11:49:32 2020 +0800

    first commit
查看简介信息

​ 日志消息太多了,只以简洁的一行显示,包含简洁哈希索引值

# 以漂亮的一行显示,包含全部哈希索引值
$ git log --pretty=oneline
11fd92e23dc8e436251d30bf8cfb0273b0668fd1 (HEAD -> master) first commit
查看简要hash信息

​ 哈希索引值太长了,能否看到所写的哈希索引值呢

$ git log --oneline
11fd92e (HEAD -> master) first commit

git reflog

git reflog 可以查看所有分支的所有操作记录(包括已经被删除的commit 记录和 reset 的操作)

$ git reflog
11fd92e (HEAD -> master) HEAD@{0}: reset: moving to 11fd92e23dc8e436251d30bf8cfb0273b0668fd1
58213db HEAD@{1}: commit: second commit
11fd92e (HEAD -> master) HEAD@{2}: commit (initial): first commit

git reset

​ 撤销操作,当前版本是 HEAD

reset模式
  • –hard

    reset --hard 会在重置 HEADbranch的同时,重置stage区和工作目录里的内容。当你在 reset 后面加了 –hard 参数时,你的stage区和工作目录里的内容会被完全重置为和HEAD的新位置相同的内容。换句话说,就是你的没有commit的修改会被全部擦掉

  • –soft

    reset --soft 会在重置 HEADbranch 时,保留工作目录和暂存区中的内容,并把重置 HEAD 所带来的新的差异放进暂存区。

  • –mixed

    reset 如果不加参数,那么默认使用 –mixed 参数。它的行为是:保留工作目录,并且清空暂存区。也就是说,工作目录的修改、暂存区的内容以及由 reset 所导致的新的文件差异,都会被放进工作目录。简而言之,就是「把所有差异都混合(mixed)放在工作目录中」

直接回到指定哈希值所对应的版本
# 11fd92e23dc8e436251d30bf8cfb0273b0668fd1 是第一次提交的commit hashcode
$ git reset --hard 11fd92e23dc8e436251d30bf8cfb0273b0668fd1
HEAD is now at 11fd92e first commit
后退版本
#一个^表示回退一个版本
git reset --hard HEAD^  # 回退一个版本
git reset --hard HEAD^^   # 回退两个版本

​ 等价于:

# 波浪线~后面的数字表示后退几个版本
git reset --hard HEAD~1  # 后退一个版本
git reset --hard HEAD~2  # 后退两个个版本
已经push到远程
# log 查看版本  得到你需要回退一次提交的commit id
git log -v

# 回退到之前的版本
git reset --hard <commit_id>

直接提交会报错如下:

$ git push -u origin master
To https://gitee.com/xiaoxiaoyunlu/mano-mall.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'https://gitee.com/xiaoxiaoyunlu/mano-mall.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.

​ 因为远程和本地不一样,提示错误,所以要强制回退

# 强制提交一次,之前错误的提交就从远程仓库删除
git push origin HEAD --force 

​ 或者:

git push -f origin master

git branch

$ git log
commit 95015cb98d738072c8bec15f7656f8a0371c8ef9 (HEAD -> master)
Master 分支

​ 默认是Master分支,其实所谓的HEAD指针,指向的是当前Master分支的版本。

​ 正常情况下,Master一般用于最稳定版本代码的维护,用于新版本发布。

为什么需要创建不同的分支

​ 主线Master分支,是最重要的,但是一个项目里面,很多人来开发,那么谁都可以来再Master分支里面直接修改吗,很危险的啊老铁。

​ 正常的做法就是,每个人在Master分支上拉出一个个人的开发分支branch,等各自修改后以后,再合并分支,回归代码到主线Master分支。

创建分支
# 创建分支
git branch test_dev

​ 创建分支,要切换到分支下开发,所以可以有更快捷的命令,创建分支以后直接切换到分支

$ git checkout -b test_prod
Switched to a new branch 'test_prod'
查看分支
$ git branch -v
* master   95015cb test4
  test_dev 95015cb test4
修改分支名称

​ 一旦创建不合适了,可以修改,具体如下:

# 修改本地分支名称
git branch -m old_branch new_branch 
# 删除远程的old 分支 
git push origin :old_branch 
# 推送新分支 到 远程仓库
git push --set-upstream origin new_branch 
切换分支
# 切换到分支
$ git checkout test_dev
Switched to branch 'test_dev'
删除分支
当前所处分支不能直接删除
$ git branch -d test_prod
error: Cannot delete branch 'test_prod' checked out at 'C:/Mano/mano/study/test_git'

​ 因为当前在test_prod,所以是不能直接删除分支的,要先切换到其他分支,再删除,就好比当前分支使用中,不能删除。

$ git checkout master
$ git branch -v
* master    95015cb test4
  test_dev  95015cb test4
  test_prod 95015cb test4

dell@DESKTOP-IB48TPN MINGW64 /c/Mano/mano/study/test_git (master)
$ git branch -d test_prod
Deleted branch test_prod (was 95015cb).

​ 注意,可能会删除失败,如果分值代码不一致的情况。

当前分支有代码没有提交到版本库
$ git checkout -b test_12
Switched to a new branch 'test_12'

vi test11.txt

​ 这个时候切换分支,可以删除,但是,test11.txt还是没有被git管理

# 新建分支测试
$ git checkout -b test_13
Switched to a new branch 'test_13' 
# 当前分支下,add 
git add test11.txt

​ 注意,这时候是在分支test_13下,被提交到暂存区,还没有提交到版本库,还是可以直接删除的

​ 猜测:所有分支是共享工作区和暂存区的,待验证。

当前分支有代码已经提交到版本库
# 提交到代码库
$ git commit -m "test5"
[test_13 d558e91] test5
 1 file changed, 1 insertion(+)
 create mode 100644 test5.txt

# 切换到master分支 , 删除  分支 test_13
$ git branch -d test_13
error: The branch 'test_13' is not fully merged.
If you are sure you want to delete it, run 'git branch -D test_13'.

​ 提示,当前分支存在没有合并(git merge)的代码,也就是出现代码不一致,是否强制删除?

# 使用 -D  强制删除
git branch -D test_13
删除远程分支

​ 注意,这个必须谨慎操作

git push origin --delete test_14   # 删除远程分支
分支合并
分支开发merge到master

​ 比如,项目组新来了个同事,开发步骤如下:

  • 先给新同事开发项目开发分支

    git checkout -b test_14
    
  • 分支下开发新功能

    # 创建了文件`test14.txt`
    vi test14.txt
    
  • 功能测试没问题,要发版本了

    要发布,首先,就得把代码从分支test_14,合并到master分支,确认没有问题,才可以审核发布。

    # git merger [被合并分支] [要合并的分支]
    $ git merge test_14 master
    Updating 95015cb..d04ca5c
    Fast-forward
     test14.txt | 1 +
     1 file changed, 1 insertion(+)
     create mode 100644 test14.txt
    
多人分支merge

​ 一个项目组,大系统,很多个同事一起开发,怎么办呢

  • 主分支

    # 比如有公用模块 test.txt
    vi test.txt
    init
    
  • 同事小张负责模块1

git checkkout -b dev_zhang

vi test.txt
# 修改代码
init
model 1

git add test.txt
git commit -m "dev_zhang commit model 1"

​ 修改代码只在dev_zhang下面

  • 同事小李负责模块2

    git checkout -b dev_li
    
    vi test.txt 
    # 修改代码
    init
    model 2
    
    git add test.txt
    git commit -m "dev_li commit model 2"
    

    ​ 修改代码只在dev_li下面

  • 切换到主分支master

    git checkout master
    

    ​ 此时,主分支master并没有同事张和同事小李的代码,所以,需要合并分支到到主分支master

  • 合并小张代码到主分支

    $ git merge dev_zhang
    Updating d04ca5c..4749995
    Fast-forward
     test.txt | 1 +
     1 file changed, 1 insertion(+)
    

    ​ 没有问题,因为没有冲突代码,查看日志如下:

    $ git log --pretty=oneline
    4749995910cfcc12fe2619489cc0fb3af60b316f (HEAD -> master, dev_zhang) zhang modify test
    

    ​ 可以看到,此时master和分支dev_zhang的代码保持一致了。

  • 合并小李代码到主分支

    $ git merge dev_li
    Auto-merging test.txt
    CONFLICT (content): Merge conflict in test.txt
    Automatic merge failed; fix conflicts and then commit the result.
    

    ​ 有冲突代码,为什么呢,因为现在小张的代码已经合并到主分支了,现在小李要合并到主分支,代码内容有冲突了,需要先处理代码冲突问题,才能顺利合并哦

  • 查看有冲突的文件

    # 注意,当前还在master 主分支
    dell@DESKTOP-IB48TPN MINGW64 /c/Mano/mano/study/test_git (master|MERGING)
    $ vi test.txt
    
    init
    <<<<<<< HEAD
    model 1
    =======
    model 2
    >>>>>>> dev_li
    
    • ======是分界线
    • <<<<<< 是已经存在的版本的分界线
    • >>>>>>是当前分支里面的分界线

    既然找到了冲突代码,就得解决,是保存都要呢,还是只要自己的,确定好

  • 修改后提交

    # 比如修改如下:
    init
    model 1
    model 2
    
    git add test.txt
    git commit -m "li handle confit to commit"
    
  • 查看日志

    dell@DESKTOP-IB48TPN MINGW64 /c/Mano/mano/study/test_git (master)
    $ git log --pretty=oneline
    652c5bbe54a894bce34da322e193e2d748a32318 (HEAD -> master) li handle confit to commit
    66a3fc5f80cb8e461c51f1d2607ba26f0d12f18e (dev_li) dev_li commit model 2
    4749995910cfcc12fe2619489cc0fb3af60b316f (dev_zhang) dev_zhang commit model 1
    d04ca5cbbab73950eeb75a7fe7e1fd6f357ec8b8 (test_14) test14
    95015cb98d738072c8bec15f7656f8a0371c8ef9 test4
    

git config

​ 主要是配置一下git需要的环境变量字段什么的。

分类和优先级

​ 注意,优先级从上到下,一次递减,存在同名的配置,优先级高的会覆盖优先级低的。

  • 仓库级别

    git config --local
    

    仓库配置,一般在当前工作区的.git目录的config文件里面

    [core]
    	repositoryformatversion = 0
    	filemode = false
    	bare = false
    	logallrefupdates = true
    	symlinks = false
    	ignorecase = true
    
  • 全局级别

    git config --global
    
  • 系统级别

    git config --system
    

    ​ 系统级别,比如当前window系统git的安装目录下的etc\gitconfig

查看配置 -l
全部配置
$ git config -l

​ 注意,这份列表,是融合了三个级别的配置哦

仓库级别
$ git config --local -l
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
全局级别
$ git config --global -l
user.name=x*******u
user.email=z****4@163.com
系统级别
$ git config --system -l
diff.astextplain.textconv=astextplain
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
http.sslbackend=openssl
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
core.autocrlf=true
core.fscache=true
core.symlinks=false
pull.rebase=false
credential.helper=manager
修改配置 -e
git config --local -e  #编辑仓库配置
git config --global -e  #编辑全局配置
git config --system -e  #编辑系统配置

​ 当然,修改单条配置的话, 直接修改

git config --global user.name "xiaoyu"

​ 添加字段

git config --global add user.name "1231231"

​ 删除字段

git config --global unset user.name
设置别名

​ 之前的很多命令,是不是感觉有些长啊,不是很方便

git log --pretty=oneline
git commit -m "2"

​ 能不能简化一下呢,比如:

git log one  # 就标识  git log --pretty=oneline
git cm -m "2" # 标识 git commit -m "2"

​ 完全可以,git支持别名配置哦

git config --global alias.bv branch -v
git config --global alias.logone log --pretty=oneline

​ 查看全局配置

$ git config --global -l
user.name=x*****u
user.email=z****@163.com
alias.logone=log
alias.bv=branch

​ 貌似,和我们修改的不一样啊,那就直接编辑文件修改吧

# 编辑全局配置 修改
git config --global -e
# 查看
$ git config --global -l
user.name=xiaoxiaoyunlu
user.email=zjxzz0714@163.com
alias.logone=log --pretty=oneline
alias.bv=branch -v

​ 测试:

$ git bv
  dev_li    66a3fc5 li modify test
  dev_zhang 4749995 zhang modify test
* master    652c5bb li modify new
  test_14   d04ca5c test14

git tag

为什么需要打标签
$ git logone
652c5bbe54a894bce34da322e193e2d748a32318 (HEAD -> master) li modify new
66a3fc5f80cb8e461c51f1d2607ba26f0d12f18e (dev_li) li modify test
4749995910cfcc12fe2619489cc0fb3af60b316f (dev_zhang) zhang modify test

​ 这么长的commit id 和 备注,毕竟不容易记住啊,也很难记住哪个版本修改了什么内容,怎么呢?

​ 就好比,ip地址123.67.342.90,很很难记住,我们就用域名www.baidu.com去映射对应,很方便,我们也可以试着给每个稳定的提交版本设置一个容易记住的标签。

给commitid打标签
# 给某个commitid 打版本标签
$ git tag v0.0.1 11fd92e -m "zhang model 2 done"

# 默认不写commitid 就是给当前最新版本打标签
$ git tag v1.0.0
删除标签
git tag -d v0.0.1
查看tag 列表
$ git tag
v0.0.9
v1.0.0

​ 查看日志

$ git logone
652c5bbe54a894bce34da322e193e2d748a32318 (HEAD -> master, tag: v1.0.0) li modify new
66a3fc5f80cb8e461c51f1d2607ba26f0d12f18e (dev_li) li modify test
4749995910cfcc12fe2619489cc0fb3af60b316f (tag: v0.0.9, dev_zhang) zhang modify test

忽略文件

​ 有些文件,其实没有必要提交到git,比如,.class 或者.jar等,怎么告诉git一下,提交的时候忽略,不去提交呢,可以建立一个.gitignore文件

vi .gitignore

*.class

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

​ 当然,这个文件要提交到git去知道

git add .gitignore
git commit -m "ignore file format"

​ 测试,

# 新建一个jar
vi m1.jar

$ git status
On branch master
nothing to commit, working tree clean

​ 被忽略了,都不会去跟踪了。

远程仓库

理解远程仓库

​ 简单来说,远程仓库实际上就是保持在服务器上的Git仓库,用来备份Git文件以及实现代码共享。

​ 因为开发的代码,不可能一直保留在个人开发环境里面的本地仓库,都需要有一个部署在远程服务器的远程仓库,可以是github,也可以是gitee,或者还可以在自己的阿里云服务器上搭建gitlab

git remote

​ 主要是用来关联和推送下载远程仓库

  • 查看远程仓库

    $ git remote
    
  • 没有,那就添加一个

    • origin 是起源,源头的意思,可以看做是远程仓库的别名
    • https://gitee.com/xiaoxiaoyunlu/mano-mall.git,这是个人基于微服务开发的微型电商项目的远程码云地址。
    git remote add origin https://gitee.com/xiaoxiaoyunlu/mano-mall.git
    
  • 再次查看

    $ git remote
    origin
    
    # -v 详细信息
    $ git remote -v
    origin  https://gitee.com/xiaoxiaoyunlu/mano-mall.git (fetch)
    origin  https://gitee.com/xiaoxiaoyunlu/mano-mall.git (push)
    

​ 只有把本地仓库和远程仓库关联起来,才可以把代码推送到远程仓库。

  • 删除远程仓库别名

    git remote rm <别名>
    

git push

推送到master分支
# 推送本地代码到远程仓库master分支
git push -u origin master
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

​ 正常情况下,第一次push都会提示权限的问题Permission denied (publickey),这是因为,本地仓库和远程仓库交互,需要有一个访问权限publickey,不然怎么保证安全性呢?

配置 ssh_key
生成ssh_key

​ 注意,这里配置的是码云gitee

$ ssh-keygen -t rsa -C *******@126.com
Generating public/private rsa key pair.
# 注意,这里是保存秘钥文件的路径
Enter file in which to save the key (~/.ssh/id_rsa): id_rsa_gitee
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in id_rsa_gitee.
Your public key has been saved in id_rsa_gitee.pub.
The key fingerprint is:
...
The key's randomart image is:
...

​ 基本上一路按照提示操作即可,

cd ~/.ssh

​ 该目录下生成文件如下: id_rsa_giteeid_rsa_gitee.pub

​ 其中id_rsa_gitee.pub存放的是公钥publickey

配置到gitee
  • 登录码云,进入到设置界面,点击SSH公钥

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A3efZ7qA-1606464685466)(Git实战.assets/1606454275889.png)]

  • 标题随便写,可以写rsa_gitee,复制id_rsa_gitee.pub里面的内容到公钥里面,保存

  • 测试

    $ ssh -T git@gitee.com
    The authenticity of host 'gitee.com (212.64.62.183)' can't be established.
    ECDSA key fingerprint is SHA256:FQGC9Kn/eye1W8icdBgrQp+KkGYoFgbVr17bmjey0Wc.
    Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
    Warning: Permanently added 'gitee.com,212.64.62.183' (ECDSA) to the list of known hosts.
    Hi xiaoxiaoyunlu! You've successfully authenticated, but GITEE.COM does not provide shell access.
    

    出现这个,就是配置成功了

  • 重新push

    $ git push -u origin master
    Enumerating objects: 5, done.
    Counting objects: 100% (5/5), done.
    Delta compression using up to 4 threads
    Compressing objects: 100% (3/3), done.
    Writing objects: 100% (3/3), 323 bytes | 161.00 KiB/s, done.
    Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
    remote: Powered by GITEE.COM [GNK-5.0]
    To https://gitee.com/xiaoxiaoyunlu/mano-mall.git
       5417c4a..8ebfb0b  master -> master
    Branch 'master' set up to track remote branch 'master' from 'origin'.
    
推送到其他分支

​ 是不是只能推送到远程仓库的master分支呢,当时不是了,制定推送的分支名称就可以了,具体如下:

# 推送本地代码到远程仓库的dev_mall分支
git push -u origin dev_mall

git pull

​ 每次提价代码到远程仓库之前,记得使用git pull拉取一下远程的最新代码,防止团队里面的其他成员已经提交了新代码,这样方便提前发现冲突,解决后提交

$ git pull
remote: Enumerating objects: 16, done.
remote: Counting objects: 100% (16/16), done.
remote: Compressing objects: 100% (15/15), done.
remote: Total 15 (delta 8), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (15/15), 7.41 KiB | 32.00 KiB/s, done.
From https://gitee.com/xiaoxiaoyunlu/mano-mall
   e184eb4..432a799  master     -> origin/master
CONFLICT (add/add): Merge conflict in README.md
Auto-merging README.md
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory
Automatic merge failed; fix conflicts and then commit the result.

​ 如果直接git pull失败的话,试试如下命令:

git pull --rebase origin master

git fetch

  • 参考文章:

    • https://blog.csdn.net/a19881029/article/details/42245955
    • https://blog.csdn.net/weixin_41975655/article/details/82887273
  • git pull很粗暴的 会将本地库更新至远程库的最新状态

    • 本地代码是merge后的状态,共存差异,本地修改后,解决冲突后,统一提交
    init
    <<<<<<< HEAD
    model 1
    =======
    model 2
    >>>>>>> dev_li
    
    • 注意,git pull简单粗暴,直接尝试merge,隐藏了过程的细节问题,看似危险,但是新版本还是需要我们自己手动去解决冲突的,所以,不用担心,放心使用。
  • git fetch 只会将本地库所关联的远程库的commit id更新至最新

    • 比如本地commitid1 ,如果远程origin没有更新的话,应该也是1,实际情况是,远程最新commtid3,使用git fetch以后,本地保存的origincommitid也会变成最新的3

    • 但是本地库代码没有变化,也没有出现共存差异的情况

    • 这时候,再去merge的话,如果本地和远程的相同代码不一样,才会提示冲突,需要我们手动解决冲突后提交,生成最新版本commit4

  • 总结起来git pull = git fetch+ git merge

    • 只是表象,实际肯定有出入,待查证

git fork

​ 一般是在github或者码云界面操作的,点击右边的fork按钮,把别人远程仓库的代码,复制到自己的远程仓库里面,但是你还需自己git clone到本地来查看和开发修改。

协同开发流程总结

初始提交

## cd 到工作目录

git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin https://gitee.com/xiaoxiaoyunlu/mano-mall.git
git push -u origin master

提交分支到远程master

# 切换到 分支
git checkout dev_14
# 保险起见,还是先pull 防止已经更新
git pull --rebase origin master
# 切换回 master
git checkout master
# 合并分支
git merge dev_14
# 提交
git push -u origin master

​ 注意,可能git pull失败,记得试试:

git pull --rebase origin master

提交到远程开发分支

# 如果master已经有更新了

#切换到master分支
git checkout master
# 拉去最新代码
git pull 
# 切换到 待合并分支
git checkout dev
# 合并到 开发分支
git merge master 
# 提交到开发分支
git push -u origin dev

window上多个git共存配置

需求

​ 比如,有些项目提交到github,其他项目管理在gitee,甚至gitlab都有,这需求要在window配置多个git支持了,否则无法正常工作

​ 前提是,每个git端,都注册有账号,记住,邮箱最好使用不同的。

清除已有的配置

​ 比如,可能已经设置了邮箱和用户名

$ git config --global user.name "你的名字"
$ git config --global user.email  "你的邮箱"

​ 清除掉已有配置:

$ git config --global --unset user.name "你的名字"
$ git config --global --unset user.email "你的邮箱"

配置git多版本

生成ssh-key
ssh-keygen -t rsa -f ~/.ssh/id_rsa.gitee -C "your email@example.com"

​ 也可以进入该目录,不用指定路径

cd ~/.ssh

$ ssh-keygen -t rsa -C "your email@example.com"

有几个git客户端,就操作几遍,记得修改容易记住的标题,比如,当前目录已生成文件列表如下:

id_rsa_gitee

id_rsa_gitee.pub

id_rsa_github

id_rsa_github.pub

分别配置到git界面

在这里插入图片描述

配置git config
# 记住,必须是这个目录
cd ~/.ssh/

# 新建配置文件
vi config

​ 内容如下:

#default github

Host github.com
  HostName github.com
  IdentityFile ~/.ssh/id_rsa_github
  
Host gitee.com
  HostName gitee.com
  IdentityFile ~/.ssh/id_rsa_gitee

​ 注意保存。

添加秘钥到ssh的agent中
  • 最好先删除已有的配置

    ssh-add -D
    

    若执行ssh-add -D是出现这个错误:Could not open a connection to your authentication agent,则先执行如下命令:

    ssh-agent bash
    
  • 挨个添加git的密钥

$ ssh-add id_rsa_github
$ ssh-add id_rsa_gitee
测试
ssh -T git@github.com
ssh -T git@gitee.com

如何参与开源项目

fork项目到自己的git

​ 浏览git上的开源项目,然后点击fork,这时就跳转到了你的账号下,此项目就是你的git仓库下的一个项目了
在这里插入图片描述

clone 代码到本地

# 克隆代码到本地
git clone https://gitee.com/xiaoxiaoyunlu/mano-mall.git
# 进入项目目录
cd mano-mall

添加原作者的仓库地址

git remote add upstream https://gitee.com/xiaoxiaoyunlu/mano-mall.git

​ 查看远程:

$ git remote -v
origin  https://gitee.com/自己的仓库名称/mano-mall.git (fetch)
origin  https://gitee.com/自己的仓库名称/mano-mall.git (push)
upstream    https://gitee.com/xiaoxiaoyunlu/mano-mall.git (fetch)
upstream    https://gitee.com/xiaoxiaoyunlu/mano-mall.git (push)

创建开发分支

​ 当然,你可以不创建开发分支,直接在自己的master分支上修改,不过最好还是创建一个开发分支,便于维护和管理

git checkout -b dev_mall

​ 然后就可以打开ieda 进行修改了

提交到自己的git

# 先获取一下原作者的,看看更新没有
git pull upstream

# 如果没有的话,那就直接提交,有的话,修改下代码在提交
git push -u origin master

申请提交代码到原项目

​ 你对项目的修改已经push到了你的github下了,但是你要向原作者请求合并到原项目中,如果原作者审核后同意合并了,你的更新才能真正提交到原作者的远程仓库,也就意味着你是此项目的贡献者了。

  • 点击Pull requests

  • 点击最右边的New pull request
    在这里插入图片描述

  • 然后按照操作提交,等待原作者审核合并

使用Git常见问题

push error: src refspec master does not match any.

$ git push -u origin master
error: src refspec master does not match any.
error: failed to push some refs to 'https://gitee.com/xiaoxiaoyunlu/mano-mall.git'

​ 引起该错误的原因是,目录中没有文件,空目录是不能提交上去的 ,可以先丢个README.md

git add README 
git commit -m 'first commit'
git push origin master

push remote: You must verify your email address.

remote: You must verify your email address.
remote: See https://github.com/settings/emails.
fatal: unable to access 'https://gitee.com/xiaoxiaoyunlu/mano-mall.git/': The requested URL returned error: 403

​ 很坑爹的问题,git界面上去验证一下邮箱就好了

push后不是项目,而是文件

​ 如果是从网上别人仓库git clone克隆下来的代码,修改后提交的话,必修删除.git文件,然后重新初始化提交,否则就会出现提交也不报错,但是就是提交的是一个文件,而不是项目,点不进去

git clone RPC failed; curl 18 transfer closed with outstanding read data remaining

remote: Counting objects: 5148, done.
remote: Compressing objects: 100% (16/16), done.
error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

​ 发现是由于项目体积过大,所以先尝试增加git传输的项目大小:

git config --global http.postBuffer 1024288000

​ 结果依然还是报错,尝试浅克隆成功,具体如下:

git clone https://gitee.com/xiaoxiaoyunlu/mano-mall.git --depth 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值