-1

how do i update my local working copy of source code with current latest version of remote code?

This is the situation:

Suppose 2 people(A,B,C) are working on the project and they follows git flow..

There is master branch, and there is develop branch...everybody is pushing their updates to develop branch only..

Now A creates a feature branch (featureA) and does a commit and pushes it to remote.. B creates a feature branch(featureB) and commits and pushes it to remote.. A, and B continues their work in their remote branch... while C created a new feature branch(featureC) and completed it and finished the feature and merged it to develop

So how can A and B update their local code to get the work done by person-C?

Should a normal PULL will solve the issue?

Or should they specifically pull to the current feature branch? will VS-code automatically update the files after the PULL?

Or is some other combination of git commands?

Can some git expert please solve this dilemma?

Antonio Petricca
  • 8,891
  • 5
  • 36
  • 74
Boris
  • 103
  • 2
  • 10

2 Answers2

1

Here the commands (we states that User C merged into develop and pushed it).

User A and/or User B must:

git checkout feature/A # Obvious!
git fetch origin/develop
git merge develop

Or, if you want to review User C changes, so avoiding auto merge-commit, you should:

git checkout feature/A # Obvious!
git fetch origin/develop
git merge develop --no-commit

git diff

# ... review changes: accept or discard some of them ...

git commit # The commit message has been auto generated by the merge command
Antonio Petricca
  • 8,891
  • 5
  • 36
  • 74
  • suppose there is a user D, and he has created a feature branch named (feature-D)... and he made a commit...but he didnt finish that feature, he didnt merge it to develop.. then how can userA and userB and userC get his work into their current working copy of source code? @Antonio Petricca – Boris Jul 09 '22 at 11:12
  • 1
    thanks @Antonio Petricca for your help... really appreciate it – Boris Jul 10 '22 at 03:44
1

The trick here is to realize that branches—or more precisely, branch names—don't really matter. All that matter are the commits. But there are two problems:

  1. We (humans) use branch names to find the commits.
  2. Branch names are specific to each Git clone.

What I mean by item 2 here is straightforward: if you and I both clone some repository (e.g., https://github.com/git/git), you get a master or main, and I get a master or main. But in fact, if you go look at https://github.com/git/git/branches you will see that they have six branch names: master and main (which are essentially the same thing: the Git project is just very traditional here so they are keeping the old name from 2005 around for the next 100 years), plus (in alphabetical order) maint, next, seen, and todo.

Now, why is it that if they have six names, we only get one when we run git clone? The answer is simple: because our branch names are ours, not theirs. Our git clone creates just one branch name in our new clone. If our git clone did not create a new branch name, we would have no branches at all! Zero, zip, zilch, 0, none. Technically we don't actually need any branch names. The only reason we might want a branch name in the first place is if we want to make a new commit. Our new commit(s) need name(s) by which we can find them. Git itself uses commit hash IDs—those big ugly strings of letters and digits like 30cc8d0f147546d4dd77bf497f4dec51e7265bd8—to find the commits. Git gives us names, such as branch names, tag names, and remote-tracking names, so that we (humans) aren't forced to memorize hash IDs.

You have actually asked two different questions here, probably without realizing it:

  1. how [do I] get remote updates?

and:

  1. how do i update my local working copy of source code with current latest version of remote code?

The answer to question 1 is much simpler: you use git fetch. I'll put off question 2 for a separate section below.

The git fetch command needs one argument or parameter: where should it go to get commits? We normally use what Git calls a remote to do this:

git fetch origin

means Look up the name origin. You will find a stored URL. Use the stored URL to call up some other Git software and connect to some other Git repository. Have them list out their branch names and other names and all the commit hash IDs associated with these names. Using the hash IDs, bring over into my repository any commits they have that I don't have. Then ... (we'll come back to the then part in a moment).

The process of fetching commits works based on the hash IDs. Every commit has a unique hash ID. When you make a new commit, it gets a new number1 that has never been used before. That "uses up" the hash ID that you get: no other Git software, anywhere, in any repository, can use that number ever again,2 unless it is to mark that particular commit. That's how Git repositories share commits: the same commit has the same number. That's really all there is to the sharing part: somehow, magically, Git can assign a unique number as a hash ID for a unique commit, and every Git implementation agrees that that's the right number.

So: you run git fetch origin, your Git reaches out to some other Git over at origin, and you get their commits. Now you have their commits—and now you need some kind of name to remember the hash IDs. This is where remote-tracking names come in.3 Your own Git software takes each of their branch names and changes them into remote-tracking names. If I run git branch -r in my clone of the Git repository for Git, I get:

$ git branch -r
  origin/HEAD -> origin/master
  origin/main
  origin/maint
  origin/master
  origin/next
  origin/seen
  origin/todo

That's one remote-tracking name for each of their branch names, plus the special "symbolic ref" origin/HEAD, which I'll just ignore here.

My Git software, on running git fetch origin, will obtain from their Git all of their new commits—I already have all of their old commits—and will update my remote-tracking names so that my names remember their branch names and commit hash IDs. So my remote-tracking names work, for me, somewhat like their branch names work for them.4

Once you've (successfully) run git fetch, using the remoteorigin or bob or boris or whatever name you choose to store the URL for "their Git"—you have their commits, found in your clone via origin/main or bob/main or boris/main or whatever.


1While hash IDs have letters in them as well as digits, they're really just very large numbers expressed in hexadecimal.

2This is technically impossible to maintain forever, and someday Git will break, but the sheer size of the hash ID puts that day very far in the future (we hope), and other things help out as well (we hope).

