Local Project Basic Steps

Basic Stepsuseful snippetsPull from Master / Mergenvm commands / usageResolving Conflicts - Package.json / Package-lock.jsonBreakdown - Expanded

Know your versions:

REACT: “^16.13.1”
NODE: 14.16.1 / NPM: 7.11.2

asdf – nvm replacement

Use NVM to control node / npm versions

Do you need access to a npm private package:

GIT/OPENING PROJECT::

get files from a branch and create folder:


    git clone -b nameOfRemoteBranch https://urlofgitrepo.com/with/files.git NewLocalFolder

enter folder:

cd NewLocalFolder

make a new branch for yourself + set it to track origin (upstream branch):

$ git checkout -b MyNameIsLocalBranch origin/working-on-remote-branch

  Branch MyNameIsLocalBranch set up to track remote branch working-on-remote-branch from origin.
  Switched to a new branch 'MyNameIsLocalBranch'

Add to GitIgnore


echo NameOfFileToIgnore >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global


check your node version:

node –version

install or use correct node for project:

nvm install 14.16.1

or

nvm use 14.16.1

Lock version in .nvmrc

ln -s .nvmrc .node-version

Check .nvmrc

ls -la

install dependencies:

npm install

launch dev:

npm start

view dev site locally:
https://localhost:3000

Hack Hack

do some coding …

Ready to add / commit / push to remote?

TO REMOTE pt1: STATUS see what you have changed – provides a list:

 git status

TO REMOTE pt2: ADD add changes into git to be committed:

git add filenamefromstatuslist

(can do them one at a time or use git add .)

TO REMOTE pt3: COMMIT once you add them – commit them:

git commit -a -m “a note about what these changes are for”

TO REMOTE pt4: PULL get tip of remote even + integrate remote into local branch:

Different Named Branches Need Pulling

Pull performs a merge on the retrieved changes, you should ensure that your local work is committed before running the pull command.

Before you begin to push – you have a local branch with a different name (MyNameIsLocalBranch) than the remote (working-on-remote-branch):

In order to push your MyNameIsLocalBranch to another branch, you may need to merge the remote working-on-remote-branch branch to your current local branch MyNameIsLocalBranch.

In order to be merged, the tip of the remote branch cannot be behind the branch you are trying to push.

Before pushing, make sure to pull the changes from the remote branch and integrate them with your current local branch.

You may also have to resolve conflicts between your branch and origin

In IntellIJ – choose:

GIT -> Resolve Conflicts or select VCS -> GIT -> Resolve Conflicts, if no conflict dialog module pops open



$ git pull origin working-on-remote-branch (will pull working-on-remote-branch from remote)

$ git checkout MyNameIsLocalBranch (to be sure you are on correct local branch)

$ git merge origin/working-on-remote-branch (merge remote into MyNameIsLocalBranch)


TO REMOTE pt5-FNL: PUSH

Check what you have set up

git remote show origin

1st push from local to remote

git push --set-upstream origin MyNameIsLocalBranch:working-on-remote-branch 
shorthand: git push -u origin MyNameIsLocalBranch:working-on-remote-branch 

once origin is configured:


$ git push origin MyNameIsLocalBranch:working-on-remote-branch  (git push origin local-name:remote-name)

Check what is going on in gitland and launch local version:

Update/pull from remote repo when when you start a new day cd into project – pull from origin the remote branch:

git pull origin working-on-remote-branch
nvm install 14.16.1
git status
npm install
npm start

You can have 2 origins


$ git remote add spiffy-origin https://url/of/new/remote/origin/from/gitlab etc.

then when it is time to push:


$ git push spiffy-origin 

setting special config git settings


git remote set-url --push origin no_push

what this does is to disable a push to “origin” – so only “spiffy-origin” will work on this site moving forward

  • Pull: git pull origin original-branch-name
  • Push: git push spiffy-origin spiffy-branch-name

setting up the push


git push --set-upstream spiffy-origin dit-dah-spiffydesign:dit-dah-spiffydesign

or 

git push --set-upstream 2nd-origin localbranchname:remotebranchname

  • spiffy-origin: The remote repository you added at https://spiffydesign.com/cubik_set/dit-dah.click.git.
  • dit-dah-spiffydesign:dit-dah-spiffydesign: This specifies pushing your local dit-dah-spiffydesign branch to the same branch name on the remote (spiffy-origin)



https://stackoverflow.com/questions/49715421/does-the-order-of-git-merging-matter

Does the order of Git merging matter?

Suppose I have two branches, A and B. Do the following properties hold?

  • Merging A into B conflicts if and only if merging B into A conflicts.
  • The contents of my files after merging A into B is the same as the contents of my files after merging B into A.

 

  • Assuming there are no conflicts, the content of the merge is the same.

     

    @Maroun That is my hunch as well, but is that actually documented somewhere? Or, does it logically follow from the known properties of the merging algorithms?


cmaster's answer is correct, with caveats. Let's start by noting these items / assumptions:

  • There is always a single merge base commit. Let's call this commit B, for base.
  • The other two inputs are also single commits. Let's call them L for left / local (--ours) and R for right / remote (--theirs).

The first assumption is not necessarily true. If there are multiple merge base candidates, it is up to the merge strategy to do something about this. The two standard two-head merge strategies are recursive and resolve. The resolve strategy simply picks one at (apparent) random. The recursive strategy merges the merge bases two at a time, and then uses the resulting commit as the merge base. The one chosen by resolve can be affected by the order of arguments to git merge-base and hence to git merge, so that's one caveat right there. Because the recursive strategy can do more than one merge, there's a second caveat here that is difficult to describe yet, but it applies only if there are more than two merge bases.

The second assumption is much more true, but note that the merge code can run on a partially-modified work-tree. In this case all bets are off, since the work-tree does not match either L or R. A standard git merge will tell you that you must commit first, though, so normally this is not a problem.

Merge strategies matter

We already noted the issue with multiple merge bases. We're assuming a two-head merge as well.

Octopus merges can deal with multiple heads. This also change the merge base computation, but in general octopus merge won't work with cases that have complicated merge issues and will just refuse to run where the order might matter. I would not push hard on it though; this is another case where the symmetry rule is likely to fail.

The -s ours merge strategy completely ignores all other commits so merge order is obviously crucial here: the result is always L. (I am fairly sure that -s ours does not even bother computing a merge base B.)

You can write your own strategy and do whatever you want. Here, you can make the order matter, as it does with -s ours.

High level merging (with one merge base): file name changes

Git now computes, in effect, two change-sets from these three snapshots:

  • L – B, or git diff --find-renames *B L*
  • R – B, or git diff --find-renames *B R*

The rename detectors here are independent—by this I mean neither affects the other; both use the same rules though. The main issue here is that it's possible for the same file in B to be detected as renamed in both change-sets, in which case we get what I call a high level conflict, specifically a rename/rename conflict. (We can also get high level conflicts with rename/delete and several other cases.) For a rename/rename conflict, the final name that Git chooses is the name in L, not the name in R. So here, the order matters in terms of final file name. This does not affect the work-tree merged content.

Low level merging

At this point we should take a small tour of Git's internals. We have now paired up files in B-vs-L and in B-vs-R, i.e., we know which files are "the same" files in each of the three commits. However, the way Git stores files and commits is interesting. From a logical point of view, Git has no deltas: each commit is a complete snapshot of all files. Each file, however, is just a pair of entities: a path name P and a hash ID H.

In other words, at this point, there is no need to walk through all the commits leading from B to either L or R. We know that we have some file F, identified by up to three separate path names (and as noted above, Git will use the L path in most cases, but use the R path if there is only one rename in the B-vs-R side of the merge). The complete contents of all three files are available by direct lookup: HB represents the base file content, HL represents the left-side file, and HR represents the right-side file.

Two files match exactly if and only if their hashes match.1 So at this point Git just compares the hash IDs. If all three match, the merged file is the same as the left and right and base files: there is no work. If L and R match, the merged file is the L or R content; the base is irrelevant as both sides made the same change. If B matches either L or R but not the other, the merged file is the non-matching hash. Git only has to do the low-level merge if there is a potential for a low-level merge conflict.

