专栏首页腾讯DevOpsGit 的一些事
原创

Git 的一些事

腾讯工蜂Git:基于Git的企业级协作开发解决方案,腾讯未来研发关键系统

https://code.tencent.com

腾讯工蜂用户:涂金林

常用命令

简单的,常用的命令也就几个。但是想非常熟练使用,怕是要记住几十个。

  • Workspace:工作区(clone或者原始内容)
  • Index/Stage:暂存区(有增删改查后add到临时区)
  • Repository:本地仓库(保存了本地的增删改查记录)
  • Remote:远程仓库(git.code.oa.com,本地的记录提交到远端,供团队所有人查看使用)

有意思的事

代码更新之Fetch vs Pull

二者都是从远程拉取代码到本地

  • fetch:只是拉取到本地
  • pull:不仅拉取到本地,还merge到本地分支中

代码合流之Merge vs Rebase

  • rebase:用于把一个分支的修改合并到当前分支

假设远程分支上有2个提交,然后基于远程develop,再创建一个分支feature。

然后分别在两个分支上做两次提交。

git merge

这时候,你可以用pull命令把develop分支上的修改拉下来并且和你的修改合并;结果看起来就像一个新的和并提交

git rebase

$ git checkout feature
$ git rebase develop
  1. 这些命令会把你的feature分支里的每个提交(commit)取消掉,并且把它们临时保存为补丁(patch)(这些补丁放到".git/rebase"目录中)
  2. 然后把feature分支更新为最新的develop分支
  3. 最后把保存的这些补丁应用到feature分支上
  4. 当feature分支更新后,会指向最新的commit,临时存放的就会被删除掉

代码回滚之Reset、Revert、 Checkout

  • Reset

将一个分支的末端指向另一个提交,可以用来移除当前分支的一些提交。

文件层面上,将缓存区的文件同步到指定的那个提交。

$ git checkout develop
$ git reset HEAD~2
​
# 将当前的README.md从缓存区中移除出去
$ git reset HEAD README.md

develop分支末端的两个提交就变成了悬挂提交

如果提交还没有push,git reset 是撤销commit的简单方法

除了在当前分支上操作,还可以通过其他参数来修改stage或者workspace

  1. --soft:stage和workspace都不会被改变
  2. --mixed(默认):stage和你指定的提交同步,但workspace不受影响
  3. --hard:stage和workspace都同步到你指定的提交
# 将当前的改动从stage中移除,但这些改动还保留在workspace中
$ git reset --mixed HEAD
​
# 完全舍弃没有提交的改动
$ git reset --hard HEAD
  • Checkout

提交层面上的checkout,可以切换分支,同一分支,可以切换当前HEAD。

文件层面上,不会移动HEAD指针,也不会切换到其他分支上,只是更改workspace,而不是stage。

# 将HEAD移到新的分支,然后更新工作目录
$ git checkout develop
​
# 将HEAD移动到当前commit的前两个commit上,同时更新workspace
$ git checkout HEAD~2
​
# 将workspace中的README.md同步到最新的提交
$ git checkout HEAD README.md
  • Revert

撤销一个提交的同时会创建一个新的提交。

# 产生一个新的commit用于撤销倒数第二个commit
$ git checkout develop
$ git revert HEAD~2
  1. 不会改变提交历史
  2. revert可以用在公共分支,reset应该用在私有分支上
  3. 如果提交已经push,想到达到撤销的目的,应该使用revert

命令

作用域

常用情景

git reset

提交层面

在私有分支上舍弃一些没有提交的更改

git reset

文件层面

将文件从缓存区中移除

git checkout

提交层面

切换分支或查看旧版本

git checkout

文件层面

舍弃工作目录中的更改

git revert

提交层面

在公共分支上回滚更改

git revert

文件层面

(然而并没有)

代码暂存之Stash

git stash会把所有未提交的修改(包括暂存和未暂存的)都保存起来,用于日后恢复当前工作目录

  • 保存一个不必要但日后又想查看的提交
  • 切换分支前先暂存,处理分支的其他事情
$ git status
On branch develop
Changes to be committed:
​
new file:   README.md
​
Changes not staged for commit:
​
modified:   index.html
​
$ git stash
Saved working directory and index state WIP on master: 5002d47 ...
​
$ git status
On branch master
nothing to commit, working tree clean

stage是本地的,不会上传到git server

实际应用中,推荐给每个stash加一个message,使用git stash save 取代 git stash

$ git stash save "test stash"
Saved working directory and index state On autoswitch: test stash
HEAD 现在位于 296e8d4 remove unnecessary postion reset in onResume function
$ git stash list
stash@{0}: On autoswitch: test stash
  1. 可以使用git stash list命令,查看stash列表
$ git stash list
stash@{0}: WIP on master: 049d078 stash_0
stash@{1}: WIP on master: c264051 stash_1
stash@{2}: WIP on master: 21d80a5 stash_2

2. 使用git stash apply命令可以通过名字指定那个stash,默认指定最近的(stash@{0})

