A merge conflict in package-lock.json is a special case. It looks like this:
Here’s how you go about resolving it.
-
Checkout the branch in question. For example, in this case the branch is:
rh-subjects_menu_page
pconrad@169-231-112-36 team03-w22-7pm-2 % git checkout rh-subjects_menu_page Branch 'rh-subjects_menu_page' set up to track remote branch 'rh-subjects_menu_page' from 'origin'. Switched to a new branch 'rh-subjects_menu_page' pconrad@169-231-112-36 team03-w22-7pm-2 %
-
Make sure the branch is up-to-date with what’s on github by pulling from the branch:
git pull origin rh-subjects_menu_page
-
Next, type the command to rebase your branch on origin main, like this:
git pull --rebase origin main
Heres what that would look like. Note that the
git
command line is telling us the same thing that GitHub did, namely that we have a merge conflict inpackage.lock.json
pconrad@169-231-112-36 team03-w22-7pm-2 % git pull --rebase origin main From github.com:ucsb-cs156-w22/team03-w22-7pm-2 * branch main -> FETCH_HEAD First, rewinding head to replay your work on top of it... Applying: created menu and pages Using index info to reconstruct a base tree... M frontend/package-lock.json .git/rebase-apply/patch:35850: trailing whitespace. warning: 1 line adds whitespace errors. Falling back to patching base and 3-way merge... Auto-merging frontend/package-lock.json CONFLICT (content): Merge conflict in frontend/package-lock.json error: Failed to merge in the changes. Patch failed at 0001 created menu and pages hint: Use 'git am --show-current-patch' to see the failed patch Resolve all conflicts manually, mark them as resolved with "git add/rm <conflicted_files>", then run "git rebase --continue". You can instead skip this commit: run "git rebase --skip". To abort and get back to the state before "git rebase", run "git rebase --abort". pconrad@169-231-112-36 team03-w22-7pm-2 %
-
Next, type
git status
and you should see that the conflicted files are in red, while the non-conflicted files are in green:pconrad@169-231-112-36 team03-w22-7pm-2 % git status rebase in progress; onto da679f5 You are currently rebasing branch 'rh-subjects_menu_page' on 'da679f5'. (fix conflicts and then run "git rebase --continue") (use "git rebase --skip" to skip this patch) (use "git rebase --abort" to check out the original branch) Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: frontend/src/App.js modified: frontend/src/main/components/Nav/AppNavbar.js modified: frontend/src/main/pages/Todos/TodosIndexPage.js new file: frontend/src/main/pages/UCSBSubjects/UCSBSubjectsCreatePage.js new file: frontend/src/main/pages/UCSBSubjects/UCSBSubjectsIndexPage.js Unmerged paths: (use "git restore --staged <file>..." to unstage) (use "git add <file>..." to mark resolution) both modified: frontend/package-lock.json pconrad@169-231-112-36 team03-w22-7pm-2 %
-
Now, let’s take stock of what’s happening here.
The file
package-lock.json
is a file that is produced whenever we typenpm install
. What it represents is the transitive closure (yes, in the CS40, CS138 Math 8 discrete math sense of transitive closure) of the dependencies that you have listed inpackage.json
.For example, if your package.json listed these three dependencies:
"axios": "^0.21.1", "babel-loader": "8.1.0", "bootstrap": "^5.0.0-beta3",
Each of these may depend on something else which in turn depends on something else, and so on, and so on.
The transitive closure is the set of all things that
axios
,babel-loader
andbootstrap
depend on, either directly, or transitiveily. It’s computed by continuing to calculate the dependency graph until nothing new is added to the set.At that point, you have the list of dependencies, and you have the specific versions that
npm
went out and found.THAT is what is listed in the
package-lock.json
.So, when you have a merge conflict in
package-lock.json
, rather than trying to resolve it the usual way, which is to go line by line, and try to choose between theincoming
andcurrent
change, it is better to just regenerate it from scrtach.The manual way is to do this:
cd frontend rm package-lock.json rm -rf node_modules npm install
Don’t be surprised if the
rm -rf node_modules
step takes a good long time, as evidenced by this cartoon from Reddit -
At this point, if you type
git status
, you’ll see thatpackage-lock.json
is still marked as “in conflict”. BUT, you’ve just regenerated a clean up-to-date version of the file. So follow the instructions on the screen, and usegit add package-lock.json
to mark it as resolved:pconrad@169-231-112-36 frontend % git status rebase in progress; onto da679f5 You are currently rebasing branch 'rh-subjects_menu_page' on 'da679f5'. (fix conflicts and then run "git rebase --continue") (use "git rebase --skip" to skip this patch) (use "git rebase --abort" to check out the original branch) Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: src/App.js modified: src/main/components/Nav/AppNavbar.js modified: src/main/pages/Todos/TodosIndexPage.js new file: src/main/pages/UCSBSubjects/UCSBSubjectsCreatePage.js new file: src/main/pages/UCSBSubjects/UCSBSubjectsIndexPage.js Unmerged paths: (use "git restore --staged <file>..." to unstage) (use "git add <file>..." to mark resolution) both modified: package-lock.json
That looks like this:
pconrad@169-231-112-36 frontend % git add package-lock.json pconrad@169-231-112-36 frontend % git status rebase in progress; onto da679f5 You are currently rebasing branch 'rh-subjects_menu_page' on 'da679f5'. (all conflicts fixed: run "git rebase --continue") Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: package-lock.json modified: src/App.js modified: src/main/components/Nav/AppNavbar.js modified: src/main/pages/Todos/TodosIndexPage.js new file: src/main/pages/UCSBSubjects/UCSBSubjectsCreatePage.js new file: src/main/pages/UCSBSubjects/UCSBSubjectsIndexPage.js pconrad@169-231-112-36 frontend %
So now, we again follow the instructions on the screen and type
git rebase --continue
What happens next will depend on how many commits you have on your branch. In the case of the branch I used to make these insructions, we got this:
pconrad@169-231-112-36 frontend % git rebase --continue Applying: created menu and pages Applying: storybook Applying: fixed Using index info to reconstruct a base tree... M frontend/package-lock.json Falling back to patching base and 3-way merge... CONFLICT (modify/delete): frontend/package-lock.json deleted in fixed and modified in HEAD. Version HEAD of frontend/package-lock.json left in tree. error: Failed to merge in the changes. Patch failed at 0003 fixed hint: Use 'git am --show-current-patch' to see the failed patch Resolve all conflicts manually, mark them as resolved with "git add/rm <conflicted_files>", then run "git rebase --continue". You can instead skip this commit: run "git rebase --skip". To abort and get back to the state before "git rebase", run "git rebase --abort". pconrad@169-231-112-36 frontend %
So, here, if we type
git status
, we see:pconrad@169-231-112-36 frontend % git status rebase in progress; onto da679f5 You are currently rebasing branch 'rh-subjects_menu_page' on 'da679f5'. (fix conflicts and then run "git rebase --continue") (use "git rebase --skip" to skip this patch) (use "git rebase --abort" to check out the original branch) Unmerged paths: (use "git restore --staged <file>..." to unstage) (use "git add/rm <file>..." as appropriate to mark resolution) deleted by them: package-lock.json no changes added to commit (use "git add" and/or "git commit -a") pconrad@169-231-112-36 frontend %
This is saying that someone deleted
package-lock.json
, and that’s no good! Let’s bring it back! To that we type:npm install
to recalculated it and create a new version of it. We’ll then add that, and typegit rebase --continue
again!pconrad@169-231-112-36 frontend % npm install up to date, audited 2871 packages in 7s 321 packages are looking for funding run `npm fund` for details 37 vulnerabilities (22 moderate, 15 high) To address issues that do not require attention, run: npm audit fix To address all issues (including breaking changes), run: npm audit fix --force Run `npm audit` for details. pconrad@169-231-112-36 frontend % git status rebase in progress; onto da679f5 You are currently rebasing branch 'rh-subjects_menu_page' on 'da679f5'. (fix conflicts and then run "git rebase --continue") (use "git rebase --skip" to skip this patch) (use "git rebase --abort" to check out the original branch) Unmerged paths: (use "git restore --staged <file>..." to unstage) (use "git add/rm <file>..." as appropriate to mark resolution) deleted by them: package-lock.json no changes added to commit (use "git add" and/or "git commit -a") pconrad@169-231-112-36 frontend % pconrad@169-231-112-36 frontend % git add . pconrad@169-231-112-36 frontend % git status rebase in progress; onto da679f5 You are currently rebasing branch 'rh-subjects_menu_page' on 'da679f5'. (all conflicts fixed: run "git rebase --continue") nothing to commit, working tree clean pconrad@169-231-112-36 frontend % git rebase --continue Applying: fixed No changes - did you forget to use 'git add'? If there is nothing left to stage, chances are that something else already introduced the same changes; you might want to skip this patch. Resolve all conflicts manually, mark them as resolved with "git add/rm <conflicted_files>", then run "git rebase --continue". You can instead skip this commit: run "git rebase --skip". To abort and get back to the state before "git rebase", run "git rebase --abort". pconrad@169-231-112-36 frontend %
-
So, now we type
git rebase --skip
to go to the next commit.And guess what, we have the merge conflict in
package-lock.json
yet again. It’s like the movie Groundhog Day.But, we just do the same thing again: once again:
rm package-lock.json
- `npm install
git add package-lock.json
git rebase --continue
We may have to repeat this several times:
- sometimes doing
git rebase --continue
- sometimes doing
git rebase --skip
Until eventually, we get to the point where the rebase is concluded.
When you see this, do
git rebase --skip
:pconrad@169-231-112-36 frontend % git rebase --continue Applying: fixed No changes - did you forget to use 'git add'? If there is nothing left to stage, chances are that something else already introduced the same changes; you might want to skip this patch. Resolve all conflicts manually, mark them as resolved with "git add/rm <conflicted_files>", then run "git rebase --continue". You can instead skip this commit: run "git rebase --skip". To abort and get back to the state before "git rebase", run "git rebase --abort". pconrad@169-231-112-36 frontend %
Eventually, when you type either
git rebase --skip
orgit rebase --continue
, you’ll get back something that looks clean, like this:pconrad@169-231-112-36 frontend % git rebase --skip pconrad@169-231-112-36 frontend %
Or, it might look like this:
❯ git rebase --continue [detached HEAD 5b85f9d] fixed 1 file changed, 447 insertions(+), 1752 deletions(-) Successfully rebased and updated refs/heads/rh-subjects_menu_page.
In either case, you have an indication that the rebase is successful, and you have resolved all merge conflicts.
Now you are ready for the scariest part of the whole thing. You are going to a force push.
-
In a force push, you are telling GitHub: “I know that you think the branch should be somewhere else. But I’m telling you I know better!”
It is potentially a destructive act, because it “rewrites history”. You’ve “rebased your branch” on the current version of
origin main
which means you’ve clipped off all of your commits, and “replayed them” on top of the new version of main.And you’ve resolved the conflicts along the way.
So now, do this:
git push origin rh-subjects_menu_page -f
At that point, go to GitHub and look at your pull request again.
It should restart all of the GitHub Actions scripts. And, the “merge conflict” message should have gone away: