3

git 常用命令

git blame [file] // 显示某个文件的提交历史
git diff              // 显示暂存区和工作区的差异
git diff  branch1 branch2 // 比较两个分支的差异
git checkout .  // 删除暂存区的所有更改
git show [commit] // 显示某次提交的元数据和内容变化
git log --oneline // 一行展示git提交历史
git log --graph // 树形展示
git log --stat // 显示commit 历史,以及每次commit发生的文件变动
gitk                     // 类似sourcetree 的管理客户端
git reflog           // 最近几次的提交

初始化

  • 初始化一个本地仓库 参考

正常流程

  1. git clone [url] (本地已产生 master分支)
  2. 两种方法创建本地 dev 分支

    • git checkout -b fetature/xxx // 以本地master分支为基础创建
    • git checkout -b fetature/xxx origin/master // 以远程master为基础创建

  3. 在本地分支 dev 上进行工作修改,修改完毕后

    • git add . (代码添加到暂存区,如果是新增的文件用 git add -A 或者接 add 文件名)
    • git commit -m '提交注释' (代码提交到本地版本库)
  4. git pull origin developer (拉取远程 developer 分支上最新内容到本地)
  5. git push origin developer (将本地 developer 分支上的内容推送到远程)
  • 至此,整个工作流程结束!

