Reputation: 1885
I'm surprised I couldn't find anything about that...
In short, my question is if is there a way to avoid the intermediate file changes between the following two commands, if after the following two commands the file content is exactly as was before?
git checkout dev
git pull
The motivation is (Solution that meets only one of the motivations is also better than nothing):
This is a very common scenario when I'm coming back from a feature branch to master after merging origin/feature into origin/dev using a remote source control server.
I would expect that performing git fetch origin dev
before will solve this but it doesn't. Also I found some answers like this which talks about grouping the commands together for easiness, but didn't targetted the file-changes issue.
Upvotes: 16
Views: 19454
Reputation: 1143
git fetch origin master:master
Replace master
with the branch you want to update. (In the OP's scenario, it will be git fetch origin dev:dev
)
This command only works for a fast-forward merge.
Once the local branch is updated with the remote changes you can switch to the desired branch without causing file changes.
References:
Upvotes: 14
Reputation: 487785
There's a way to do this, using git worktree add
. Be sure your Git is at least 2.5 (so that it has git worktree
) and preferably at least 2.15 (fixes a fairly severe bug with added worktrees; without the fix, an added worktree should not be used for more than about two weeks, in general).
Your IDE may be incompatible with git worktree add
; I avoid IDEs so cannot say which ones cooperate with it, and which do not.
Assuming you have a Git version that supports added worktrees, use git worktree add
to create your dev
branch, and leave the main worktree on the master
branch. Alternatively, use added work-tree for the main (master, or whatever) branch, and the main work-tree for the dev
branch. Remember that Git enforces that each work-tree have a different branch checked-out.
Stop using git pull
. (This is not strictly necessary, but I recommend it.)
To update your repository from the server, use git fetch
—with no additional arguments—at any time, from either work-tree. This obtains any new commits they have that you don't, and updates your origin/*
remote-tracking names.
To update your master
branch, enter the master
-branch work-tree and, on the command line, run git merge
or git merge origin/master
. (Run git fetch
first, if you have not done so recently, so as to have an up-to-date origin/master
.)
To update your dev
branch, enter the dev
-branch work-tree and, on the command line, run git merge
or git merge origin/dev
. As before, if you have not run git fetch
recently, you may want to do that first so that your origin/master
is up to date.
Your IDE may or may not be able to achieve what the command line does, here. Depending on the IDE, perhaps it will work to run two copies of it, one in each work-tree.
Remember, all git pull
does is run git fetch
and then git merge
(or git fetch
and then git rebase
). It's the git checkout
that is messing with the time-stamps on your work-tree files. Git doesn't really use or need the work-tree: that's for you. Running git checkout
replaces the files in the work-tree with those from the other commit, while also replacing the files in the index; the index copies are the ones Git uses and cares about.
Git replaces the work-tree files because it assumes you need the ones from the branch you are switching-to. Switching back, of course, updates those work-tree files yet again. So now various files have been updated twice, and need rebuilding.
When you add a new work-tree, Git actually adds a group of three items:
HEAD
for the new work-tree, to remember what commit and/or branch are the current ones in the new work-tree;This work-tree is simply a directory (or folder) that is outside the main repository work-tree. For instance if your main repository is in ~/work/project
you could move it to ~/work/project/main
and create ~/work/project/dev
to hold the dev
-branch work-tree.
Fundamentally, though, the problem is simple: When you use git checkout
, git replaces both index and work-tree contents as needed. So you need to stop using git checkout
. If you need both work-trees, make two separate work-trees.
If your Git is too old to support work-trees, make two clones. Everything else works the same except, of course, that the two clones do not share branches.
Upvotes: 1