So now, Git extracts the three contents and does the merge. This works on a line-by-line basis (with lines grouped together when multiple adjacent lines are changed):

  • If both left and right sides touched only different source lines, Git will take both changes. This is clearly symmetric.
  • If left and right touched the same source lines, Git will check whether the change itself is also the same. If so, Git will take one copy of the change. This, too, is clearly symmetric.
  • If left and right touched the same lines, but made different changes, Git will declare a merge conflict. The work-tree content will depend on the order of the changes, since the work-tree content has <<<<<<< HEAD ... ||||||| base ... ======= ... other >>>>>>> markers (the base section is optional, appearing if you choose diff3 style).

The definition of the same lines is a little tricky. This does depend on the diff algorithm (which you may select), since some sections of some files may repeat. However, Git always uses a single algorithm for computing both L and R, so the order does not matter here.


1To put this another way, if you manage to produce a Doppelgänger file—one that has different content from, but the same hash as, some existing file, Git simply refuses to put that file into the repository. The shattered.it PDF is not such a file, because Git prefixes the file's data with the word blob and the size of the file, but the principle applies. Note that putting such a file into SVN breaks SVN—well, sort of.


-X options are obviously asymmetric

You can override merge conflict complaints using -X ours or -X theirs. These direct Git to resolve conflicts in favor of the L or R change respectively.

Merging makes a merge commit, which affects merge base computation

This symmetry principle, even with the above caveats, is fine for a single merge. But once you have made a merge, the next merge you run will use the modified commit graph to compute the new merge base. If you have two merges that you intend to do, and you do them as:

git merge one    (and fix conflicts and commit if needed)
git merge two    (fix conflicts and commit if needed)

then even if everything is symmetric in each merge, that does not mean that you will necessarily get the same result as if you run:

git merge two
git merge one

Whichever merge runs first, you get a merge commit, and the second merge now finds a different merge base.

This is particularly important if you do have conflicts that you must fix before finishing whichever merge goes first, since that also affects the L input to the second git merge command. It will use the first merge's snapshot as L, and the new (maybe different) merge base as B, for two of its three inputs.

This is why I mentioned that -s recursive has potential order differences when working with multiple merge bases. Suppose there are three merge bases. Git will merge the first two (in whatever order they pop out of the merge base computation), commit the result (even if there are merge conflicts—it just commits the conflicts in this case), and then merge that commit with the third commit and commit the result. The final commit here is then the input B. Only if all parts of this process are symmetric will that final B result be order-insensitive. Most merges are symmetric, but we saw all the caveats above.

 

Thanks for supplementing my very high-level, imprecise answer with this low-level, precise, technical detail answer 🙂

cmaster – reinstate monica

Apr 8, 2018 at 19:37


https://www.varonis.com/blog/git-branching

Merging Branches

Once you’ve completed work on your branch, it is time to merge it into the main branch. Merging takes your branch changes and implements them into the main branch. Depending on the commit history, Git performs merges two ways: fast-forward and three-way merge. Let’s examine both of these based on the branches and commit history in the following diagram.merge diagram 1When you merge the hotfix branch into the main branch, Git will move the main branch pointer forward to commit nr7jk. Git does this because the hotfix branch shares a direct ancestor commit with the main branch and is directly ahead of its commit. This commit is a fast-forward merge.fast forwardOnce you merge the hotfix branch, continue working on the feature1 branch. As you continue making commits on the feature1 branch, the commit history diverges.diverged commit historyGit is unable to move the pointer to the latest commit like in a fast-forward commit. To bring the feature1 branch into the main branch, Git performs a three-way merge. Git takes a snapshot of three different commits to create a new one:The common commit both branches share (a90hb)The latest commit of the branch (az84f)The commit of the branch to merge into (nr7jk)3 way merge commitMerging Branches in a Local RepositoryTo merge branches locally, use git checkoutto switch to the branch you want to merge into. This branch is typically the main branch. Next, use git mergeand specify the name of the other branch to bring into this branch. This example merges the jeff/feature1 branch into the main branch. Note that this is a fast-forward merge.git checkout main git merge jeff/feature1 git merge ffWork continues on the main and other branches, so they no longer share a common commit history. Now a developer wants to merge the jeff/feature2 branch into the main branch. Instead, Git performs a three-way (or recursive) merge commit.git checkout main git merge jeff/feature2git recursive mergeMerging Branches to Remote RepositoryIf you create a branch in your local repository, the remote repository is not aware of the branch’s existence. Before you can push the branch code in the remote repository, you set the remote repository as the upstream branch using the git pushcommand. This command simultaneously sets the upstream branch and pushes the branch contents to the remote repository.git push --set-upstream origin <branch name>git push set upstreamMerging Main into a BranchWhile you are working on your branch, other developers may update the main branch with their branch. This action means your branch is now out of date of the main branch and missing content. You can merge the main branch into your branch by checking out your branch and using the same git merge command.git checkout <branch name> git merge maingit merge to branchGit FAQsWhat is creating a branch in Git?Creating a branch takes a snapshot of the existing code so you can work on it independently of the main branch.How do I create a new branch in Git?Use the git branch command and specify the branch name, e.g., git branch feature1.How can I view which branch is active?Use git branch to view available branches and which one is active. Git typically designates the active branch with an asterisk and a different colored font.How can I switch to working on another branch?Use git checkout and the name of the branch to make it active.Can I create a branch inside another branch?Yes, specify the name of the branch to base the new branch, e.g., git branch feature-bug feature1.My branch only exists locally. How can I add my branch to my remote Git repository?Yes, use the git push command to set the upstream branch, e.g., git push –set-upstream origin .How can I update the main branch with my branch’s changes?Switch to the main branch using the git checkout command, then merge the branch using the git merge command along with the branch name.How can I delete a branch?When you are done with a branch, delete it using the git branch command and the -d switch, e.g., git branch -d feature1.ClosingGit branching is a powerful feature that allows teams to work on the code independently of each other. Knowing how to create, name, and merge branches are essential skills for any developer, systems administrator, or DevOps engineer.

Jeff Brown


https://www.delftstack.com/howto/git/git-pull-master-into-branch/

Git Pull Master Into Branch

Git Git Pull

Created: February-17, 2022

  1. Git Pull Master Into Another Branch
  2. Use the git merge Command to Pull Changes From master Into Another Branch
  3. Use the git rebase Command to Pull Changes From master Into Another Branch
  4. Use the git pull Command to Pull Changes From master Into Another Branch

While developing software with the Git tool, you can create different branches for different features. When making changes to master, those changes are not automatically added to other branches.

This article will explain how to pull all changes from master into another branch in Git.

Git Pull Master Into Another Branch

When using the Git tool, you may need to pull the changes you made in the master to a different branch. These changes are not transferred automatically, so you have to make them manually.

The rest of the article will explain how to pull changes from the master to the dev branch in three different ways.

Note

Because it may be considered dehumanizing toward enslaved people, the master branch has been renamed to main.

Merge

Use the git merge Command to Pull Changes From master Into Another Branch

First, we need to switch to the branch we want to work. The checkout command updates the files in the working tree according to the specified branch.

Use the following command to switch to the dev branch.

git checkout dev

The git fetch command downloads objects and refs from another repository. Use the below command to update your branch if the main branch is changed.

git fetch origin

The git merge command incorporates changes from the named commits into the current branch. Finally, you need to use the following command to merge the changes.

git merge origin/main

image-20220530175816626

Rebase

Use the git rebase Command to Pull Changes From master Into Another Branch

Use the command below to switch to the dev branch.

 

git checkout dev

Use the fetch command to update the dev branch if the main branch is changed.

git fetch origin

The git rebase command reapplies commits on top of another branch. Use the following command to reapply commits on the dev branch.

 

 

git rebase origin/main

image-20220530175840237

Pull

Use the git pull Command to Pull Changes From master Into Another Branch

Use the command below to switch to the dev branch.

git checkout dev

The git pull command fetches from and integrates with another branch. The --allow-unrelated-histories parameter can be used to merge histories that do not share a common ancestor when merging projects.

Use the following command to get the changes from the main.

 

git pull origin main --allow-unrelated-histories

image-20220530175856965

Write for us

DelftStack articles are written by software geeks like you. If you also would like to contribute to DelftStack by writing paid articles, you can check the write for us page.

Related Article – Git Pull

Overwrite Local Changes in Git

Difference Between Git Fetch and Git Pull