3. 使用git stash pop将stash中第一个stash删除,并将对应修改应用到当前的工作目录中

4. 使用git stash drop,后面加上stash名,可以移除相应的stash;或者使用git stash clear清空所有stash

默认情况下,git stash会缓存:

  • 添加到暂存区的修改(staged changes )
  • Git跟踪但并未添加到暂存区的修改(unstaged changes)

但不会缓存:

  • 在工作目录中新的文件(untracked files)
  • 被忽略的文件(ignored files)

此时,使用-u或者--include-untracked可以stash untracked 文件;使用-a或者--all可以stash当前目录下的所有修改(慎用

基础命令

初始化

# 在当前目录新建一个Git代码库
$ git init
​
# 新建一个目录,将其初始化为Git代码库
$ git init git_test
​
# 下载一个项目和它的整个代码历史
$ git clone http://git.code.oa.com/jaelintu/git_test

增加/删除文件

# 添加指定文件到暂存区
$ git add file1 file2...
​
# 添加指定目录到暂存区,包括子目录
$ git add dir
​
# 添加当前目录的所有文件到暂存区
$ git add .
​
# 添加每个变化前,都会要求确认
# 对于同一个文件的多处变化,可以实现分次提交
$ git add -p
​
# 删除工作区文件,并且将这次删除放入暂存区
$ git rm file1 file2 ...

代码提交

# 提交暂存区到仓库区
$ git commit -m "message"
​
# 提交暂存区的指定文件到仓库区
$ git commit file1 file2 ... -m "message"
​
# 提交工作区自上次commit之后的变化,直接到仓库区
$ git commit -a
​
# 提交时显示所有diff信息
$ git commit -v
​
# 使用一次新的commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
$ git commit --amend -m "message"
​
# 重做上一次commit,并包括指定文件的新变化
$ git commit --amend file1 file2 ...

分支

# 列出所有本地分支
$ git branch
​
# 列出所有远程分支
$ git branch -r
​
# 列出所有本地分支和远程分支
$ git branch -a
​
# 新建一个分支,但依然停留在当前分支
$ git branch name
​
# 新建一个分支,并切换到该分支
$ git checkout -b branch
​
# 新建一个分支,指向指定commit
$ git branch name commit_SHA
​
# 新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track name orgin/name
​
# 切换到指定分支,并更新工作区
$ git checkout name
​
# 切换到上一个分支
$ git checkout -
​
# 建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream name origin/name
​
# 合并指定分支到当前分支
$ git merge branch-name
​
# 选择一个commit,合并进当前分支
$ git cherry-pick commit_SHA
​
# 删除分支
$ git branch -d branch-name
​
# 删除远程分支
$ git push origin --delete branch-name
$ git branch -dr remote/branch

tags

# 列出所有tag
$ git tag
​
# 新建一个tag在当前commit
$ git tag tag-name
​
# 新建一个tag在指定commit
$ git tag tag-name commit-SHA
​
# 删除本地tag
$ git tag -d tag-name
​
# 删除远程tag
$ git push origin :refs/tags/tag-Name
​
# 查看tag信息
$ git show tag-name
​
# 提交指定tag
$ git push origin tag-name
​
# 提交所有tag
$ git push origin --tags
​
# 新建一个分支,指向某个tag
$ git checkout -b branch-name tag-name

查看信息

# 显示有变更的文件
$ git status
​
# 显示当前分支的版本历史
$ git log
​
# 显示commit历史,以及每次commit发生变更的文件
$ git log --stat
​
# 搜索提交历史,根据关键词
$ git log -S [keyword]
​
# 显示某个commit之后的所有变动
$ git log (tag-name||commit-SHA) HEAD
​
# 显示某个文件的版本历史,包括文件改名
$ git log --follow file
$ git whatchanged file
​
# 显示指定文件相关的每一次diff
$ git log -p file
​
# 显示过去5次提交
$ git log -5 --pretty --oneline
​
# 显示所有提交过的用户,按提交次数排序
$ git shortlog -sn
​
# 显示指定文件是什么人在什么时间修改过
$ git blame file
​
# 显示暂存区和工作区的代码差异
$ git diff
​
# 显示暂存区和上一个commit的差异
$ git diff --cached file
​
# 显示工作区与当前分支最新commit之间的差异
$ git diff HEAD
​
# 显示两次提交之间的差异
$ git diff [first-branch]...[second-branch]
​
# 显示今天你写了多少行代码
$ git diff --shortstat "@{0 day ago}"
​
# 显示某次提交的元数据和内容变化
$ git show commit-SHA
​
# 显示某次提交发生变化的文件
$ git show --name-only commit-SHA
​
# 显示某次提交时,某个文件的内容
$ git show commit-SHA:filename
​
# 显示当前分支的最近几次提交
$ git reflog
​
# 从本地master拉取代码更新当前分支:branch 一般为master
$ git rebase branch-name

远程同步

# 下载远程仓库的所有变动
$ git fetch origin
​
# 显示所有远程仓库
$ git remote -v
​
# 显示某个远程仓库的信息
$ git remote show origin
​
# 增加一个新的远程仓库,并命名
$ git remote add shortname url
​
# 取回远程仓库的变化,并与本地分支合并
$ git pull origin branch-name
​
# 上传本地指定分支到远程仓库
$ git push origin branch-name
​
# 强行推送当前分支到远程仓库,即使有冲突
$ git push origin --force
​
# 推送所有分支到远程仓库
$ git push origin --all

撤销

# 恢复暂存区的指定文件到工作区
$ git checkout file
​
# 恢复某个commit的指定文件到暂存区和工作区
$ git checkout commit-SHA file
​
# 恢复暂存区的所有文件到工作区
$ git checkout .
​
# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
$ git reset file
​
# 重置暂存区与工作区,与上一次commit保持一致
$ git reset --hard
​
# 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
$ git reset commit-SHA
​
# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
$ git reset --hard commit-SHA
​
# 重置当前HEAD为指定commit,但保持暂存区和工作区不变
$ git reset --keep commit-SHA
​
# 新建一个commit,用来撤销指定commit
# 后者的所有变化都将被前者抵消,并且应用到当前分支
$ git revert commit-SHA
​
# 暂时将未提交的变化移除,稍后再移入
$ git stash
$ git stash pop

冲突解决

rebase过程中,也许会出现冲突(conflict)

  • git会停止rebase,需要解决冲突
  • 解决完,使用git add添加冲突的文件,更新暂存区
  • git rebase --continue继续剩下的rebase
  • git rebase --abort终止rebase行为,并且feature会回到rebase开始之前的状态
$ git rebase develop
CONFLICT (content): Rebase conflict in readme.txt
Automatic rebase failed; fix conflicts and then commit the result.
​
$ git status
On branch feature
​
You have unmerged paths.
  (fix conflicts and run "git rebase --continue")
  (use "git merge --abort" to abort the merge)
​
Unmerged paths:
  (use "git add <file>..." to mark resolution)
​
    both modified:   readme.txt
​
no changes added to commit (use "git add" and/or "git commit -a")

查看readme.md 内容

Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature

选择保留HEAD或者feature的版本

Git tracks changes of files.
Creating a new branch is quick AND simple.

在提交:

$ git add readme.md
$ git rebase --contine

推荐的Git GUI工具

 1.  Source Tree(号称最好用):特色支持git flow,一键创建工作流

  • 免费功能
  • 强大:无论你是新手还是重度用户,SourceTree 都会让你觉得很顺手。对于非常重度用户,Source Tree还支持自定义脚本的执行
  • 同时支持 Windows 和 Mac 操作系统
  • 同时支持 Git 和 Mercurial 两种 VCS
  • 内置GitHub, BitBucket 和 Stash 的支持:直接绑定帐号即可操作远程repo

2. Tortoise git:文件的右键菜单很容易上手

  • 免费
  • 只支持Windows:与文件管理器良好集成
  • 中文界面
  • 与Tortoise SVN相同的体验


扫描以下二维码,研发管理从此高效、轻便、可靠

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Git快速入门

    git作为现在最为流行的版本管理系统,大部分公司都使用git进行版本控制,并且最大程序员交友网站github也是在git的基础上建立的。 很多人认为git难,在...

    腾讯工蜂
  • 【超干货】Git 的基本操作、开发流程、实用技巧总结

    Git 是一个分布式的代码管理容器,本地和远端都保有一份相同的代码。 Git 仓库主要是由是三部分组成:本地代码,缓存区,提交历史,这几乎是所有操作的本质,但是...

    腾讯工蜂
  • Git内部原理介绍

    git 是一个内容寻址的文件系统,其核心部分是一个简单的键值对数据库(key-value data store),可以向该数据库插入任意类型的内容,它会返回一个...

    腾讯工蜂
  • 高频使用的 Git 命令

    在整个功能开发完毕的时侯,会有非常多的 commit,用 rebase 可以让我们的commit记录很干净

    CRPER
  • 高效协同开发

    假设服务机器开通sambas服务端口,并且windows防火墙允许访问。这时候可以在windows打开网盘一样,打开sambas共享的服务器文件夹,把代码工程放...

    mariolu
  • 珍藏多年的 Git 问题和操作清单

    本文整理自工作多年以来遇到的所有 Git 问题汇总,之前都是遗忘的时候去看一遍操作,这次重新整理了一下,发出来方便大家收藏以及需要的时候查找答案。

    coder_koala
  • Git从入门到速成

    Scott_Mr
  • Git从入门到速成

    Scott_Mr
  • 收好这份 Git 命令应急手册,关键时刻可保你一命

    这个网站整理了一些 Git 新手在使用 Git 时常会遇到的各种突发状况,并贴心的给出了应对方案。

    GitHubDaily
  • 如何帮助女神处理Git使用的问题

    这个网站上面整理了一些 Git 新手在使用 Git 时常会遇到的各种突发状况,并贴心的给出了应对方案。

    灵魂画师牧码

扫码关注云+社区

领取腾讯云代金券