Posts in category “Git”

Git Tips: Remove tracking branches no longer on remote

My colleage Joe asked me tonight, "how to remove those branches that no longer exist on remote?"

In short, you have two options

  1. run git remote prune origin at times
  2. run git config --global fetch.prune true command to config your git to delete those branches every time when you run git fetch

I prefer the second option, how about you?

Reference

神奇且无害的REBASE

2014年底翻译了这篇文章,当时发表在GotGit 群组,搬过来留存一下

作者:Jeff Kreeftmeijer 发表于 2010-10-11 原文链接

大约一个月前, 以Git为主题我写了不少文章,始于@nvie 出色的git开发流程教你写出更好的提交注释,终结于强大的reflog和惊人强大的bisect 。你猜怎么着?我竟然忘记了介绍神奇的rebase

人们通常认为rebase是一种压合提交工具,但这并非它的看家本领。顾名思义,它的本职工作是变基(改变我们所做变更的基础)。

哦,忘掉那篇吓唬人的文章,只要清楚自己在做什么,根本不会产生什么恶果。

假设你正工作在一个名叫feature/login的新功能分支上,某个家伙实现了某样东西,并把他的代码push到了develop分支上。你需要那个东西,该怎么做?

可以把develop分支合并到你正在工作的分支,这会产生一些....乱七八糟的合并提交,不好。

也可以把我们需要的那个提交cherry-pick过来。不过经验表明虽然不是什么大问题,从一堆提交里找出需要拣选的提交,终究是个麻烦事。

Git的rebase指令允许我们先回退自己的改动(类似“倒带”),拉回另一个分支的所有变动之后(变基),在新的基础(HEAD)上“重放”我们的变更:

$ git rebase develop

First, rewinding head to replay your work on top of it...
Fast-forwarded feature/login to develop.

仿佛在拉回那些变更之前,我们什么也没做(我们所有的改动仿佛发生那些变更之后)。这非常好,是不是?我们还能在pull的同时变基(使用--rebase选项),这样的话我们甚至都不需要离开自己的工作分支。

##更小块的冲突

rebase让我们拥有干净的提交历史,即便在rebase的过程中发生冲突,它也是我们解决冲突的坚强后盾:

$ git rebase develop

First, rewinding head to replay your work on top of it...
Applying: feature/login
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging config/environment.rb
CONFLICT (content): Merge conflict in config/environment.rb
Failed to merge in the changes.
Patch failed at 0001 feature/login

When you have resolved this problem run "git rebase continue".
If you would prefer to skip this patch, instead run "git rebase
skip".
To restore the original branch and stop rebasing run "git rebase --abort".

由于rebase顺序重放每一个提交,冲突会以更小的块(更多的次数)出现,这有助于我们迅速理解冲突原因,更快地解决冲突。在解决冲突之后,只需git add冲突文件,然后输入下面的命令继续rebase过程:

$ git rebase --continue

##rebase 还是 merge

当我们工作于一个功能分支,发现需要 develop 分支上的所有变更时,我建议使用rebase。当我们的功能分支已经开发完成,应该使用 merge 把功能分支合并回 develop分支。这样我们能够记录下我们在何时把分支合并到 develop 主干,就是利用那个...我们前面说过的“乱七八糟”的提交。在这个时候,它真的不是乱七八糟的提交,确实不是。

在合并功能分支之前,我希望你使用rebase。这样我们方能保证自己的分支在合到并主干时仍然拥有干净的提交历史。

你用过rebase吗?你在何时使用 rebase 不用 merge?还是只用 rebase?你还害怕rebase吗?欢迎撰写评论留下你的想法,让我知道。

PS: 这篇文章虽然写于2010年,但写的清晰明快。我今天(2014年)把它翻译过来,希望能帮助到更多的人。rebase是一个很好的工具,只要你愿意了解它。

Git Tips

按最近提交的提交时间(DESC)列出本地分支

git branch --sort=-committerdate

太长记不住?运行下面的命令配置一个git命令别名,下次只需要敲 git brs 即可得到同样结果:

git config --global alias.brs "branch --sort=-committerdate"

解决git 命令行把中文文件名显示成 \343\200\212类似乱码的问题

git config --global core.quotepath off

将变更加入缓冲区,但不加入空白(空格、制表符或者换行符)的变更

git diff -w | git apply --cached --ignore-whitespace

Reference

git diff 时排除掉某些不想看的文件

git diff -- . ':(exclude)db/irrelevant.php' ':(exclude)db/irrelevant2.php'

删除远端分支

git push origin --delete branchname

嫌打字麻烦的,可以使用以下简写命令

git push origin :branchname

发现文件丢了不知道谁删的,比如 yarn.lock , 用下面这个命令

git log -p -- yarn.lock

设置总是push到远端的同名分支,从此再也不用如此麻烦的敲 git push -u origin theSameBranchName,你只管 git push 就好!

git config --global push.default current

从 git 2.37 版开始,我们可以用下面这个新设置更好的解决这个问题。它不仅起到类似上一个命令的作用,它还自动设置 track 到远端的同名分支。如果你的git版本比较新,使用这个设置更好。

git config --global push.autoSetupRemote true

解决 git diff 时出现讨厌的 ^M

git config --global core.whitespace cr-at-eol

Reference

更多的技巧请访问我的 GotGit 群组

A guide for git status change

状态标识

标志 含义
nul 文件已提交到版本库未做修改
?? untracked 新文件尚未 git add
A staged 已经 git add 但尚未提交
AM staged 未提交又做限新的修改,新修改尚未staged
MM 一些修改staged之后又做了新的修改,新修改尚未staged

状态转换指南

状态A -> 状态B 需要的操作
nul -> M 修改文件
MM -> nul git checkout HEAD file(s) OR git checkout -- file(s)
A -> ?? git rm --cached file(s)
M -> M git add file(s)
A -> AM git reset file(s)
A -> nul git reset file(s)
?? -> A git add file(s)
A -> ?? git rm --cached file(s)
A -> AM git add 之后再修改文件
AM -> A git checkout -- file(s)