zoukankan      html  css  js  c++  java
  • Ubuntu---Git

    本篇文章简单总结了常用 Git 的使用

    前言

    设置用户信息

    1, Git 是分布式的 SSH 代码管理工具,远程的代码管理是基于 SSH 的,所以要使用远程的 Git 则需要 SSH 的配置。

    step 1: 设置 Git 用户的 name 和 email:

    $ git config --global user.name "peng.zhang"
    $ git config --global user.email "peng.zhang@yeah.net"

    生成 SSH 密钥对

    step 2: 生成 ssh 密钥:

    # Ubuntu 默认已安装了 git 和 ssh
    # 进入家目录下的隐藏文件夹 .ssh 下
    $ cd ~/.ssh
    
    # 生成公私钥对
    # 生成的公私钥对名称分别为:公钥:id_rsa 私钥:id_rsa.pub,如果不是,则用 mv 命令重命名即可 $
    ssh-keygen

    加入 SSH 公钥到远端仓库(Repo)

    step 3: 登录 github 账户,然后把生成的公钥加入到 github 账户下的 SSH 公钥列表中,即可对github 进行 ssh 访问了

    # 测试是否能连接到 git 账户
    $ git clone git@github.com:ssezhangpeng/script-to-chouti.git

     git 操作

    初始化 git 仓库

      method1:自己在本地创建一个空仓库

      method2:从远程 clone 一个仓库到本地

    # 创建一个空文件夹作为仓库
    $ mkdir git
    
    # 进入空文件夹,初始化该仓库
    $ cd git
    $ git init

    加入文件到工作区(Work Directory),此时未 add 进 暂存区(Stage)

    # 加入新文件到仓库
    <~git>$ mkdir dir1 dir2 dir3
    <~git>$ vim dir1/main.cpp
    <~git>$ vim dir2/logic.cpp
    <~git>$ vim dir3/logs.txt

    # 此时用 git status 看一下,发现是
    # status: Untracked

    add 文件到暂存区(Stage)

    # add 文件到 Stage 区
    # . 表示本目录下的所有文件
    <~git>$ git add .
    
    # 此时用 git status 看一下,发现是 
    # status: changes to be commit 
    <~git>$ git status
    
    # 此时如果想要撤回 add 的文件
    # stage---> unstage
    <~git>$ git rm --cached file-name

    commit 文件到本地仓库分支(Repo)

    $ 提交暂存区所有文件到本地仓库
    <~git>$ git commit -m "version 0.1"此时如果想要撤回 add 的文件
    
    # 此时用 git status 看一下,发现是
    # status: nothing to commit, working tree clean
    
    # 此时如果想要撤回 commit 的文件
    暂时还没整理好,待续...

    commit 后继续修改原文件

    # 继续开发新功能,修改了 dir1/main.cpp 
    <~git>$ vim dir1/main.cpp
    
    # 此时用 git status 看一下,发现是
    # status: modified:   dir1/main.cpp
    
    # ===============如果想要更新该文件===============
    <~git>$ git add dir1/main.cpp
    # add 之后如果想要撤销此次 add 进的文件
    <~git>$ git reset HEAD dir1/main.cpp
    # 此时可以用 git status 看一下,发现回到了修改后未 add 的状态,此时可以用 add / checkout -- file-name 来决定是否要更新/忽略此次修改
    # ====================END======================
    # 如果想要忽略此次修改,将修改后的文件恢复到未修改之前的状态,像修改文件后没有保存直接退出的操作 
    <~git>$ git checkout -- dir1/main.cpp

    # 如果想要看一下修改的内容是什么
    # 查看当前工作区和暂存区的不同,当然 git diff 还有其它功能,后面有补充
    <~git>$ git diff

     补充:时刻用 git diff 来查看不同之处

    # git diff 的强大之处
    # ==========[1]工作区 VS 暂存区===========
    #
    如果还没 add 进暂存区,则查看文件自身修改前后的差别 $ git
    diff <file-name>

    # 查看与工作区与另一分支的区别
    $ git diff <branch> <file-name>

    # ==========[2]暂存区 VS Git仓库==========
    # 查看已经 add 进暂存区但是尚未 commit 的内容同最新一次 commit 的内容的差异
    # git diff --cached <file-name>

    # 上述可以指定 commit 的版本
    $ git diff --cached <commit-ID> <file-name>

    # ==========[3]工作目录 VS Git仓库==========
    # 查看工作目录同 Git仓库指定的 commit 的内容差异,当 commit-ID = HEAD 时,查看同最近一次 commit 的内容差异
    $ git diff <commit-ID> <file-name>

    # ==========[4]Git 仓库 VS Git仓库==========
    # Git 库任意两次 commit 的差别
    $ git diff <commit-ID> <commit-ID>

    注1:以上命令均可以不指定 <file-name>,此时对全部文件操作

    注2:以上涉及和 Git 仓库进行对比的,均可以指定 commit 的版本(HEAD、HEAD^ ,HEAD~100 等命令可指定)

    版本回退

    =======前言===========
    # 用来显示从近到远的 commit 日志
    $ git log
    
    # 用来记录每一次命令
    $ git reflog
    
    # 移动到任意一个版本[版本穿梭]
    git reset --hard <commit-ID>
    
    ========版本回退========
    # 想回到上一个版本
    $ git reset --hard HEAD^
    # 回到未来的版本:通过 git reflog 找到未来的 commit-ID
    $ git reset --hard <commit-ID>

    删除文件

    # 删除文件也是一个修改操作
    # 我们先加一个文件
    $ git add test.txt
    $ git commit -m "add test.txt"
    
    #============删除文件========
    # 一般情况下,通常在工作区直接把文件删除了
    $ rm -r test.txt
    
    # 此时 Git 知道你删除了文件,此时工作区和版本库就不一致了
    # 用 git status 看一下: Changes not staged for commit [delete:test.txt]
    
    # 1,如果你确实要从版本库中删除该文件
    $ git rm -r  test.txt
    $ git commit -m "remove test.txt"
    
    # 2,如果你是删除错了,因为版本库中还有,所以可以恢复到版本库中的最新版本
    $ git checkout -- test.txt

     分支操作

    #============创建分支============
    # 在本地 master分支下创建并切换到新分支 dev [note:如果想在dev分支下创建新分支,首先切换到 dev 分支,然后再执行下述命令]
    $ git checkout -b dev
    # 等价于下面两条命令
    $ git branch dev
    $ git checkout dev
    
    # 创建远程分支
    # 当我们在本地创建了新分支之后,直接推送到远端,此时远端就会生成一个同名分支
    $ git push origin dev
    
    #============删除分支============
    # 删除本地分支 dev
    $ git branch -d dev
    # 强制删除
    $ git branch -D dev
    # 删除远端分支 dev 
    $ git push origin
    --delete dev

    注:删除该分支之前必须要切换到其它分支,然后再执行删除操作

    合并操作

    # 本地合并操作
    # 合并指定分支到当前分支,当前分支在 master 上
    $ git merge dev

    解决冲突

    # 当进行合并操作时,如果两个要合并的分支内容不同,则产生冲突,因为 git 当前分支不知
    # 道我是继续保留我自己的分支,还是要换成指定分支的内容,需要用户手动解决冲突
    
    # 例如 master 分支内容为:
    to test conflict!
    # feature1 分支内容为:
    TO TEST CONFLICT!
    
    # 我们想要把 dev 分支上的内容合并到 master 上
    # 执行下面命令后会出现错误提示: Merge conflict in readme.txt(冲突文件名)
    $ git merge feature1
    
    # 此时我们用 vim 打开冲突的文件,进行手动编辑决定保留哪一个
    # 此时冲突文件中:
    # <<<<<<<<<HEAD :表示 master 冲突文件中不同的内容
    # >>>>>>>>> dev : 表示指定合并的分支的冲突文件中不同的内容
    # 并用 ==============来分割两个不同的分支的内容
    
    # 解决冲突后可以重新进行合并操作,但是注意也要重新 add 文件
    $ git add readme.txt
    $ git commit -m "fixed conflict"

    此时查看分支的合并情况:

    $ git log --graph --pretty=oneline --abbrev-commit

    Rebase 合并提交历史记录

      当多人在一个分支上协同工作时,很容易出现冲突。即使没有冲突,后 push 的同学不得不先 pull ,在本地合并,然后才能 push 成功。每次合并再 push 后,分支就会变成下图那样:

      那能不能使 Git 的提交历史是一条干净的直线?当然可以,这就是 Rebase 的作用。

    # 首先我们在本地分支 master 上添加新文件 helo.py,内容为 # Author:peng.zhang
    # 然后 add , commit
    $ git add hello.py
    $ git commit -m ".py file add Author"
    
    # 此时用 git status 看一下发现当前分支提前 origin/master 一个提交
    # 然后我们在 github 上修改 README.md 文件,然后直接在页面上 commit,以此模拟其它同学的提交操作
    # 然后我们推送我们的修改到远端
    # 此时发生错误:updates were rejected because...,这说明有人先于我们推送了远程分支
    $ git push origin master
    
    # 按照经验,先 pull 一下
    # 提示:Merge made by the ‘recursive’ strategy
    # pull 中包含 merge 操作,没有发生冲突,因为我们只是增加了文件,没有修改其它相同文件
    # 如果发生了冲突,则需要先 fetch 到本地,然后手动解决冲突,再执行 merge 操作
    $ git pull 

    此时我们看一下 commit 历史记录:

    $ git log --graph --pretty=oneline --abbrev-commit

    可以看到,此时历史提交记录已经分叉了,我们用 rebase 试试看结果是什么?

    $ git rebash

    此时,我们再看一下历史提交记录

    我们可以发现历史提交记录变成了一条直线,我们仔细看可以发现变化的是什么?其实就是 Git 把本地的提交移动了位置,相当于[先从本地执行 pull 操作,然后再在本地做修改,接着再提交修改]的顺序执行,把一个并行操作转换为一个顺序执行的操作,这样就不会发生任何冲突,所以也就不需要进行合并操作,即历史记录不会有分支。

    开发过程中所用到的一些操作

    git fetch

      当我们在自己的分支进行开发时,别的同事可能已经对 master 分支进行过合并操作,我们需要取回远端 master 分支上我们本地没有的内容,然后再进行本地和远程分支的合并操作,之后 push 到远端。

    # git fetch 可以从远端仓库获取到最新版本到本地
    # 将远程主机的更新全部取回本地,git fetch 获取所有分支的更新
    $ git fetch
    
    # 取回特定分支的更新,可以指定分支名称
    $ git fetch origin master
    
    #当取回远程主机的更新以后,可以执行合并操作,在本地分支上合并远程分支,当然,此时可能会发生冲突,需要手动解决冲突
    # 在当前分支上合并 origin/master
    $ git merge origin/master

    注:具体图示见文末参考资料链接[1]

    git stash

      当我们在自己的分支进行开发工作时,此时有一个 Bug 需要我们紧急修复,我们没有办法先把我们的开发工作提交,因为该工作还没完成,这是我们就可以用打 stash 命令了。这条命令会把当前个工作现场“储存起来”,等以后恢复现场后继续工作。

    # 存储现场
    $ git stash
    
    # 此时用 git status 看一下工作区,发现是干净的
    ========修复 Bug=========
    # 如果我们要在 master 分支上修复 issue
    $ git checkout master
    $ git checkout -b issue-101
    $ vim bug-file 进行修复
    $ git add bug-file
    $ git commit -m "fixed issue-101"
    # 切换回 master 分支,完成合并
    $ git checkout master
    $ git merge --no-ff -m "merged bug fix issue-101"
    
    =======恢复现场=======
    # 查看保存的工作现场
    $ git stash list
    
    #恢复现场方法1:该方法不会删除保存的工作现场,需要用 git stash drop 来删除
    $ git stash apply
    
    # 恢复现场方法2:恢复的同时也把 stash 给删除了
    $ git stash pop
    
    ===========多次 stash========
    # 恢复的时候,先用 git stash list 查看,然后恢复指定的 stash
    $ git stash apply stash@{0}

    ===========清空 stash========
    #如果有多个 stash 队列,下面命令会清空所有 stash 队列
    $ git stash clear

    多人协作

      在工作中,我们都会往 master 和 dev 分支上推送各自的修改,当我们从远程库 clone 时,默认情况下,只能看到本地的 master 分支,当我们要在 dev 分支上进行开发时,就必须创建远程的 dev 分支到本地(现实情况是 master 是稳定分支,dev 是开发分支,我们再建立每个人自己的开发分支,比如我的分支名称为: from_zhangpeng,然后不断往 dev 分支上进行何合并,由管理员合并 dev 分支到 master 分支)

    # 建立自己的分支 dev
    # 下行命令可以自动追踪 dev 分支[此时远程的 dev 分支必须已存在]
    $ git checkout -b dev  origin/dev
    
    # 不自动追踪 dev 分支
    $ git checkout -b dev
    
    # 不断进行修改,时不时把本地 dev 分支推送到远程 dev 分支
    # 如果已建立追踪,则可以忽略分支名称
    $ git push origin dev

     git 相关配置

    gitconfig 相关配置

    # ===========配置用户名和密码============
    $ git config --global user.name "peng.zhang"
    $ git config --global user.email "peng.zhang@yeah.net"
    
    # 如果希望在不同的项目中使用不同的 user.name 和 user.email,可在该项目中运行:
    $ git config user.name "peng.zhang"
    $ git config user.email "peng.zhang@yeah.net"
    
    # ===========配置默认编辑器============
    $ git config --global core.editor vim
    
    # ===========配置默认比较工具============
    $ git config --global merge.tool vimdiff
    
    # ===========检查配置============
    $ git config --list
    
    # ===========添加配置项============
    # 默认为 local 范围修改
    $ git config [--local | --global | --system ] --add site.name yiibai 
    
    # ===========删除配置项============
    $ git config --local --unset set.name
    
    # ===========获取帮助============
    $ git help config

     参考资料

    [1] https://git-scm.com/book/zh-tw/v1

    [2] https://www.liaoxuefeng.com/wiki/896043488029600

    [3] https://www.yiibai.com/git/git-quick-start.html

    所有博文均为原著,如若转载,请注明出处!
  • 相关阅读:
    2018-8-18 训练神经网络笔记
    ffmpeg解码视频为图片和将图片合成一个MP4视频
    minikube start error
    按顺序将目录下的所有文件的绝对路径写入文件中
    ssh远程免密登录
    Ubuntu默认的awk一直报语法错误
    ffmpeg常用操作
    ssh免密登录server
    cv::namedWindow是非线程安全的
    lingcrypt源码安装undefined reference to ...
  • 原文地址:https://www.cnblogs.com/zpcoding/p/11103374.html
Copyright © 2011-2022 走看看