本地分支与远程分支不同时存在的情况

  1. 本地分支存在远程没有与之对应的分支,如何将本地该分支push到远程,并在远程创建一个同名分支并与之联系?

    • git push origin test (如果远程不存在test分支,会在远程自动创建一个test,并与本地test分支进行联系)
    • 或者
    • git push --set-upstream origin test
    • 上条命令的好处就是 下次在该分支上 push 的时候,可以直接 使用 git push 命令了,因为该分支已于远程分支建立联系了
  2. 远程分支已存在,本地想创建一个分支与远程分支建立追踪关系

    • git checkout -b developer origin/developer(已远程的developer分支为基础,创建本地分支)
    • or
    • git checkout --track origin/developer
      (这时本地会新建一个分支名叫 developer,此时会自动跟踪远程的同名分支 developer
    • 或者直接使用 git checkout branch_name (利用tab键补全分支名称),这样创建的分支会与远程分支建立直接联系(该方法最简单)
  3. 删除远程分支

    • git push origin :the_branch // 删除远程 the_branch 即推送一个空的内容到远程

git分支使用

当你在写一个新功能的时候,突然万恶的产品狗提出了一个bug,并要求你一个小时内修复,这时,你只能放下手中的工作,去修复这个bug,但是,你此时并不想提交你的当前修改的代码这时怎么办呢???

git 强大的分支功能,就派上用场了

第一种方法
  • 操作步骤:创建一个新的分支并提交修改,只需要以下几个步骤

    1. git checkout -b bug001 // 创建bug 分支并切换
    2. 修改完成后 git add ,git commit -m ''
    3. 切换到开发分支上

        `git checkout dev`
        `dev 上 git merge bug001 ``
        `git push dev origin Developer`
    4. 提交完成后 切换回 work 分支,继续原来的工作
第二种解决办法用 git stash 命令
  • 命令作用:备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中。
  • 命令选项:

    • git stash 即上述功能
    • git stash list: 显示Git栈内的所有备份,可以利用这个列表来决定从那个地方恢复。
    • git stash apply stash@{x} // x:为 list 列出的编号 具体恢复哪一个备份
    • git stash drop stash@{X} //将记录列表中取出的对应暂存记录删除
    • git stash pop: 从Git栈中读取最近一次保存的内容,恢复工作区的相关内容。由于可能存在多个Stash的内容,所以用栈来管理,pop会从最近的一个stash中读取内容并恢复。
    • git stash clear:
    • 清空Git栈。此时使用git等图形化工具会发现,原来stash的哪些节点都消失了。

git 删除分支

  1. 删除本地分支 git branch -D br
  2. 删除远程分支 git push origin :br (origin 后面有空格) 即:推送一个空的分支到远程的该分支

合并远程的两个分支

  1. 假如远程有两个分支 分别是 master、dev 分支,两个分支内容不同
  2. 本地有一个 master 分支
  3. 在本地建立一个 dev 分支并与远程 dev 建立联系
  4. 在 dev 分支 上 merge master 分支
  5. 将 dev 分支 push 到远程
  • 操作命令:
  • git checkout -b origin/dev 建立联系
  • git merge master 合并master分支
  • git push origin dev 本地 dev 分支 push 到远程

利用 github (gh-pages 分支) 展示前端静态页面

git后悔操作 - reset revert checkout

reset

  • 将当前分支的末端指向某一次提交,可用于移除该提交之后的提交(push 后 远程的本版本记录里不会存在该提交后的提交,只有本地还记录这这几次commit)

    git reflog  // 找到要退回的版本的 commit_id
    git reset --hard commit_id // 版本历史回退到指定的 commit
  • 撤销当前 commit

    绿字变红字(撤销缓存区的修改即撤销 add ) git reset HEAD .
    红字变无  (撤销工作区的修改) 
    git checkout .   git checkout 目录   git checkout 文件
  • reset 的三个参数

      --soft – 缓存区和工作目录都不会被改变
      --mixed – 默认选项。缓存区和你指定的提交同步,但工作目录不受影响
      --hard – 缓存区和工作目录都同步到你指定的提交
      一般使用 --hard

checkout

  1. 切换分支 git checkout branch
  2. 切换到 某次 commit git checkout commit_id // 仅仅是切换到这次提交的代码上
  3. 丢弃工作目录上的修改:
    git checkout . // 丢弃所有工作目录上的修改
    git checkout js/component/extendExport.js // 仅仅只是丢弃该文件上的修改

revert

  • git revert commit_id 以历史上的某次 commit 为基础新建一次 提交,该 commit 之后的记录依旧存在于版本库中,但代码已经不见了
  • 在主干分支git revert 操作之后,会导致某些分支的提交无法再 merge 到 主干分支,因为主干分支已经领先于功能分支了
  • 使用场景:master 分支一般不允许git操作,只能进行 merge,所以利用该功能进行版本回退

reset / checkout/ revert 撤销的区别联系

命令作用使用场景
git reset提交层面/文件层面在私有分支上舍弃一些没有提交的更改/将文件从缓存区中移除
git checkout提交层面/文件层面切换分支或查看旧版本/舍弃工作目录中的修改
git revert提交层面在公共分支上回滚更改

reset 远程分支

git reflog  查看提交版本号
git reset --hard commit_id  回退本地版本库

紧接着强制推送到远程分支:git push -f
注意:本地分支回滚后,版本将落后远程分支,必须使用强制推送覆盖远程分支,否则无法推送到远程分支

添加忽略文件

  • 情况一:要忽略的文件还没有被git追踪(可能是刚刚新建的文件)
    解决方法:这种情况很简单,只要在 .gitignore 添加一行忽略规则即可
  • 情况二:要忽略的文件已经被git追踪过了(临时想起来想忽略的文件)

    git update-index --assume-unchanged html-test/.env

git 打标签

git 命令行如何打 tag(标签)? http://www.jianshu.com/p/dab7...
  • tag 要提交生产环境的版本号,打上 tag 就意味着,该版本要部署到生产环境

新建tag

  • git tag -a v1.0 -m “Release version 1.0″ // 创建本地tag
  • git push origin --tags (or git push origin v1.0)
  • 本地tag push 到远程 --tags 将所有的tag提交到服务端 或者 直接加tag名称,是将该tag提交到服务端
  • git tag -l -n // 列出所有 tag 及注释, git tag 只能列出tag列表,不会显示注释

删除 tag

  • 删除本地tag git tag -d tag名称
  • 删除远程tag git push origin :refs/tags/标签名

利用linux命令 grep 进行标签模糊查询

  • git tag|grep dev_20180124 模糊查询所有含有dev_20180124tag名称

git fetch 与 git pull

  • git fetch + git merge
   git fetch origin master // 将远程的变动拉取到本地
   git diff origin/master // 查看本地分支与远程分支的差异
   git merge  // 将远程分支与本地分支合并
   git fetch 与 git pull 都是从远程拉去最新的代码到本地
   
   git fetch: git fetch 取回所有分支的更新。如果只想取得固定分支的更新,可以指定分支名
              取回的纪录存在 .git/FETCH_HEAD 文件中
              
   git fetch 取回的远程分支的更新不会和本地分支自动合并
   git pull 取回远程主机某个分支的更新,再与本地指定的分支合并。
   
   git pull origin master === git fetch origin master   +  git merge 

   =========================================================================
    上面说的太泛泛了,没有针对性
    
    git fetch 取回的更新,再本地主机上要用 “远程主机名/分支名” 的形式读取。
    比如 origin 主机上的 master分支,就要用 origin/master 读取
    要查看 fetch 下来的内容,可用如下操作
    git checkout origin/master (即切换到以当前提交的版本号为名的分支上)
    如下所示:
    easy git:(e0078ea) git branch -a
    
    查看完之后,切回master分支,然后 merge
    git checkout master
    git merge
    即把fetch下来的内容合并到本地master分支上了

git rebease or git merge merge 与 rebase

  • merge:是将分叉几方与他们最近的共同祖先进行合并,然后生成一个新的提交
  • rebase:将 目标分支合并到本分支上, 不会产生新的提交,主干分支看起来就好像一条线提交,commit 历史比较整洁
  • rebase 合并后的分支呈线性,而merge 后分支显示的错综复杂
  • rebase学习链接 rebase学习
  • rebase的作用简要概括为:可以对某一段线性提交历史进行编辑、删除、复制、粘贴;因此,合理使用rebase命令可以使我们的提交历史干净、简洁!
基础 rebase 操作
git rebase master // 一定要在一个只有你自己做修改的 feature 分支上执行这个命令
// 把整个的 feature 分支移到 master 分支后面,有效地把master分支上新的提交合并过来
// rebase 重写了 feature 分支上所有的提交,并且不会产生合并提交

git checkout master

git merge dev_xxx  // 现在回到 master 分支,进行一次快进合并。

这种自动 rebase 不会去除多余的commit信息,只会让 master 提交历史变得线性
交互式的 rebase 操作
git log --oneline // 一行展示 commit 信息

git rebase -i master

会打开一个vim文本编辑器
pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

- 将 pick 改成你需要的操作-- 一般是用 squash (挤压)

- 文本注释部分给我提供了如下注释
pick:保留该commit(缩写:p)
reword:保留该commit,但我需要修改该commit的注释(缩写:r)
edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
squash:将该commit和前一个commit合并(缩写:s)
fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
exec:执行shell命令(缩写:x)
drop:我要丢弃该commit(缩写:d)

- :wq 保存退出后,会再打开以文本编辑器,然你修改注释信息,把要保留的 commit 信息,保留下来,其余删除(示意图如下)

- 然后再用 `git log --oneline ` 新提交注释信息,只剩下刚才编辑剩下的了

git checkout master
git merge fetature  即可看到一条线性的提交历史

交互式rebase 修改注释信息
clipboard.png

git pull
  • 默认会执行一次 merge,可用 git pull --rebase,不会产生多余的 merge commit
  • git pull --rebase 相当于 git fetch + git rebase
总结
在你执行「变基」操作的时候,git会将你feature分支中的所有新提交撤销commit,
并把这些改动临时帮你寄存在.git/rebase目录下,
之后再将清空后的feature分支更新到master分支状态,
最后再把刚才临时帮你保存的变动应用到同步过后的fetaure分支上。
这样就起到了「变基」的作用,这种改动是从commit的最后一个公共部分开始的。所以叫「变基」

1. merge和rebase合并后的结果是一模一样的,形象的说,二者是殊途同归。
2. 使用rebase「变基」后的commit与之前没有变基前的commit是不同的,它们的SHA-1值不同,Git会把它们看成两次提交。

现在的多人协作的开源项目一般都是用 rebase 的(即提交前先 rebase 一下 主干分支)
这其实相当于帮作者处理好了冲突,作者合代码的时候比较轻松
本地清理-修改commit 历史
  • --amend 修改最近一次的 commit 信息

    git commit --amend // 进入 vim 编辑,:wq 保存即修改完成
    如果该 commit 已 push 到远程,在 push 需用 git push -f
  • git rebase -i HEAD~3 // 查看最后三次提交,和上面的交互式rebase 一样,进行修改提交历史
merge vs rebase
  • merge 是一个安全的操作,现有的分支提交不会被修改,merge 会多产生一次commit,将各个 分支的 commit 组合到一起 , 会产生错综复杂的历史提交线
  • rebase 会将主干分支新产生的提交挪到 feature 之前,在 feature merge 到 master 之后,会产生一条线性的历史提交线,还可以做到修改 历史提交记录
总结:
  • 如果你想要一个干净的、线性的提交历史,没有不必要的合并提交,你应该使用 git rebase 而不是 git merge 来并入其他分支上的更改。
  • 如果你想要保存项目完整的历史,并且避免重写公共分支上的 commit, 你可以使用 git merge。两种选项都很好用,但至少你现在多了 git rebase 这个选择。

git cherry-pick commit_id

cherry: 🍒 ,git 精心帮你挑选的🍒
  • 使用场景:想把某次 commit(随便哪个分支上的),放到你需要的分支
  • 问题: 今天碰到一个问题:同事离职了,但他还有未发布的需求(已经发到测试环境上了),但是他的开发分支并没有 push 到远程,现在要上线了,找不到他的开发分支,无法发布(真是一个坑爹达人啊)
  • 解决方案:从 test 根据 commit注释信息 按顺序找到他所有的 commit id,然后在新分支上按从始到终的顺序依次执行git cherry-pick commit_id,把它所以commit pick 到你的新分支上
  • 该操作会产生一次新的提交(一个新的 commit_id

git 仓库迁移

git clone [旧仓库地址]

# 拉取旧仓库所有分支代码
git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done
git fetch --all
git pull --all

# 修改本地代码仓库远程源地址指向新的远程源地址
# 新建一个空白仓库: git@gitlab.hupu.com:HPLiveFront/live-pc.git
git remote set-url origin [新仓库地址如]
git push --all 
# 完成

其他系统操作/linux命令

  1. 自动生成文件目录结构

    brew install tree 进行安装
    
    常用命令:
    tree -a       // 查看某个文件下的所有文件
    tree -d       // 只显示文件夹
    tree -L n     // 显示项目的 n 层级
    tree -I "node_module|dist"   // 用于过滤不想显示的文件或文件夹
    tree > tree.md  // 将结果输出到相应的文件内

大桔子
588 声望51 粉丝

下一步该干什么呢...