First: be careful with the word pull when talking about Git, because git pull is a Git command that means: run git fetch, then if that succeeds, run a second Git command, usually git merge.  To "pull" a branch therefore means to run git fetch and then run git merge with a commit based on the result.  Well, that is, unless you've configured or instructed git pull to use a different second command, in which case, it means something different—but it still starts with git fetch.
(In scripts, you should often avoid git pull, because the way it behaves depends on the user's configuration.  You have to decide whether you want to change what your script does based on the user's configuration.)
All that said, what git checkout does is ... a little bit complicated.  While it sometimes does do a simple kind of pattern matching, it does not invoke git fetch.  That means you shouldn't think of it as pulling anything.
To simplify things, let's talk only about the command git checkout X, for some X.  (There are about four or five other kinds of git checkout, depending on how you count.)  For this one particular kind of git checkout, Git goes through a four-step process to figure out what you want, and then do that:
- Is - Xan existing (local) branch name?  That is, if you ran- git branch, would it list- Xas a branch?  If so,- git checkout Xmeans to check out that (existing) branch.  Afterwards,- git statuswill say- on branch X.
 
- If - Xis not an existing branch name, can- Xbe resolved to a Git commit hash ID?  To answer this question for yourself, you can run- git rev-parse X^{commit}.1  If this works,- git checkoutwill check out that commit as a detached HEAD.  Afterwards,- git statuswill say- HEAD detached at X, or in very old version of Git,- HEAD detached at hashfor some hash.
 - The checkout itself will begin by printing, e.g.: - $ git checkout v2.18.1
Checking out files: 100% (1517/1517), done.
Note: checking out 'v2.18.1'.
You are in 'detached HEAD' state. You can look around, ...
 - (though some of this changes depending on your internationalization locale setting, e.g., the messages might be in French). - The example above could be what you're getting; it's what I got when using - git checkout v2.18.1to name a tag in the Git repository for Git.
 
- If both 1 and 2 fail, - git checkoutgoes on to try what Git calls DWIM mode.  It now lists all the remote-tracking names, which you can see for yourself using- git branch -r:
 - $ git branch -r
  origin/HEAD -> origin/master
  origin/maint
  origin/master
  origin/next
  origin/pu
  origin/todo
 - This is also a case you might be getting.  Note that each of these names has a pattern: each one starts with - origin/, which is the name of the remote in this particular Git repository for Git:
 - $ git remote
origin
 - This particular repository has only one remote.  You can have more than one remote, using - git remote addto add more.  In that case, you'll often have multiple different remote-tracking names.  For instance, if I were to add remotes named- aliceand- bob, I might end up with remote-tracking names- alice/master,- alice/dev,- bob/master, and- bob/feature-1234(in addition to my usual- origin/*ones).
 - For case 3, Git will take the name you gave it and look through all your remote-tracking names.  For each one, Git will take off the remote's name and the slash—for instance, - origin/masterbecomes just- master,- alice/masterbecomes just- master, and- bob/masterbecomes just- master.  The same goes for- alice/devand- bob/feature-1234.  If exactly one of these stripped-down names match the argument you used, Git selects this "DWIM mode" checkout option.
 - Note that if two or more names match—e.g., if I have both an - origin/devand an- alice/devand I type- git checkout dev(and we're in case 3 in the first place)—then "DWIM mode" fails and we move on to case 4.   I'll describe "DWIM mode" the rest of the way in a moment; for now, let's move on to case 4.
 
- Having failed at all three of the earlier cases, - git checkoutnow tries to use- Xas a path name.  If that works, it does the equivalent of- git checkout -- X.  This extracts the copy of file- Xfrom the index and uses that to overwrite the copy of- Xin the work-tree.
 
If all four cases fail, git checkout itself fails.  Note that if cases 1, 2, or 3 succeed at resolving the name X, but the rest of the operation fails for some reason, git checkout does not try any of the later cases.  The four steps above are done only to figure out what X should mean in order to decide whether to do a commit checkout (cases 1 and 2), a name-creating checkout (case 3), or a file checkout (case 4).
Branch-creating checkouts, including DWIM mode
The git checkout command has the ability to create a branch.  The most basic way to create a branch in Git is to use git branch.  Here, you pick some existing commit—often the tip commit of some existing branch—and tell git branch to make a new name that identifies the same commit as the existing name:
git branch new-branch a123456
(where a123456 is the commit hash you want), or:
git branch new-branch master
(where you let the name master resolve to the commit hash, then create the new name new-branch, pointing to that same commit).  If the name master currently resolves to the hash ID a123456, these two commands accomplish the exact same thing, which we can draw as:
...--o--o--o   <-- master, new-branch
Now all the commits that end at a123456 are on both branches.
Having made a new branch, you can then git checkout that branch:
git checkout new-branch
That puts you on new-branch while checking out commit a123456 (again, assuming master meant a123456—use git rev-parse master to see the actual hash ID).
To make this all a bit easier, git checkout offers you the ability to:
- create a branch name, and then
- switch to it (and its commit)
as a single command.  Typically, to do this, you do the same thing you do with git branch: you pick out a commit, maybe using an existing branch name to do that, then you say: Make a new name, make it identify that commit, and check it out.  So you could write:
git checkout -b new-branch a123456
to do the same thing we did with git branch followed by git checkout.  That's not a huge savings, but it's convenient.  It's especially convenient when you want to create the new branch from the same commit as whatever branch you're on right now, because then you can just run:
git checkout -b new-branch
and the new branch's commit is the same as the current commit.
But there's more to set for a branch.  In particular, any branch can have one upstream.  The upstream of a branch helps you out a bit (or helps Git help you out a bit) when you run git status, git push, and various other Git commands.  See this answer for more—but in short, you might want to run:
git branch --set-upstream-to=origin/dev dev
after creating your own dev from the commit identified by the name origin/dev.  If you did this the hard way, it would be:
git branch dev origin/dev
git branch --set-upstream-to=origin/dev dev
git checkout dev
or:
git branch dev origin/dev
git checkout dev
git branch --set-upstream-to=origin/dev
(you get to leave out one copy of the name dev here as git branch assumes you mean to operate on the current branch, which you set with the git checkout command).
If you use git checkout dev when you don't have a dev, and invoke git checkout's DWIM mode, Git assumes that you meant to do all three of these operations.  So a simple:
git checkout dev
does all three, and that's a pretty significant savings: you don't have to type origin/dev at all, because Git figured that out on its own, and you only have to type dev once.
1There a few exceptions for particularly complicated strings.  For instance, if we set X to the literal stringHEAD:/fix and try to use git rev-parse X:/fix^{commit}, we'll get the wrong answer.  To get the right answer in all cases requires two steps:
hash=$(git rev-parse $X) || ... handle error; do not proceed ...
hash=$(git rev-parse $hash^{commit}) || ... handle error ...
If these two steps both succeed, $hash contains the hash ID of the commit that git checkout would check out.