Pull Changes From a Specific Branch in Git

Pull Changes From Another Branch in Git


https://stackoverflow.com/questions/61069101/how-do-i-pull-changes-from-a-branch-in-master-to-a-subbranch

 

 

I checked out branch B1, did a pull, then merged it with B2.

 

You can either merge or rebase the branch b1 to branch b2.

git checkout b2
git merge b1

or

git checkout b2
git rebase b1

 

  • I tried the first option with the merge, but it says already up to date. However, I know it's not the case when I compare against the github commi thistory. Maybe it's pulling from master somehow?

     

  • Try to pull first before merging or rebasing. git checkout b2 git pull similarly pull for branch b1 and then perform the merge or rebase

    Than you! That worked. I checked out branch B1, did a pull, then merged it with B2.

 

 

Breakdown

How do I pull changes from a branch in master to a subbranch?

 

So I have a branch B1 which is a branch of master. I later created branch B2 from branch B1. However, when I do git pull in B2, I'm not pulling the changes from branch B1. How do I pull changes from B1? Thank you.

  • you will have to merge B1 into B2 to get the changes

     

2 Answers

 

I recommend avoiding git pull entirely, at least (or especially) if you're just starting with Git. All git pull does is run git fetch, then run a second Git command for you. The problem is that this obscures what is really happening, preventing you from learning what you need to know.

What you need to know starts with what a commit really is and does, because Git is all about commits. Git is not about files, though a commit does hold files; and it's not even really about branches either, though branch names like b1 and b2 help you—or at least Git—find commits. But while commits hold files, and branch names hold commit hash IDs, Git is really all about the commits.

So, each commit:

  • Holds a snapshot of all of your files. That's a full snapshot, not changes since the previous commit.
  • Holds some extra information—some metadata—such as your name and email address, and why you made the commit you made. Most of this is just for other humans, but there's a key element in the metadata that's for Git itself, which we'll get to in a moment.
  • Has a hash ID. That hash ID is a big ugly string of letters and digits. It looks random, though it's entirely not-random. In fact, the hash ID is a cryptographic checksum of the complete contents of the commit: the files-as-snapshot, and the metadata.

The result of all this is that once made, no part of any commit can ever change. You can take everything out of a commit, make changes to it somewhere else, and then make a new commit from the result, but if you've changed even one single bit anywhere—your name, your log message, one bit of some source file, whatever—what you get is a new and different commit. So commit hash IDs are guaranteed to find one particular commit, and every Git uses the same hash algorithm, so all Gits everywhere use the same hash IDs for the same commits.

How branches grow, or,there is no such thing as a sub-branch

The next thing you need to know is that there is no such thing as a sub-branch.

Given that every commit has its own unique hash ID, we're still left with a problem: how do we find commits? The hash IDs look random, and certainly are not in any sort of useful order. This is where Git's internal metadata, and branch names, come in.

Every commit holds, as part of its metadata, a list of parent commit hash IDs. Usually there is just one hash ID here. That one hash ID is the (singular) parent of this commit. This ties all commits together, one by one, backwards:

... <-F <-G <-H

where H stands for the hash ID of the last commit in the chain. Commit H itself records the actual hash ID of earlier commit G, so by looking inside H we can find the number—the hash ID—that lets us find G. Commit G stores the hash ID of earlier commit F, and so on.

We've now reduced the problem to finding commit H. The way we do that is with a branch name like master or b1. We store the raw hash ID of commit H into the name, giving us:

...--F--G--H   <-- b1

Each branch name holds exactly one commit hash ID. If we make a second branch b2, we must pick one of the various existing commits, and make b2 hold that hash ID. Typically we might pick the current commit, i.e., the one with hash H:

...--F--G--H   <-- b1, b2

Now we need to remember which name we're using. Git uses the special name HEAD (in all uppercase like this) for that. There are several ways to draw that; here, I'll just attach HEAD in parentheses to one of these branch names:

...--F--G--H   <-- b1 (HEAD), b2

or:

...--F--G--H   <-- b1, b2 (HEAD)

At this point, let's make a new commit, in the usual way: modify something, git add, and git commit. Git builds the snapshot for the new commit from Git's index—something we won't describe properly here, but this index is why you have to run git add all the time–and the appropriate metadata, including a log message you must write. This new commit gets a new, unique hash ID. The data for the new commit is the new snapshot, and the metadata is what you said, except for the parent: that comes from what Git knows, which is that the current commit is H at this time. So new commit I points back to existing commit H:

...--F--G--H
            \
             I

and now Git updates whichever branch name HEAD is attached to. If that's b2, the name b2 now holds the hash ID of commit I:

...--F--G--H   <-- b1
            \
             I   <-- b2 (HEAD)

Note that commits up through H are now on both branches, while commit I is only on b1. The name HEAD remains attached to the current branch, but now the current commit is commit I.

Merging

Suppose you start with:

...--G--H   <-- master (HEAD)

and then create names b1 and b2, both pointing to existing commit H. You then select b1 to work on, with git checkout b1, and make two commits:

          I--J   <-- b1 (HEAD)
         /
...--G--H   <-- master, b2

Note that b2 has not yet moved. Now you run git checkout b2 to select commit H again. The snapshots you made for I and J are still there, frozen for all time, but now you're working with the snapshot from H again. You can now make a couple of commits here on b2, giving:

          I--J   <-- b1
         /
...--G--H   <-- master
         \
          K--L   <-- b2 (HEAD)

Note that, at this point, you could git checkout master and make new commits there:

          o--o   <-- b1
         /
...--o--o--o--o--o--o   <-- master (HEAD)
         \
          o--o   <-- b2

We won't worry about this just yet, but note that nothing happened to any existing commit or any other branch name. Each time we added new commits, the current branch name moved. The new commits all just added to the existing graph of all-commits-so-far. It's totally impossible to change any existing commit, but we never did. All we did was add new commits that link back to the existing ones, and then change the branch names.

Let's go back to the idea of merging, though. We didn't make any new master commits after all, and if we git checkout b1, and temporarily stop drawing in the name master (because it will get in the way), we have:

          I--J   <-- b1 (HEAD)
         /
...--G--H
         \
          K--L   <-- b2

We can now run git merge b2, or we can run git checkout b2; git merge b1. Git will now do its best to combine work, because git merge is about combining work.

Now, each commit holds a snapshot, but combining work requires looking at changes. What Git does here is to use its internal difference engine, which you can invoke yourself with git diff. To make this work, Git first has to find the best common commit: a commit that is on both branches, and not too different from the latest commit on each branch.

Here, it's super-obvious which commit is the best common commit. That's commit H. So Git will now compare the snapshot in H to the snapshot in whichever commit we picked with our git checkout—the commit HEAD is attached to. If we assume that's b1, the commit for this comparison is J:

git diff --find-renames <hash-of-H> <hash-of-J>   # what we changed

This tells Git what "we" changed on b1, with respect to the common starting point. Then Git diffs the other pairing:

git diff --find-renames <hash-of-H> <hash-of-L>   # what they changed

This tells Git what "they" changed on b2, with respect to the same starting point.

The merge operation now combines these changes, file by file. If we changed line 42 of main.py and they didn't touch main.py at all, Git takes our change. If they did touch main.py too, but not line 42, Git takes their change as well. If we both touched line 42, we'd better both have changed it the same way. If not, Git declares a merge conflict and leaves us with a mess.

Assuming there are no merge conflicts—the above is not a complete list of possible conflicts, just the obvious kind—Git will be able to combine the two sets-of-changes and apply all those changes to all the files as they appear in commit H. That way, the new commit that Git is about to make has our changes from J, but also has their changes from L.

At this point, Git makes the new commit. As usual, the new commit has a snapshot: that's the one Git built by combining changes. As usual, the new commit has a parent; since we're on branch b1, this parent is J. But—not as usual—the new commit has a second parent too. Since we told Git to merge commit L, this second parent is L.

Having made the commit, Git drags our current branch name forward:

          I--J
         /    \
...--G--H      M   <-- b1 (HEAD)
         \    /
          K--L   <-- b2

and this is the result of running git merge.

Git is distributed

Now, you're probably not the only person who makes commits. Other people make commits too. You typically start by cloning a repository, perhaps from GitHub, perhaps from somewhere else. This gets you all of their commits. Your Git is going to call this other Git origin, by default.

