惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

爱范儿
爱范儿
MyScale Blog
MyScale Blog
Recent Announcements
Recent Announcements
N
Netflix TechBlog - Medium
GbyAI
GbyAI
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
阮一峰的网络日志
阮一峰的网络日志
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
Visual Studio Blog
Martin Fowler
Martin Fowler
腾讯CDC
大猫的无限游戏
大猫的无限游戏
aimingoo的专栏
aimingoo的专栏
云风的 BLOG
云风的 BLOG
J
Java Code Geeks
WordPress大学
WordPress大学
P
Proofpoint News Feed
雷峰网
雷峰网
酷 壳 – CoolShell
酷 壳 – CoolShell
有赞技术团队
有赞技术团队
人人都是产品经理
人人都是产品经理
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Y
Y Combinator Blog

Steve Bennett blogs

Whenever: exploring times and places in film and books Alternative Earth: a procedurally generated map using vector tiles Host your own vector tile server on Glitch Building TinyMap: an itty bitty collaborative mapping tool You might not need PostGIS: streamlined vector tile processing for big map visualisations OpenStreetMap vector tiles: mixing and matching engines, schemas and styles 2015’s proudest moments Your own personal National Map with TerriaJS: no coding and nothing to deploy After the hackathon: 4 classic recipes OpenTrees.org: how to aggregate 373,000 trees from 9 open data sources Cycletour.org: a better map for Australian cycle tours Normalize cross-tabs for Tableau: a free Google Sheets tool 7 reasons to release that government dataset The Data Guru in Residence Chromecast in the real world: six casting workflows Web map projections: the bare minimum you need to know Multivariate binary symbol maps with TileMill. The Australian’s menacing editorial Cycletouring and OpenStreetMapping: a beautiful symbiosis One week of Salt: frustrations and reflections. Super lightweight map websites with Github Digital humanities for beginners: get started with the Trove API Trello Tennis Terrain in TileMill: a walkthrough for non-GIS types A TileMill server with all the trimmings Forget trying to remember your servers’ names! Anonymous longitudinal surveys with LimeSurvey Windows red cross errors scam What I learned at e-Research Australasia 2012 A pattern for multi-instrument data harvesting with MyTardis
Git: what they didn’t tell you
steveko · 2014-02-25 · via Steve Bennett blogs

Posted by on February 26, 2014


Credit:Tim Strater from Rotterdam, Nederland CC-BY-SA

Of all the well-documented difficulties I’ve had working with Git over the years, a few conceptual difficulties really stand out. They’re quirks in the Git architecture that took me far too long to realise, far too long to believe, or far too long to really grasp. And maybe you have the same problem without realising it.

Branch names are completely arbitrary


git branch -d master
git checkout develop -b master

There, I did it. I’m now calling the develop branch master. What you call this branch, and what I call it, and what your Github repo calls it, and what my Github repo calls it just don’t matter. Four different names? No problem. There are some flimsy conventions that Git half-heartedly follows to link two branches with the same name, but it gives up pretty easily.

Remote branches are local

I have very frequently fallen into this trap:

$ git diff origin/master
$

No differences, so my branch must be in sync with Origin, right? Wrong. What is true is my branch is in sync with the local copy of Origin. If you don’t run git fetch, then Git will never even update its local copies.

Technically, Git has always been upfront about this. The Git book opens the section on remote branches:

Remote branches are references to the state of branches on your remote repositories.

But it’s counterintuitive, and so I keep messing it up. I keep hoping (and assuming) that Git will one day include an auto-fetch option, where it constantly synchronises remote branches

‘Detached HEAD’ mode is fine

Here’s the message that we have seen many times:

Note: checking out ‘origin/develop’.

You are in ‘detached HEAD’ state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b new_branch_name

This scary looking message threw me off for a long time, despite the fact that it’s actually one of Git’s most helpful messages – it tells you everything you need to know.

It boils down to this: you can’t make a commit if you’re not at the top of a branch. The two most common situations that cause this are:

    1. Checking out a remote branch. You should do this:

      git checkout origin/develop -b mydevelop
      or even, if you want to abandon your branch completely:
      git branch -d develop
      git checkout origin/develop -b develop
  1. Checking out a commit in the middle of a branch, like:

    git checkout a8e6b18

    Usually in this case you just want to look at it, so you can just ignore the message.

There’s nothing special about ‘git clone’

For a long time, I thought that ‘git init’, ‘git pull’ and ‘git clone’ somehow created repositories that were different, even if they ended up with the same commits in them. It’s hard to recreate my state of mind, but I spent a long time trying to salvage certain directories on disk when I should have just abandoned them.

Similarly, there is no difference between:

  1. git clone http://github.com/stevage/myrepo
  2. git init
    git remote add origin http://github.com/stevage/myrepo
    git pull origin master

Well, in the second case Git’s a bit confused about which local branches map onto which remote branches, so you have to be more explicit or fix it with some configuration option.

Don’t call any remote ‘origin’

Credit: Chevassu (GFDL)

For some reason, Git encourages you to call the source of the first clone “origin”. I have found this very confusing and ultimately very unhelpful. Let’s say you’re working on a project called widget, and you fork it in Github so you can work on it. You will want both remotes accessible locally, so you will probably do one of these:

  1. git clone http://github.com/stevage/widget
    git remote add widget http://github.com/widget/widget
  2. git clone http://github.com/widget/widget
    git remote add mine http://github.com/stevage/widget

So you either have remotes called “origin” and “widget”, or remotes called “origin” and “mine”. But on the next project, you might make the opposite choice, and soon you really don’t remember what “origin” means.

My tip: never name any remote “origin” ever. Name them all after their Github username.

  1. git init
    git remote add widget http://github.com/widget/widget
    git remote add stevage http://github.com/stevage/widget
    git fetch --all
    get checkout stevage -b master

You will never understand “git reset”‘s options

The difference between “git reset”, “git reset –soft” and “git reset –hard” is beyond your comprehension. And you probably wanted “git checkout” anyway.

Rule of thumb:

  • If your directory is FUBAR: git reset –hard
  • If you just want to throw away changes to one file: git checkout file
  • In all other cases, google it.