Aargh! Every Git file update generates a merge conflict

Every time I change a Git file, I get a merge conflict. I thought the idea was for Git to take a sort of snapshot of the file and apply any changes it. No one has edited these files since my last commit. So why doesn’t Git assume that the new file supersedes the old? Do I really have to sort out a merge conflict every time I make a minor file update? Is that the intended process??

Then there’s the question of how to settle the merge conflict. Git helpfully presents side-by-side windows showing the differences. But that preview is worthless, since the content in those windows isn’t editable. One tutorial said you could save it as merge.txt, but in Bitbucket I don’t see any way to do that.

I feel like I’m missing something totally obvious, but I’ve read 20+ posts on this today, and no one explains how to do a simple file update.

FYI, I’m using Mac OS Mojave, 10.14.06. I’m creating the PRs in Bitbucket but doing everything else from the command line.

Are you on the same branch as you were when you made your last commit? If you are currently working with an old version of the files, then the updated version will see conflict.

It’s hard to debug here without more information on the specifics. However, it definitely isn’t the intended process - merge conflicts happen when something has gone wrong; you don’t normally need to deal with them.

If you share more information (branches, the specific conflicts, etc.), it will help find your issue.

2 Likes

[I’m assuming you mean the files in your project that are tracked by git, not the git files themselves]

So you get merge conflicts when the branch you are trying to merge your changes into has newer changes [that you do not have in your code] than the ones you have made in your code. So to be getting this as a single user on every file means something is wrong with the state: I can empathise because I’ve been in the same position (and I guess most people who have used got for any long period of time have faced a similar issue), and it means something has got out of sync, maybe from a bad commit, or a force commit, or a rebase or…something. It’s difficult to tell, and as you’ve found it’s difficult to Google because it’s likely very specific to something you did at some point. You need to ensure that your branch is ahead of the one you’re merging into, so it may simply involve pulling then pushing, or rebasing, or going back to the last good merge and carefully replaying the changes since (possibly, and painfully, doing it manually) or even taking the nuclear option and reinitialising git and wiping out the history, and even making a new repo.

As an aside, install a git extension into your editor/ide. That should provide a diff view on git commits, and for conflicts lets you pick which change you want to keep to resolve the conflict.

1 Like

As @DanCouper said, I have no insight into your specific cause here because it sounds like something very odd has happened.

If you are the only one working on this repo, then just getting it working again by reinitialising the repo could be a sensible idea. You’ll lose your git history, but if that doesn’t matter for you in this instance than it’ll lead to the least heartache.

You wouldn’t be able to do that on a professional repo, most likely, so you can decide what is more important to you today: fix the immediate problem quickly and get on with learning what you were trying to learn; or take a detour and learn one of the more esoteric features of git and know that if you can document it well enough that you can learn from it you’ll basically be a mini-git wizard and know at least one thing that will impress seasoned devs who still find this stuff tricky to resolve.

(Aside: It’s probably worth creating some branches to test resolving this conflict on. Literally branch off master and attempt to merge your current changes into that branch - when you figure out what works on your throwaway branches, it’ll work on master too. The trouble with trying everything you can think of on master is that you could just end up getting even more tangled.)

VSCode has a pretty good UI for dealing with merge conflicts - it presents the conflicted file and has little links above the conflicted sections allowing you to pick the current state, the incoming changes, or both. You can also edit them as you see fit, just remember to remove all the markers etc and save before recommitting.

If the VSCode one doesn’t suit you, GitKraken also has a really nice UI for merge conflicts - it’s a little more fully featured and gives you a little more control over what lines get included or not from each version, and the order they appear in.

Good luck, git merges can be very challenging, so don’t be too disheartened if you find the solution does to you!

2 Likes

Hi, @JacksonBates, @DanCouper, and @Peritract:

I’m not sure whether or how I can reply to all of you at once, but I really appreciate your thorough responses. I was away visiting relatives last night, so I wasn’t able to reply until today. Please let me give you some more info. First, I’m a tech writer, not a dev, which probably explains a lot. But I need to use Git for our API dev portal documentation. So it is a professional repo, not one I can freely experiment on. I’m the only person who works on the docs branch, though. It’s super important that I understand how to merge files smoothly into Git. Becoming a “mini-git wizard” is my goal!

Here’s a summary of what I did to create this snafu:

  • I converted my documentation plan to Markdown and updated the README file (as requested by a team member). I saved the new document (the documentation plan) and the updated document (the README), along with the images that appear in the documents, in a new folder on my desktop called “doc-plan.”

  • Having just gotten a new computer, I had to get new SSH keys etc. and then clone the main repo (ddd-api) again. The repo contains a branch called ddd-api-docs.

  • I dragged the files from doc-plan into the docs directory and then did a git add . to stage them.

  • Next I did a 'git commit -m “Update README.md and add documentation plan.”

  • Then I created a PR.

In looking this over again, I see that the PR has somehow picked up not just this current commit, but also half a dozen old commits that I squashed to fix some earlier glitch. That must be what’s causing the problem. So my questions now are (1) How do I detach and delete all those earlier commits and (2) Did I do everything else correctly?

Thank you so much! I’m so grateful for your help.

Melissa

1 Like