We already saw that in any repository, we find the last commit of some branch by its branch name. So their Git—the one over on GitHub, or whatever—has some branch names:

...--o--o   <-- master
         \
          o--o--o   <-- develop

and so on. When you clone their repository, you get all of their commits, with their unique hash IDs that stay those hash IDs. But you don't get their branch names. Those are theirs. Your Git takes their names and changes them, so that you can have your own branch names.

The changes your Git makes to their branch names turn their names into your remote-tracking names. These names look like origin/master and origin/develop. These remember, in your repository, where their branch names were:

...--D--E   <-- origin/master
         \
          F--G--H   <-- origin/develop

For the last step of your git clone, your Git creates a new branch name, pointing to the same commit as one of their branch names. You can choose which branch this is but usually it's just master, so that you get:

...--D--E   <-- master (HEAD), origin/master
         \
          F--G--H   <-- origin/develop

If you now go making new commits, you get this:

          I--J   <-- master (HEAD)
         /
...--D--E   <-- origin/master
         \
          F--G--H   <-- origin/develop

Now, suppose that they, whoever they are, manage to create two new commits on their master. Your Git does not have these commits yet, but you can get them.

You run:

git fetch origin

(or just git fetch, which defaults to origin). Your Git calls up their Git again. They tell your Git about their branch names (and other names) and your Git discovers that, gosh, there are new commits K-L to get from them. So your Git does, and then your Git updates your origin/master accordingly:

          I--J   <-- master (HEAD)
         /
...--D--E--K--L   <-- origin/master
         \
          F--G--H   <-- origin/develop

(I've assumed here they did not add new commits to their develop, otherwise we'd have new commits on origin/develop now too.)

So, this is what git fetch is all about: your Git calls up some other Git, and gets new commits from that Git (if there are any to get) and then updates your remote-tracking names. After this git fetch you may have new commits. What if you want to use them?

To use their new commits after fetching, you need a second Git command

Let's say that you'd like to merge their work with your work, to create merge commit M in the usual way. You can now run:

git merge origin/master

This will make new merge commit M on its own, if it can, merging your J with their L, exactly as we saw above. It doesn't matter that commit L is found by a remote-tracking name instead of a branch name. Git doesn't care about names; Git cares about commits. So we get:

          I--J--M   <-- master (HEAD)
         /     /
...--D--E--K--L   <-- origin/master
         \
          F--G--H   <-- origin/develop

This is where git pull comes in

The pull command just combines two commands into one:

  • run git fetch to get new commits from them; then
  • run a second Git command to incorporate those new commits.

The default second command is git merge, so git fetch uses the commits that just came in to run a git merge. But git pull can run a deliberately limited kind of fetch, and doesn't just merge with any new commits from them. To know what to merge, git pull requires that you say what to use here.

The confusing part is that when you name what to use on the git pull command, you must use their branch names, even though your Git is going to work with your own remote-tracking names in a moment. So if you want to fetch from origin, then merge with what they call b2, you need:

git pull origin b2

This runs a limited kind of git fetch, then merges with whichever commit they're naming via their b2, that your Git names via your origin/b2. The missing slash here is because the first step—the git fetch—needs to know which Git to call up (the one at origin) and the second step needs to know which of their branch names to use.

Both of these two steps, git fetch and git merge, can fail. It's very unlikely for git fetch to fail (and git pull will stop if it does), but if you keep these as two separate commands, you can tell which one failed, if either one did. Moreover—and for me, much more important—you can look to see what git fetch fetched before you run git merge. And last, not so important once you know it, you'll realize that these are two entirely separate operations in Git: fetch gets commits; merge combines work.

It's safe to run git fetch any time, from any branch. Fetch just calls up another Git and gets commits from them. This does not touch anything you're doing right now. It's not so safe to run git merge any time: that merges something into your current branch, and you only have one current branch at any time. If you have lots of branches to update, you can git fetch and update all your remote-tracking names all at once, but then you have to, one by one, git checkout the branches you want updated, and git merge each one, with whichever commit you want to merge with—probably from the remote-tracking name for that branch, but because you can look, you can check first to see if you really do want that merge.

Sending commits to them

You now have commits I-J-M (with M having two parents, the first being J and the second being L) that they don't have. To send them your commits, you can use git push, providing they give you permission. (Note: these permissions are controlled by the hosting software, not by Git itself.) Running:

git push origin master

has your Git call up their Git, give them commits you have that they don't, that they'll need—in this case, I, J, and M—and then ask them to set their branch name. Note that you do not ask them to set a remote-tracking name. There are no remote-tracking names in this direction! You just ask them to set a branch name directly.

Sometimes, they'll accept this request. Sometimes they might refuse, because they've set up preventive barriers—maybe on specific branch names, and again, this is controlled by the hosting software—or because they just don't allow pushes at all. Or, they might refuse because you didn't merge, or didn't merge recently enough. Suppose they had the above, but while you were running git merge, someone else added another commit. If you run git fetch now, you'll get:

          I--J--M   <-- master (HEAD)
         /     /
...--D--E--K--L--N   <-- origin/master
         \
          F--G--H   <-- origin/develop

which means that their master now names commit N, which didn't exist a moment ago. You might need to merge again, or maybe you want to remove your commit M entirely (which is a little tricky sometimes) and make a new merge O that incorporates N this time.

 

 