3Git documentation calls these remote-tracking branch names, but the word branch in there is not doing much if any good, and is doing some damage. Using the shorter phrase is, in my opinion, an improvement.

4This is why Git sticks that extra word branch in there. But they don't actually work like branch names for me, which is one reason I say to leave that extra word out. They only do one of the things that branch names do, and tag and other names do that too. Why not just call these "remote-tracking names"? (We could call them "reflections" or something, but I worry that that's getting too far away from existing Git terminology. But this is what they are: they "reflect" (or "mirror") the names that my Git saw in their Git, the last time my Git called up their Git.)


"Checking out" vs "merging"

Let's visit your second question now:

  1. how do i update my local working copy of source code with current latest version of remote code?

The word update is doing some heavy lifting here. What, precisely, do you mean by update?

Git stores commits. Each commit, besides being found by its hash ID, stores two things: a full snapshot of every file, like an archive (tar or WinRAR or zip or whatever), plus some metadata. The metadata give you information about the commit itself: who made it, when, and so on, for instance. The snapshot gives you a permanent archive of all the files. Both parts are 100% read-only—no part of any existing commit can ever be changed5—and you can discard your current checkout at any time, if you wish, and replace it with any other commit.

If you just want to do that, you first need to discard or commit any work you've done that you have not yet committed. This is because the working area—the place where you do your work, where files are ordinary read/write files that live in ordinary folders that your computer can work with—is not in the repository.6 You're about to tell Git to overwrite it, to rip out all the files from this commit and to go use a different commit.

Then, once git status says nothing to commit, working tree clean, you're ready to switch to some other commit. Simply give git switch --detach the name or raw hash ID of the commit you want to view:

git switch --detach boris/branch-a

and now you have that commit in your working tree.

Note that you don't have a branch. You are now in detached HEAD mode, where you can look at and use the commit. You can even make new commits, but if you do so, Git isn't saving the hash ID in a branch name. If you plan to make new commits, it's probably wise to create a new branch name now:

git switch -c newbr

and now you're on your own branch, named newbr, using this same commit. (Multiple names—branch names, tag names, remote-tracking names, and so on—can all select the same commit, and this is the case now: both the remote-tracking name and the branch name newbr select this commit.)

But: What if you don't want to just use their commit, but rather combine their commit's files with your own files? In this case, you probably want git merge, or perhaps some other action such as git rebase. These kinds of commands are useful for combining work.

The choice of command for combining work is up to you. Different people like to use different methods. You must choose which method you want, and then learn which Git commands implement that method. This leads us to your last Git question:

  1. Should a normal PULL will solve the issue?

5This is required for Git's magic unique-numbering trick to work. If you use the hash ID of some commit to extract the commit, then make any change at all, to the snapshot or metadata, and write the result back, what you get is a new commit with a new and different hash ID. The old commit continues to exist. So you literally can't change a commit. Not even Git can do that. Any change results in a different object.

6The "repository proper" is in the .git directory. This is where Git stores its databases and ancillary files. The area in which you do your work, called the working tree or work-tree, is not in the .git directory. Instead, in a sort of inversion, the .git directory is normally a hidden folder in the top level of the working tree. Be careful not to wreck the contents of this .git folder as your OS doesn't know how to coordinate closely with Git: you must use Git commands to update things in the .git folder, unless you know exactly what you're doing.

For the same reason, never put the .git folder in a cloud-synchronized storage area: most cloud-sync software doesn't cooperate with Git (I don't know of any that does, though having some do it would certainly be technically possible). Software that assumes that files within .git are used by humans will mess with Git, which is not a human.


About git pull: don't use it yet

What git pull means is:

  1. run git fetch; then
  2. run a second command to do something using the fetched commits.

The second command that git pull runs is usually git merge, unless you tell Git that it should be git rebase.

The precise way that git pull runs this second command is complicated. Since you're not sure yet which second command you want in the first place, don't drive a boat a few kilometers out to sea and then dive in without a life-jacket by running git pull. First learn to swim in shallow fresh and salt water (run the individual commands and experiment with their behaviors), then learn to drive a boat (learn the git pull command itself) and try scuba diving or whatever. The pull command has a lot of bad behaviors that exist because it was one of the earliest Git commands ever and was written before remotes (like origin) even existed. It therefore encodes a whole bunch of bad ideas, that it continues to support for the same kind of reason that the Git project still uses the name master.

(A bunch of defaults have changed since I started with Git 1.5 or so, and it is a lot better now than it was then. But it's still messy. Learn from others' mistakes: start with git fetch, git merge, and git rebase.)

torek
  • 448,244
  • 59
  • 642
  • 775
  • thank you very much @torek for giving such a detailed explanation.. i really appreciate you deciding to spend this much time to help me... – Boris Jul 09 '22 at 21:58
  • suppose there is a user D, and he has created a feature branch named (feature-D)... and he made a commit...but he didnt finish that feature, he didnt merge it to develop.. then how can userA and userB and userC get his work into their current working copy of source code?.. when i pull and merge code will VS-code automatically update the already open project file contents? – Boris Jul 09 '22 at 21:59
  • 1
    As above: run `git fetch` using a remote that will connect to a repository in which user D made his commit, or to which he has delivered his commit (either suffices). You now have his commit. Find it (by remote-tracking name or hash ID) and use it or incorporate it as you see fit. – torek Jul 09 '22 at 22:22
  • 1
    (I cannot answer questions about VSCode. Note that VSCode is not Git, and has numerous plug-ins, each of which work differently, and some of which conflict. Ask VSCode questions in a VSCode forum.) – torek Jul 09 '22 at 22:23