git

git使用小技巧

Posted by 御风 on 2017-10-18

现在代码管理工具基本是git的天下了,除了一些很保守的公司还在用svn,其他基本都是自己搭一个gitlab,下面总结一下git实用技巧。

  1. 本地目录如何关联远程仓库?
1
2
git remote add <主机名> <网址>
git remote add origin git@github.com:wulv/scripts.git

一个本地仓库可以设置好几个远程仓库,比如你在gitlab有一个仓库,你也想把它推送到github去,可以使用:

1
2
3
4
5
6
7
8
9
git remote add github git@github.com:wulv/scripts.git

git push <远程主机名> <本地分支名>:<远程分支名>
git push github master:master
// 可以使用-u指定默认主机名
git push -u github master

git pull <远程主机名> <远程分支名>:<本地分支名>
git pull github master:master

同理,也可以手动设置本地分支与服务器分支的对应关系,比如我本地叫next分支,服务器叫feature分支,可以使用以下代码设置

1
git branch --set-upstream next origin/feature
  1. 如何让推送不用每次输密码?

使用ssh的方式,在GitHub的https://github.com/settings/keys设置一下SSH keys,关于SSH keys生成的问题查看https://help.github.com/articles/connecting-to-github-with-ssh/

  1. 如何回退一个文件?
  • 如果还没git add,使用ctrl + z吧,如果想回到没添加文件之前,使用 git clean -df
  • 如果已经git add,还没commit,使用git checkout -- files
  • 如果已经git commit,还没有push,使用git reset <commit> files
    • --soft:软回退表示将本地版本库的头指针全部重置到指定版本,且将这次提交之后的所有变更都移动到暂存区。
    • --hard:不仅仅是将本地版本库的头指针全部重置到指定版本,也会重置暂存区,并且会将工作区代码也回退到这个版本
  • 如果已经git push了,使用git revert <commit>,恢复一个指定提交。此次操作之前和之后的commit和history都会保留,并且把这次撤销作为一次最新的提交。

git revert 和 git reset 的区别:

  1. git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit。

  2. git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。

  3. 已经添加到仓库的文件如何忽略不提交?

将文件添加到.gitignore,然后git rm files

  1. 当前分支还没开发完,突然需要到另外一个分支修复紧急bug如何处理?

首先确认当前分支能否提交,可以提交的直接commit,但一般代码没写完不好提交,就储藏工作目录与暂存区的状态到堆栈中git stash,切换到另外一个分支修复bug后,切回本分支,git stash pop

  1. 仓库依赖另外一个仓库?

比如本博客仓库依赖一个主题,但我想对这个主题进行一些修改,首先我从原作者的主题仓库fork一份到我自己仓库,做一些修改,以后原作者有更新我还是想pull过来,这样既享受原作者的更新,又可以自己修改一些特殊的需求。将fork下来的仓库与原作者的仓库关联起来:git remote add remote-name remote-url,然后更新时拉取指定远程仓库指定分支到本地仓库指定分支:git pull remoterepository branchname[:localbranch]

在父仓库里添加子仓库:git submodule add repository-url dir,这个时候会出现一个.gitmodules文件,这是一个配置文件,保存了项目 URL 和你拉取到的本地子目录。如果克隆了一个带子模块的项目,你必须运行两个命令:git submodule init来初始化你的本地配置文件,git submodule update来从那个项目拉取所有数据并检出你上层项目里所列的合适的提交。

submodule与subtree是有区别的,区别在于,submodule其实只是相当于引用了子仓库,你在git clone的时候是不会下载submodule的代码的,必须手动执行git submodule update,更新的话,直接进入对应目录,执行git pull,而subtree则是直接把子仓库下载到父仓库,当成一个正常目录,更新的话相当于重新下载一遍对应仓库指定分支的某次提交。

  1. 如何查看提交记录?
  • git log:查看提交记录
  • git log --oneline:查看提交记录,以oneline形式显示,只显示一行,显示的内容时提交hash的前7位与提交消息
  • git log -p -times:表示查看最近times次提交改变的内容
  • git log --author="<pattern>": 查找某位作者的提交记录
  • git log --grep="<pattern>":搜索有某字符串的提交记录
  • git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit:图形化显示提交历史
  1. 比较两次提交或分支的差异?
  • git diff:查看工作目录与暂存区的差异
  • git diff --cached [<commit>]:查看暂存区与指定提交(默认是HEAD)的差异
  • git diff <commit>:查看工作目录与指定提交的差异
  • git diff <commit>:查看工作目录与指定提交的差异
  • git diff <commit> <commit>:查看两次指定提交的差异
  • git diff branchname:查看工作目录与指定分支的差异
  • git diff branchname branchname:查看两个指定分支间的差异

上面的所有操作后面都可以加上-- dir表示查看该目录下面的差异,在后面加上>patchname.patch表示将差异生成补丁,patchname是补丁的名字。

  1. 有两个稳定版本,将其中一个版本的功能应用到另外一个版本?

比如某仓库有VIP版和普通版,分别在两个分支开发,普通版更新了一些功能,VIP版也希望将更新应用到分支,但又不能直接将普通版的分支merge过来,这个时候使用:git cherry-pick <commit id>将另一个分支上面的指定提交应用到当前分支上。

  1. 提交信息写错了怎么办?

比如git commit -am ‘单词拼错’,可以使用 git commit --amend -m“新提交消息”重新设置提交信息。同理如果你本次提交新加了几个文件,你忘了git add,而直接提交了,也可以执行git add xxx,然后git commit --amend --no-edit--no-edit 表示提交消息不会更改,在 git 上仅为一次提交。

那如何合并多次提交呢?比如一个小功能,你提交了几十次,这样会造成很多无意义的提交。这个时候可以使用git rebase -i HEAD~4来合并前面4次提交。

  1. 为什么git pull也会有一次merge提交?

有时候你从master拉了一个分支出来,开发了一周,这期间master分支已经有别人提交了代码进去,你在push之前肯定需要先pull一下,按照 Git 的默认策略,如果远程分支和本地分支之间的提交线图有分叉的话(即不是 fast-forwarded),Git 会执行一次 merge 操作,因此产生一次没意义的提交记录。git pull = git fetch + git merge。
解决方式:

  1. 使用git pull --rebase = git fetch + git rebase origin/master

  2. git pull --ff-only = git fetch + git merge --ff-only origin/master

  3. 分支太多,如何批量删除一个星期之前分支?

1
2
3
4
5
6
7
#!/bin/bash
#删除一个星期之前的所有本地分支
for k in $(git branch | sed /\*/d); do
if [ -n "$(git log -1 --before='1 week ago' -s $k)" ]; then
git branch -D $k
fi
done


支付宝打赏 微信打赏

赞赏一下