nvm –help Show this message
nvm –version Print out the installed version of nvm
nvm install [-s] Download and install a , [-s] from source. Uses .nvmrc if available
–reinstall-packages-from= When installing, reinstall packages installed in <nodeios jsnodeversion>
–lts When installing, only select from LTS (long-term support) versions
–lts= When installing, only select from versions for a specific LTS line
–skip-default-packages When installing, skip the default-packages file if it exists
–latest-npm After installing, attempt to upgrade to the latest working npm on the given node version
–no-progress Disable the progress bar on any downloads
nvm uninstall Uninstall a version
nvm uninstall –lts Uninstall using automatic LTS (long-term support) alias lts/*, if available.
nvm uninstall –lts= Uninstall using automatic alias for provided LTS line, if available.
nvm use [–silent] Modify PATH to use . Uses .nvmrc if available
–lts Uses automatic LTS (long-term support) alias lts/*, if available.
–lts= Uses automatic alias for provided LTS line, if available.
nvm exec [–silent] [] Run on . Uses .nvmrc if available
–lts Uses automatic LTS (long-term support) alias lts/*, if available.
–lts= Uses automatic alias for provided LTS line, if available.
nvm run [–silent] [] Run node on with as arguments. Uses .nvmrc if available
–lts Uses automatic LTS (long-term support) alias lts/*, if available.
–lts= Uses automatic alias for provided LTS line, if available.
nvm current Display currently activated version of Node
nvm ls [] List installed versions, matching a given if provided
–no-colors Suppress colored output
–no-alias Suppress nvm alias output
nvm ls-remote [] List remote versions available for install, matching a given if provided
–lts When listing, only show LTS (long-term support) versions
–lts= When listing, only show versions for a specific LTS line
–no-colors Suppress colored output
nvm version Resolve the given description to a single local version
nvm version-remote Resolve the given description to a single remote version
–lts When listing, only select from LTS (long-term support) versions
–lts= When listing, only select from versions for a specific LTS line
nvm deactivate Undo effects of nvm on current shell
nvm alias [] Show all aliases beginning with
–no-colors Suppress colored output
nvm alias Set an alias named pointing to
nvm unalias Deletes the alias named
nvm install-latest-npm Attempt to upgrade to the latest working npm on the current node version
nvm reinstall-packages Reinstall global npm packages contained in to current version
nvm unload Unload nvm from shell
nvm which [current ]Display path to installed node version. Uses .nvmrc if available
nvm cache dir Display path to the cache directory for nvm
nvm cache clear Empty cache directory for nvm

Example:  
nvm install 8.0.0 Install a specific version number
nvm use 8.0 Use the latest available 8.0.x release
nvm run 6.10.3 app.js Run app.js using node 6.10.3
nvm exec 4.8.3 node app.js Run node app.js with the PATH pointing to node 4.8.3
nvm alias default 8.1.0 Set default node version on a shell
nvm alias default node Always default to the latest available node version on a shell

   

Package.json / Package-lock.json

https://www.jetbrains.com/help/idea/resolve-conflicts.html#CRLF_warning

https://www.jetbrains.com/help/idea/resolving-conflicts.html

Resolve conflicts

Last modified: 08 March 2021

Depending on your version control system, conflicts may arise in different situations.

When you work in a team, you may come across a situation when somebody commits changes to a file you are currently working on. If these changes do not overlap (that is, changes were made to different lines of code), the conflicting files are merged automatically. However, if the same lines were affected, your version control system cannot randomly pick one side over the other, and asks you to resolve the conflict.

Conflicts may also arise when merging, rebasing or cherry-picking branches.

Non-Distributed Version Control Systems

When you try to edit a file that has a newer version on the server, IntelliJ IDEA informs you about that, showing a message popup in the editor:

conflicts warning

In this case, you should update your local version before changing the file, or merge changes later.

 

If you attempt to commit a file that has a newer repository version, the commit fails, and an error is displayed in the bottom right corner telling you that the file you are trying to commit is out of date.

 

The failed commit behavior is regulated by the Create changelist on failed commit list in the Version Control | Confirmation page of the Settings / Preferences dialog.

If you synchronize a file that already has local changes with a newer repository version committed by somebody else, a conflict occurs. The conflicting file gets the Merged with conflicts status. The file remains in the same changelist in the Local Changes view, but its name is highlighted in red. If the file is currently opened in the editor, the filename on the tab header is also highlighted in red.

Distributed Version Control Systems

Under distributed version control systems, such as Git and Mercurial, conflicts arise when a file you have committed locally has changes to the same lines of code as the latest upstream version and when you attempt to perform one of the following operations: pull, merge, rebase, cherry-pick, unstash, or apply patch.

If there are conflicts, these operations will fail and you will be prompted to accept the upstream version, prefer your version, or merge the changes manually:

IntelliJ IDEA: VCS operation conflicts dialog

The Conflicts dialog is triggered automatically when a conflict is detected on the Version Control level.

If you click Close in this dialog, or call a Git operation that leads to a merge conflict from command line, a Merge Conflicts node will appear in the Local Changes view with a link to resolve them:

The Merge Conflicts node in the Local Changes view

IntelliJ IDEA provides a tool for resolving conflicts locally. This tool consists of three panes:

  • The left page shows the read-only local copy
  • The right pane shows the read-only version checked in to the repository
  • The central pane shows a fully-functional editor where the results of merging and conflict resolving are displayed. Initially, the contents of this pane is the same as the base revision of the file, that is, the revision from which both conflicting versions are derived.

color coding in the conflict resolution tool

Resolve conflicts

Last modified: 08 March 2021

When you work in a team, you may come across a situation when somebody pushes changes to a file you are currently working on. If these changes do not overlap (that is, changes were made to different lines of code), the conflicting files are merged automatically. However, if the same lines were affected, Git cannot randomly pick one side over the other, and asks you to resolve the conflict.

In Git, conflicts may arise when you attempt to perform one of the following operations: pull, merge, rebase, cherry-pick, unstash changes or apply a patch. If there are conflicts, these operations will fail, and you will be prompted to accept the upstream version, prefer your version, or merge the changes:

Files Merged with Conflicts dialog

The Conflicts dialog is triggered automatically when a conflict is detected on the Git level.

If you click Close in this dialog, or call a Git operation that leads to a merge conflict from command line, a Merge Conflicts node will appear in the Local Changes view with a link to resolve them:

The Merge Conflicts node in the Local Changes view

IntelliJ IDEA provides a tool for resolving conflicts locally. This tool consists of three panes:

  • The left pane shows the read-only local copy
  • The right pane shows the read-only version checked in to the repository.
  • The central pane is a fully-functional editor where the results of resolving conflicts are displayed. Initially, the contents of this pane are the same as the base revision of the file, that is, the revision from which both conflicting versions are derived.

color coding in the conflict resolution tool

Resolve conflicts

  1. Click Merge in the Conflicts dialog, the Resolve link in the Local Changes view, or select the conflicting file in the editor and choose VCS | Git | Resolve Conflicts from the main menu.

  2. To automatically merge all non-conflicting changes, click (Apply All Non-Conflicting Changes) on the toolbar. You can also use the (Apply Non-Conflicting Changes from the Left Side) and (Apply Non-Conflicting Changes from the Right Side) to merge non-conflicting changes from the left/right parts of the dialog respectively.

  3. To resolve a conflict, you need to select which action to apply (accept or ignore ) to the left (local) and the right (repository) version, and check the resulting code in the central pane:

    Resolve conflicts

    You can also right-click a highlighted conflict in the central pane and use the commands from the context menu. The Resolve using Left and Resolve using Right commands provide a shortcut to accepting changes from one side and ignoring them from the other side respectively:

    the context menu of a conflicting change

    For simple conflicts (for example, if the beginning and the end of the same line have been modified in different file revisions), the Resolve simple conflicts button that allows merging the changes in one click becomes available.

    the Resolve Simple Conflicts button

    Such conflicts are not resolved with the Apply All Non-Conflicting Changes action since you must make sure that they are resolved properly.

     

    Note that the central pane is a fully-functional editor, so you can make changes to the resulting code directly in this dialog.

  4. It may also be useful to compare different versions to resolve a conflict. Use the toolbar button to invoke the list of options. Note that Base refers to the file version that the local and the repository versions originated from (initially displayed in the middle pane), while Middle refers to the resulting version.

  5. Review merge results in the central pane and click Apply.

Productivity tips

  • Apply non-conflicting changes automatically

    You can configure IntelliJ IDEA to always apply non-conflicting changes automatically instead of telling it to do so from the Merge dialog. To do this, select the Automatically apply non-conflicting changes option on the Tools | Diff Merge page of the IDE settings ⌘,.

  • Manage changes in the central pane

    You can manage changes in the central pane using the toolbar that appears when you hover the mouse cursor over a change marker in the gutter, and then click it. The toolbar is displayed together with a frame showing the previous contents of the modified line:the change toolbarFor example, when there are multiple non-conflicting changes, and you only need to skip one or two of them, it's easier to apply all of them simultaneously using the Apply all non-conflicting changes action, and then undo the unwanted ones using the Revert action from this toolbar.

Quite often, people working in a team and contributing to the same repository use different operating systems. This may result in problems with line ending, because Unix, Linux and MacOS us LF, and Windows uses CRLF to mark the end of a line.

IntelliJ IDEA displays the discrepancies in line endings in the Differences Viewer, so you can fix them manually. If you want Git to solve such conflicts automatically, you need to set the core.autocrlf attribute to true on Windows and to input on Linux and MacOS (for more details, see Dealing with line endings). You can change the configuration manually by running git config --global core.autocrlf true on Windows or git config --global core.autocrlf input on Linux and macOS.

However, IntelliJ IDEA can automatically analyze your configuration, warn you if you are about to commit CRLF into a remote repository, and suggest setting the core.autocrlf setting to true or input depending on your operating system.

To enable smart handling of LF and CRLF line separators, open the Settings/Preferences dialog ⌘,, and select the Version Control | Git node on the left. Enable the Warn if CRLF line separators are about to be committed option.

After you have enabled this option, IntelliJ IDEA will display the Line Separators Warning Dialog each time you are about to commit a file with CRLF separators, unless you have set any related Git attributes in the affected file (in this case, IntelliJ IDEA supposes that you clearly understand what you are doing and excludes this file from analysis).

In the Line Separators Warning Dialog, click one of the following:

  • Commit As Is to ignore the warning and commit a file with CRFL separators.
  • Fix and Commit to have the core.autocrlf attribute set to true or input depending on your operating system. As a result, CRLF line separators will be replaced with LF before the commit.

If, at a later time, you need to review how exactly conflicts were resolved during a merge, you can locate the required merge commit in the Log tab of the Git tool window ⌘9, select a file with conflicts in the Commit Details pane in the right, and click < or press ⌘D (see Review how changes were merged for details).

 


NPM creates a new package-lock.json – do you commits?

(e.g. my version of silvermine player had to be updated to match up with the updated package.json file from stage)

Yes, package-lock.json is intended to be checked into source control. If you're using npm 5+, you may see this notice on the command line: created a lockfile as package-lock.json. You should commit this file. According to npm help package-lock.json:

package-lock.json is automatically generated for any operations where npm modifies either the node_modules tree, or package.json. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.

This file is intended to be committed into source repositories, and serves various purposes:

  • Describe a single representation of a dependency tree such that teammates, deployments, and continuous integration are guaranteed to install exactly the same dependencies.
  • Provide a facility for users to "time-travel" to previous states of node_modules without having to commit the directory itself.
  • To facilitate greater visibility of tree changes through readable source control diffs.
  • And optimize the installation process by allowing npm to skip repeated metadata resolutions for previously-installed packages.

One key detail about package-lock.json is that it cannot be published, and it will be ignored if found in any place other than the toplevel package. It shares a format with npm-shrinkwrap.json, which is essentially the same file, but allows publication. This is not recommended unless deploying a CLI tool or otherwise using the publication process for producing production packages.

If both package-lock.json and npm-shrinkwrap.json are present in the root of a package, package-lock.json will be completely ignored.

 


If software did not resolve package.json conflicts

 

Package.json – ALL INFO

https://docs.npmjs.com/cli/v6/configuring-npm/package-json


https://docs.npmjs.com/cli/v6/configuring-npm/package-locks

Resolving lockfile conflicts

Occasionally, two separate npm install will create package locks that cause merge conflicts in source control systems. As of npm@5.7.0, these conflicts can be resolved by manually fixing any package.json conflicts, and then running npm install [--package-lock-only] again. npm will automatically resolve any conflicts for you and write a merged package lock that includes all the dependencies from both branches in a reasonable tree. If --package-lock-only is provided, it will do this without also modifying your local node_modules/.

To make this process seamless on git, consider installing npm-merge-driver, which will teach git how to do this itself without any user interaction. In short: $ npx npm-merge-driver install -g will let you do this, and even works with pre-npm@5.7.0 versions of npm 5, albeit a bit more noisily. Note that if package.json itself conflicts, you will have to resolve that by hand and run npm install manually, even with the merge driver.


package-locks

An explanation of npm lockfiles

Table of contents

Description

Conceptually, the "input" to npm install is a package.json, while its "output" is a fully-formed node_modules tree: a representation of the dependencies you declared. In an ideal world, npm would work like a pure function: the same package.json should produce the exact same node_modules tree, any time. In some cases, this is indeed true. But in many others, npm is unable to do this. There are multiple reasons for this:

  • different versions of npm (or other package managers) may have been used to install a package, each using slightly different installation algorithms.
  • a new version of a direct semver-range package may have been published since the last time your packages were installed, and thus a newer version will be used.
  • A dependency of one of your dependencies may have published a new version, which will update even if you used pinned dependency specifiers (1.2.3 instead of ^1.2.3)
  • The registry you installed from is no longer available, or allows mutation of versions (unlike the primary npm registry), and a different version of a package exists under the same version number now.

As an example, consider package A:

 

{
  "name": "A",
  "version": "0.1.0",
  "dependencies": {
    "B": "<0.1.0"
  }
}

package B:

 

{
  "name": "B",
  "version": "0.0.1",
  "dependencies": {
    "C": "<0.1.0"
  }
}

and package C:

 

{
  "name": "C",
  "version": "0.0.1"
}

If these are the only versions of A, B, and C available in the registry, then a normal npm install A will install:

 

A@0.1.0
`-- B@0.0.1
    `-- C@0.0.1

However, if B@0.0.2 is published, then a fresh npm install A will install:

 

A@0.1.0
`-- B@0.0.2
    `-- C@0.0.1

assuming the new version did not modify B's dependencies. Of course, the new version of B could include a new version of C and any number of new dependencies. If such changes are undesirable, the author of A could specify a dependency on B@0.0.1. However, if A's author and B's author are not the same person, there's no way for A's author to say that he or she does not want to pull in newly published versions of C when B hasn't changed at all.

To prevent this potential issue, npm uses package-lock.json or, if present, npm-shrinkwrap.json. These files are called package locks, or lockfiles.

Whenever you run npm install, npm generates or updates your package lock, which will look something like this:

 

{
  "name": "A",
  "version": "0.1.0",
  ...metadata fields...
  "dependencies": {
    "B": {
      "version": "0.0.1",
      "resolved": "https://registry.npmjs.org/B/-/B-0.0.1.tgz",
      "integrity": "sha512-DeAdb33F+"
      "dependencies": {
        "C": {
          "version": "git://github.com/org/C.git#5c380ae319fc4efe9e7f2d9c78b0faa588fd99b4"
        }
      }
    }
  }
}

This file describes an exact, and more importantly reproducible node_modules tree. Once it's present, any future installation will base its work off this file, instead of recalculating dependency versions off package.json.

The presence of a package lock changes the installation behavior such that:

  1. The module tree described by the package lock is reproduced. This means reproducing the structure described in the file, using the specific files referenced in "resolved" if available, falling back to normal package resolution using "version" if one isn't.
  2. The tree is walked and any missing dependencies are installed in the usual fashion.

If preshrinkwrap, shrinkwrap or postshrinkwrap are in the scripts property of the package.json, they will be executed in order. preshrinkwrap and shrinkwrap are executed before the shrinkwrap, postshrinkwrap is executed afterwards. These scripts run for both package-lock.json and npm-shrinkwrap.json. For example to run some postprocessing on the generated file:

 

"scripts": {
    "postshrinkwrap": "json -I -e \"this.myMetadata = $MY_APP_METADATA\""
  }
Using locked packages

Using a locked package is no different than using any package without a package lock: any commands that update node_modules and/or package.json's dependencies will automatically sync the existing lockfile. This includes npm install, npm rm, npm update, etc. To prevent this update from happening, you can use the --no-save option to prevent saving altogether, or --no-shrinkwrap to allow package.json to be updated while leaving package-lock.json or npm-shrinkwrap.json intact.

It is highly recommended you commit the generated package lock to source control: this will allow anyone else on your team, your deployments, your CI/continuous integration, and anyone else who runs npm install in your package source to get the exact same dependency tree that you were developing on. Additionally, the diffs from these changes are human-readable and will inform you of any changes npm has made to your node_modules, so you can notice if any transitive dependencies were updated, hoisted, etc.

Resolving lockfile conflicts

Occasionally, two separate npm install will create package locks that cause merge conflicts in source control systems. As of npm@5.7.0, these conflicts can be resolved by manually fixing any package.json conflicts, and then running npm install [--package-lock-only] again. npm will automatically resolve any conflicts for you and write a merged package lock that includes all the dependencies from both branches in a reasonable tree. If --package-lock-only is provided, it will do this without also modifying your local node_modules/.

To make this process seamless on git, consider installing npm-merge-driver, which will teach git how to do this itself without any user interaction. In short: $ npx npm-merge-driver install -g will let you do this, and even works with pre-npm@5.7.0 versions of npm 5, albeit a bit more noisily. Note that if package.json itself conflicts, you will have to resolve that by hand and run npm install manually, even with the merge driver.

See Also

 

DO NOT – Delete `package-lock.json` to Resolve Conflicts quickly

Yes it can have bad side effects, maybe not very often but for example you can have in package.json “moduleX”: “^1.0.0” and you used to have “moduleX”: “1.0.0” in package-lock.json.

By deleting package-lock.json and running npm install you could be updating to version 1.0.999 of moduleX without knowing about it and maybe they have created a bug or done a backwards breaking change (not following semantic versioning).

Anyway there is already a standard solution for it.

Fix the conflict inside package.json
Run: npm install –package-lock-only
https://docs.npmjs.com/cli/v7/configuring-npm/package-locks#resolving-lockfile-conflicts

package-lock.json – role

It stores an exact, versioned dependency tree rather than using starred versioning like package.json itself (e.g. 1.0.*). This means you can guarantee the dependencies for other developers or prod releases, etc. It also has a mechanism to lock the tree but generally will regenerate if package.json changes.

From the npm docs:

package-lock.json is automatically generated for any operations where npm modifies either the node_modules tree, or package.json. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.

This file is intended to be committed into source repositories, and serves various purposes:

Describe a single representation of a dependency tree such that teammates, deployments, and continuous integration are guaranteed to install exactly the same dependencies.

Provide a facility for users to “time-travel” to previous states of node_modules without having to commit the directory itself.

To facilitate greater visibility of tree changes through readable source control diffs.

And optimize the installation process by allowing npm to skip repeated metadata resolutions for previously-installed packages.”

To answer jrahhali’s question below about just using the package.json with exact version numbers. Bear in mind that your package.json contains only your direct dependencies, not the dependencies of your dependencies (sometimes called nested dependencies). This means with the standard package.json you can’t control the versions of those nested dependencies, referencing them directly or as peer dependencies won’t help as you also don’t control the version tolerance that your direct dependencies define for these nested dependencies.

Even if you lock down the versions of your direct dependencies you cannot 100% guarantee that your full dependency tree will be identical every time. Secondly you might want to allow non-breaking changes (based on semantic versioning) of your direct dependencies which gives you even less control of nested dependencies plus you again can’t guarantee that your direct dependencies won’t at some point break semantic versioning rules themselves.

The solution to all this is the lock file which as described above locks in the versions of the full dependency tree. This allows you to guarantee your dependency tree for other developers or for releases whilst still allowing testing of new dependency versions (direct or indirect) using your standard package.json.

NB. The previous shrink wrap json did pretty much the same thing but the lock file renames it so that it’s function is clearer. If there’s already a shrink wrap file in the project then this will be used instead of any lock file.

 

Solving conflicts in package-lock.json

https://tkdodo.eu/blog/solving-conflicts-in-package-lock-json

One thing that can be costly when done wrong is solving conflicts in generated files, like package-lock.json. It usually happens when two branches add or update a dependency. The result of package-lock then changes, and whoever gets their PR merged to main first is the lucky one who avoided those conflicts. It's almost like a race.

So here you are, updating your PR with the base branch, and git shows you this huge amount of conflicts in package-lock.json. The conflicts in package.json are usually easily solved (if there even are any), so I think it is tempting to just delete package-lock.json and run npm install. After all, this will give you a brand new package-lock.json, which you can happily commit.

Why you should never delete package-lock.json

When you install a dependency for the first time, it is usually automatically added to your dependencies or devDependencies with ^version, which means "compatible with version, according to semver". You can try out what that means here.

Enter, for example, lodash as the package and ^4.2.1 as version, and you will see that you can get anything from 4.2.1 to 4.17.20 (the latest version)

semver calc

This is where package-lock.json comes into play. Upon installing, it will "lock" you in on the version that you just installed. So if 4.2.1 is the latest version at the moment of your install, this version will be written to package-lock and will, from there on, always be installed. Even if newer versions come out that are theoretically compatible with it.

This is important because it guarantees that every developer in the team will have the same version on their machine, and it is equally important for CI/CD. I would not want to ship a newer version to production than we tested with, even if it's just a patch version.

So when you delete package-lock.json, all those consistency goes out the window. Every node_module you depend on will be updated to the latest version it is theoretically compatible with. This means no major changes, but minors and patches. I believe this is bad for three reasons:

  1. It trusts that everyone strictly adheres to semantic versioning, and I sincerely doubt that this is the case. There is also no way to enforce this.

  2. Major version zero is exempt from the rules of semantic versioning. From

    the semver spec

    :

    Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.

Have a look at your package-lock.json and count how many dependencies with major version 0 you have. For this blog (made with gatsby) I have 362!

  1. This also applies to transitive dependencies. So even if you are using strict versions (without the ^), the libraries you are using do not.

If you delete package-lock.json now from any one of your projects and run npm install again, it will most certainly look completely different.

Will your app be fine? Maybe, maybe not. No one can tell. For me, this would usually mean: "regression test everything", which is certainly not what I have in mind when I am just solving a conflict.

What you can do instead

My usual approach was the following:

  • Solve the conflicts in package.json
  • Take package-lock.json from the base branch
  • run npm install again

This will then just re-install whatever changes we made in our branch. However, I recently learned about and even easier way:

npm can automatically detect conflicts in package-lock.json and resolve them for us. From the npm docs:

Occasionally, two separate npm install will create package locks that cause merge conflicts in source control systems. As of npm@5.7.0, these conflicts can be resolved by manually fixing any package.json conflicts, and then running npm install [–package-lock-only] again. npm will automatically resolve any conflicts for you and write a merged package lock that includes all the dependencies from both branches in a reasonable tree. If –package-lock-only is provided, it will do this without also modifying your local node_modules/.

This means that we can just keep the conflicts in the lock file. All we have to do is get package.json right, and npm will do the rest for us 🎉.

I wish I had known this sooner – it would've saved me some trouble.

Other ways to unset remote tracking

You don’t have to delete your local branch.

Simply delete the local branch that is tracking the remote branch:


git branch -d -r origin/

-r, –remotes tells git to delete the remote-tracking branch (i.e., delete the branch set to track the remote branch). This will not delete the branch on the remote repo!

See “Having a hard time understanding git-fetch”
https://stackoverflow.com/questions/1070496/having-a-hard-time-understanding-git-fetch

there’s no such concept of local tracking branches, only remote tracking branches.
So origin/master is a remote tracking branch for master in the origin repo

As mentioned in Dobes Vandermeer’s answer, you also need to reset the configuration associated to the local branch:


git config --unset branch..remote
git config --unset branch..merge
Remove the upstream information for .

If no branch is specified it defaults to the current branch.

That will make any push/pull completely unaware of origin/.


Set tracking branches for existing local branches

On the other hand, you may have chosen to work on a local branch and to set the upstream branch (or the remote tracking branch later on).

It is perfectly fine, but you will have to use the “git branch” in order to set the existing branch upstream branch.


$ git branch -u /

Let’s take the example of the “feature” branch that you just created to start working.

$ git checkout -b feature
Switched to a new branch ‘feature’

You created some commits in your branch, you want to set the tracking branch to be master.

$ git branch -u origin/master
Branch ‘feature’ set up to track remote branch ‘master’ from ‘origin’.

Great! You successfully set the upstream branch for your existing local branch.


Sorting out which branch is which – origin / pull / push

“origin” is not special
Just like the branch name “master” does not have any special meaning in Git, neither does “origin”. While “master” is the default name for a starting branch when you run git init which is the only reason it’s widely used, “origin” is the default name for a remote when you run git clone. If you run git clone -o booyah instead, then you will have booyah/master as your default remote branch.

Using the example of my copy of Puppet checked out from the upstream Git repository on Github.com…


$ git remote show origin
* remote origin
  Fetch URL: git://github.com/reductivelabs/puppet.git
  Push  URL: git://github.com/reductivelabs/puppet.git
  HEAD branch: master
  Remote branches:
    0.24.x                 tracked
    0.25.x                 tracked
    2.6.x                  tracked
    master                 tracked
    next                   tracked
    primordial-ooze        tracked
    reins-on-a-horse       tracked
    testing                tracked
    testing-17-march       tracked
    testing-18-march       tracked
    testing-2-april        tracked
    testing-2-april-midday tracked
    testing-20-march       tracked
    testing-21-march       tracked
    testing-24-march       tracked
    testing-26-march       tracked
    testing-29-march       tracked
    testing-31-march       tracked
    testing-5-april        tracked
    testing-9-april        tracked
    testing4268            tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

Then if I were to execute the following:


$ git checkout -b local_2.6 -t origin/2.6.x 
Branch local_2.6 set up to track remote branch 2.6.x from origin.
Switched to a new branch 'local_2.6'

And finally re-run the git remote show origin command again I will then see the following down near the bottom:


  Local branches configured for 'git pull':
    local_2.6 merges with remote 2.6.x
    master    merges with remote master

Upstream shorthand

When you have a tracking branch set up, you can reference its upstream branch with the @{upstream} or @{u} shorthand. So if you’re on the master branch and it’s tracking origin/master, you can say something like git merge @{u} instead of git merge origin/master if you wish.


Tracking Branches

Checking out a local branch from a remote-tracking branch automatically creates what is called a “tracking branch” (and the branch it tracks is called an “upstream branch”). Tracking branches are local branches that have a direct relationship to a remote branch. If you’re on a tracking branch and type git pull, Git automatically knows which server to fetch from and which branch to merge in.

When you clone a repository, it generally automatically creates a master branch that tracks origin/master. However, you can set up other tracking branches if you wish — ones that track branches on other remotes, or don’t track the master branch. The simple case is the example you just saw, running git checkout -b /. This is a common enough operation that Git provides the –track shorthand:


$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

In fact, this is so common that there’s even a shortcut for that shortcut. If the branch name you’re trying to checkout (a) doesn’t exist and (b) exactly matches a name on only one remote, Git will create a tracking branch for you:


$ git checkout serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

To set up a local branch with a different name than the remote branch, you can easily use the first version with a different local branch name:


$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch 'sf'

Now, your local branch sf will automatically pull from origin/serverfix.

If you already have a local branch and want to set it to a remote branch you just pulled down, or want to change the upstream branch you’re tracking, you can use the -u or –set-upstream-to option to git branch to explicitly set it at any time.


$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Note
Upstream shorthand

When you have a tracking branch set up, you can reference its upstream branch with the @{upstream} or @{u} shorthand. So if you’re on the master branch and it’s tracking origin/master, you can say something like git merge @{u} instead of git merge origin/master if you wish.

If you want to see what tracking branches you have set up, you can use the -vv option to git branch. This will list out your local branches with more information including what each branch is tracking and if your local branch is ahead, behind or both.


$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] Add forgotten brackets
  master    1ae2a45 [origin/master] Deploy index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] This should do it
  testing   5ea463a Try something new

So here we can see that our iss53 branch is tracking origin/iss53 and is “ahead” by two, meaning that we have two commits locally that are not pushed to the server. We can also see that our master branch is tracking origin/master and is up to date. Next we can see that our serverfix branch is tracking the server-fix-good branch on our teamone server and is ahead by three and behind by one, meaning that there is one commit on the server we haven’t merged in yet and three commits locally that we haven’t pushed. Finally we can see that our testing branch is not tracking any remote branch.

It’s important to note that these numbers are only since the last time you fetched from each server. This command does not reach out to the servers, it’s telling you about what it has cached from these servers locally. If you want totally up to date ahead and behind numbers, you’ll need to fetch from all your remotes right before running this. You could do that like this:


$ git fetch --all; git branch -vv

Pulling

While the git fetch command will fetch all the changes on the server that you don’t have yet, it will not modify your working directory at all. It will simply get the data for you and let you merge it yourself. However, there is a command called git pull which is essentially a git fetch immediately followed by a git merge in most cases. If you have a tracking branch set up as demonstrated in the last section, either by explicitly setting it or by having it created for you by the clone or checkout commands, git pull will look up what server and branch your current branch is tracking, fetch from that server and then try to merge in that remote branch.

Generally it’s better to simply use the fetch and merge commands explicitly as the magic of git pull can often be confusing.


Push Branch to Another Branch (different named branches)

In some cases, you may want to push your changes to another branch on the remote repository.

In order to push your branch to another branch, you may need to merge the remote branch to your current local branch.

In order to be merged, the tip of the remote branch cannot be behind the branch you are trying to push.

Before pushing, make sure to pull the changes from the remote branch and integrate them with your current local branch.

$ git pull (from remote branch)

$ git checkout my-feature (local branch)

$ git merge origin/feature (main project)

$ git push origin my-feature:feature  |  git push origin local-name:remote-name

Note : when merging the remote branch, you are merging your local branch with the upstream branch of your local repository.

 

In order to push your branch to another remote branch, use the “git push” command and specify the remote name, the name of your local branch as the name of the remote branch.

$ git push <remote> <local_branch>:<remote_name>

As an example, let’s say that you have created a local branch named “my-feature”.

$ git branch

  master
* my-feature
  feature

However, you want to push your changes to the remote branch named “feature” on your repository.

In order to push your branch to the “feature” branch, you would execute the following command

$ git push origin my-feature:feature

Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 513 bytes | 513.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/SCHKN/repo.git
   b1c4c91..9ae0aa6  my-feature -> feature

 


Origin

setting origin for local branch (different named branches)

Use the colon notation:

git push -u origin local_branch:remote_branch

 



More Origin notes

git remote show origin

origin is an alias on your system for a particular remote repository. It's not actually a property of that repository.

By doing

git push origin branchname

you're saying to push to the origin repository. There's no requirement to name the remote repository origin: in fact the same repository could have a different alias for another developer.

Remotes are simply an alias that store the URL of repositories. You can see what URL belongs to each remote by using

git remote -v

In the push command, you can use remotes or you can simply use a URL directly. An example that uses the URL:

git push git@github.com:git/git.git master

 


You can also specify -v, which shows you the URLs that Git has stored for the shortname to be used when reading and writing to that remote:

$ git remote -v

 


Set upstream branch – same name

Given a branch foo and a remote upstream:

As of Git 1.8.0:

git branch -u upstream/foo

Or, if local branch foo is not the current branch:

git branch -u upstream/foo foo

Or, if you like to type longer commands, these are equivalent to the above two:

git branch --set-upstream-to=upstream/foo

git branch --set-upstream-to=upstream/foo foo

As of Git 1.7.0 (before 1.8.0):

git branch --set-upstream foo upstream/foo

Notes:

  • All of the above commands will cause local branch foo to track remote branch foo from remote upstream.
  • The old (1.7.x) syntax is deprecated in favor of the new (1.8+) syntax. The new syntax is intended to be more intuitive and easier to remember.
  • Defining an upstream branch will fail when run against newly-created remotes that have not already been fetched. In that case, run git fetch upstream beforehand.

 


git branch --set-upstream-to, which can be used as follows, if you're on the branch my_branch:

git branch --set-upstream-to origin/my_branch

… or with the short option:

git branch -u origin/my_branch

This change, and its reasoning, is described in the release notes for git 1.8.0, release candidate 1:

It was tempting to say git branch --set-upstream origin/master, but that tells Git to arrange the local branch origin/master to integrate with the currently checked out branch, which is highly unlikely what the user meant. The option is deprecated; use the new --set-upstream-to (with a short-and-sweet -u) option instead.

 

 

 


A shortcut, which doesn't depend on remembering the syntax for git branch --set-upstream 1 is to do:

git push -u origin my_branch

… the first time that you push that branch. Or, to push to the current branch to a branch of the same name (handy for an alias):

git push -u origin HEAD

You only need to use -u once, and that sets up the association between your branch and the one at origin in the same way as git branch --set-upstream does.

Personally, I think it's a good thing to have to set up that association between your branch and one on the remote explicitly. It's just a shame that the rules are different for git push and git pull.


1 It may sound silly, but I very frequently forget to specify the current branch, assuming that's the default – it's not, and the results are most confusing

Update 2012-10-11: Apparently I'm not the only person who found it easy to get wrong! Thanks to VonC for pointing out that git 1.8.0 introduces the more obvious git branch --set-upstream-to, which can be used as follows, if you're on the branch my_branch:

git branch --set-upstream-to origin/my_branch

… or with the short option:

git branch -u origin/my_branch

This change, and its reasoning, is described in the release notes for git 1.8.0, release candidate 1:

It was tempting to say git branch --set-upstream origin/master, but that tells Git to arrange the local branch origin/master to integrate with the currently checked out branch, which is highly unlikely what the user meant. The option is deprecated; use the new --set-upstream-to (with a short-and-sweet -u) option instead.

 


When you're publishing a local branch – same names remote and local

Let's now look at the opposite scenario: you started a new local branch and now want to publish it on the remote for the first time:

$ git push -u origin dev

You can tell Git to track the newly created remote branch simply by using the -u flag with "git push".

When you decide at a later point in time

In cases when you simply forgot, you can set (or change) a tracking relationship for your current HEAD branch at any time:

$ git branch -u origin/dev

 

Push Branch To Remote – same names remote and local

In order to push a Git branch to remote, you need to execute the “git push” command and specify the remote as well as the branch name to be pushed.

$ git push <remote> <branch>

For example, if you need to push a branch named “feature” to the “origin” remote, you would execute the following query

$ git push origin feature

git push branch to remote
git push branch to remote

If you are not already on the branch that you want to push, you can execute the “git checkout” command to switch to your branch.

If your upstream branch is not already created, you will need to create it by running the “git push” command with the “-u” option for upstream.

git push upstream branch to remote
git push upstream branch to remote

$ git push -u origin feature

Congratulations, you have successfully pushed your branch to your remote!

 

Scroll to Top