i'm a little confused pulling from remote branches while being on another branch. for example, if I change to main, then pull:
git checkout main
git pull
I get updated with the remote changes. good.
but, if i'm on another branch and I want to update main without changing to main, I always get results that confuse me (I don't really get the updates unless I change to main).
let's say i'm on branch 'feature', and I try:
git pull main
or git pull origin/main
or git pull origin main
, I get something I didn't expect, but never the updated branch.
a specific example, running git pull origin main
while being on branch feature
, will output this:
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), done.
From <repo name>
* branch master -> FETCH_HEAD
8a84194..d00d469 master -> origin/main
Updating 340286a..d00d469
Fast-forward
But when I change into main git checkout main
, then git pull
, I get the actual updates:
git pull
Updating 8a84194..d00d469
Fast-forward
Pipfile | 2 -
Pipfile.lock | 1583 --------------------------------------------------------------
setup.py | 2 -
3 files changed, 863 insertions( ), 724 deletions(-)
Can you please help me understand what am I getting wrong? Thank you!
Roy.
CodePudding user response:
First, you literally can't merge into anything other than the branch you have checked out right now.1
Second, what git pull
means2 is:
- run
git fetch
, then - run a second Git command.
That second Git command is your choice, but without making an explicit choice, you generally get git merge
. So pull
= fetch
merge
, and merge
only works on the current branch.
(Your other normal option is git rebase
. But git rebase
has this same constraint of only working on whatever branch you have checked out right now. It too has some footnotes because Git can't stand to leave anything simple, but again we'll ignore these.)
So, to a first approximation:
git pull
means pick the upstream for this branch, and then pull into this branch (we'll define upstream later);git pull origin main
means something complicated, which I'll describe later; andgit checkout main
and thengit pull
means pick the upstream formain
, and pull intomain
since "this branch" ismain
.
Unless you're already on main
, none of these three commands can be exchanged for any of the others.
1There are a number of caveats to this—special cases that seem like merging, for instance, and upcoming future Git software that may eventually escape this constraint—but for now just take it as Truth.
2In the old days (as in before 2015, before Git 2.6), git pull
was literally a shell script that ran git fetch
, and then ran the appropriate second command. The C version is faster and more efficient, but the logic is still the same internally.
The necessary background, without which Git never makes any sense
You probably use Git to maintain a bunch of files. But Git isn't really about files. You also use branches, but Git isn't about branches either. In the end, Git is all about commits. It's true that commits contain files, and we use branch names to help us (and Git) find commits, but Git isn't about the files or branch names: it's raison d'être is the commit.
You therefore need to know what a Git commit is and does for you. Fortunately this part is pretty simple. A Git commit:
Is numbered. Each commit gets a unique hash ID. The hash ID is huge and ugly and random-looking, and impossible for humans to remember. It has to be, because it has to be unique: when you make a new commit, it has to get a number that has never been used before, and now that number can never be used again for any other commit.
(This part is mathematically impossible due to the pigeonhole principle, but by being huge, the hash IDs push off the inevitable failure well into the future, by which point we all plan to be dead, so that we don't care.