Your PR contains all the changes that were made from the point where you branched off. New work should be done on a new branch, from the most up-to-date version of master (usually the master branch anyway – if not, the dev team will tell you).

Git has a “feature” that flattens merges from a branch with no possible conflicts (where no edits were made to the base branch) and often these changes will show up in your history. There’s not much you can do about this rewriting of history, but be assured that git won’t apply any changes you didn’t make.

1 Like

OK, so those earlier commits are listed as being part of the PR, but only my most recent changes will be made?

Are you saying that I don’t need to use the docs branch every time—that I can just delete it? So in this case, I could’ve just initialized my doc-plan folder as a new branch and merged it into the clean, freshly cloned master?

Thank you!

I do use long-term branches sometimes for experiments or for editing things that are parallel to our usual ticket-based workflow, which is always one branch per ticket. Such parallel branches include, well, updating docs.

You can re-push such long-term branches and create a new PR off of them, but when you do that, always be sure to first merge the latest master into your branch using git merge master. The longer you wait between merges from master, the more and worse conflicts tend to become.

Generally speaking though, it’s better to use lots of short-lived branches, one for each “task” (however you define it, but it should be a limited-scope thing), both to avoid merge conflicts and just to keep things better-organized overall.

If you’re still experiencing a lot of merge conflicts, can you share what command line commands you’re using that generate them?

1 Like

This sounds really helpful. I like the idea of starting with a fresh branch each time. I won’t know if it’s working til I try it, of course, and I need to fix this mess first. Is there a way to cancel those earlier commits?

Here, sans identifying data, is my ugly terminal window for the last few attempts:

docs melissa.xxxx$ git status
On branch master
Your branch is ahead of ‘origin/master’ by 1 commit.
(use “git push” to publish your local commits)
nothing to commit, working tree clean
docs melissa.xxxx$ git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 240 bytes | 240.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0)
remote: ----------------------------------------------------
remote: Branch refs/heads/master can only be modified through pull requests.
remote: Check your branch permissions configuration with the project administrator.
remote: ----------------------------------------------------
To ssh://git.tcc.li:7999/ddd/ddd-api.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to ‘ssh://git@git.tcc.li:7999/ddd/ddd-api.git’
docs melissa.xxxx$ git merge master
Already up to date.
docs melissa.xxxx$ cd
~ melissa.xxxx$ cd ddd-api
ddd-api melissa.xxxx$ git pull
Already up to date.

You’re not on a branch. Your repo admin has locked the master branch to pushes, so you must make all changes by merging to master. This is the workflow you should generally be doing:

$ git checkout master
$ git pull
$ git checkout -b my-new-branch-name
# ... do some work on it ...
$ git add .     # or git add file1 file2 ... however you prefer
$ git commit -m "commit message"
$ git push

If you’re using something like bitbucket or github enterprise, you’ll get a link to create a new PR, otherwise head to your repo and create one.

Don’t forget the first two steps when creating a new branch: you always want to branch from the latest master. I’ve forgotten a few times and branched off of a branch. Which has its uses, but it can get ugly merging it back to master.

1 Like

Fantastic! I’ll give it a shot. I’ll ping you and let you know how it goes. Thank you so much.

To get rid of all those stray commits, I’m going to do a git reset --hard to the last good commit. Then I’ll follow your suggested workflow. When I execute the reset command, should I be in the docs directory?

Git commands don’t change the directory you’re in. Just cd docs and you’re all good. You can do the reset from anywhere in your project.

1 Like

I’m hugely frustrated. I did the git reset --hard back to the last good merge. It says the head has been reset to that merge. But all my bad commits are still in the PR queue, including the very latest one that I made yesterday (which was actually the only good one). What am I doing wrong??? Where’s the Cmd+Z on this thing?

Okay, here’s an update: I still don’t know what went wrong, but I threw myself at the mercy of one of the engineers here—someone who can actually look at my terminal and commits in Bitbucket. (Without seeing my screen, it must be very hard to figure out what’s going on!) He suggested cherrypicking that one good commit by creating a new branch (off the master). Tomorrow he’s going to help me figure out how to get rid of those stubborn commits in the existing branch. I’ll post an update then.

Your input was actually really helpful, Chuck, as I was hashing things out with the engineer. For example, he was going to push to the master, and I told him I couldn’t do that because of a permissions issue. Then I showed him your suggested workflow, which he agreed I should follow once we get these stray commits cleaned up. So despite my frustration, I know a little more than I did yesterday. I literally learn something new every day—that’s why I love working in this field! :smiling_face_with_three_hearts:

1 Like

Okay, resolved. Even when executing a cherry-pick, Bitbucket picked up the old commits. We still don’t know why, but the lesson learned here is to (1) keep my branch up to date with the master as I go, rather than bringing it up to speed only before submitting a PR, and (2) delete old branches after merging.

Thanks again for your help!

1 Like

Glad you got it working, cheers! Sometimes git does get in a really wedged state that no amount of local git commands can seem to fix. In that case, I tend to just backup my old repo, wipe it out, clone it fresh from upstream, and pick out the changes I need from the backup by hand.

git can be a real PITA sometimes. I kind of wish Mercurial had won the VCS wars instead, but alas.