Tortoise Git - lost commits after a pull resulted in conflicts

前端 未结 2 1899
悲哀的现实
悲哀的现实 2021-01-16 04:26

This SO question perfectly describes our situation: What is the right way to commit/push when there are conflicts in Git or TortoiseGit?

There is no answer (atleast

相关标签:
2条回答
  • 2021-01-16 04:55

    For everyone's benefit, this is the strategy that I have resorted to that seems to work well for us.

    1. If a Git pull, results in a conflict, resolve the conflict locally.
    2. Ensure there are no remaining files that are conflicted.
    3. Do a Git pull again.
    4. Goto Step 2 if you again get a conflict.

    Basically you try to resove conflicts and do a Git pull and keep on doing this until a Git pull completes successfully with no conflicts (effectively meaning your commit head now is updated to the remote commit head).

    A change of mindset is needed when addressing conflicts if you are coming from a SVN background. In SVN, a merge conflict during an update does not abort the SVN update process. SVN client would still update your local copy to the latest remote revision. Only individual files would be left in conflicted state that you can resolve (and commit back if needed).

    So a conflict still means all local files that were not conflicted are up--to-date with the remote repo after an update.

    In Git, a conflict during pull simply terminates/aborts the update process. So if the remote repo had 10 commits that need to be pulled, and you get a conflict when Git was pulling (and merging) the 3rd of these commits, effectively the process is aborted. 8 of the remote commits are NOT in your local repo (note the remote commit that caused a conflict also isn't merged successfully, so its 8 commits that are not synced locally and not 7).

    You resolve conflicts and keep doing a git pull until successful thus preventing you from overwriting other commits. To provide a bit more details from what I have understood about git, a push without resolving the conflict would cause the remote branch's commit head to be relocated incorrectly. e.g. suppose you need to pull 4 revisions from a Git repo:

    A - B - C - D
                |- commit head
    

    Now suppose you get a conflict while pulling and merging Revision B. If you do a push now to remote (without resolving the conflicts and doing a git pull until successful), the remote repo now looks like this:

    A - B - C - D
        |- E - commit head
    

    So effectively although commits C/D exist remotely, they won't be a part of your build based on the branch's commit head. If you follow @CupCake's advice and push the remaining files, commits C/D become a part of commit E sort of. So that doesn't impact your correctness of the build. But if you don't push those files after conflict which you don't changed but Git was showing as modified (because you did not resolve the conflict and completed a successful git pull), then effectievly you are leading to lost commits.

    0 讨论(0)
  • 2021-01-16 05:05

    I'm going to address your questions line by line:

    On occasional conflicts, I thought we can always resolve locally and then make another local commit and remote push.

    Yes, that's correct.

    Now a colleague committed locally and was trying to push resulting in a conflict. She pulled, resolved conflicts and then ONLY pushed her changed files. The remote repo had another commit saying merge branch with some files that is effectively undoing my commits earlier. Is this expected?

    Yes, it's expected (i.e. I'm not surprised), though that doesn't mean that what your coworker did was correct. Your coworker basically threw away all the work you did previously with that mege commit. I shall explain.

    When git detects conflicts that it can't figure out how to auto-resolve during an attempted merge, it aborts the merge midway, leaving un-conflicted files added to your staging area, and leaving conflicted files with conflict markers un-staged in your working copy.

    For example, this is what a merge that results in conflicts looks like from the command line:

    git status
    
    On branch master
    You have unmerged paths.
      (fix conflicts and run "git commit")
    
    Changes to be committed:
    
            modified:   hello.txt
    
    Unmerged paths:
      (use "git add <file>..." to mark resolution)
    
            both modified:      foo.txt
    

    Notice that git has automatically staged hello.txt to be committed, because it doesn't have any conflicts. I haven't used TortoiseGit in over 1.5+ years, but if my memory serves me correctly, staged files are represented in TortoiseGit with checked-checkboxes, which means you want to commit those files.

    Un-checking those automatically-staged checkboxes is incorrect, in this case. It basically means that you don't want to commit those file changes that you've just merged in from the other branch (or in your case, from the upstream remote/origin). It's essentially throwing away the work that was done on those files.

    The correct way to merge, in this case, would be to resolve the conflicted files, and then add them to the staging area to be committed, along with all the other file changes that are already there, even if you were not originally responsible for those changes.

    How are we supposed to work locally and then re-sync once in a while.

    That's up to how you and your team want to organize your workflow.

    If I have committed locally, and a subsequent pull results in a conflict, how do I ensure I merge correctly so I don't undo previous commits on the remote repo.

    Unless you have a good reason not to, as I've already said, you usually want to commit all the files, even if you weren't originally reponsible for the changes to them. Not doing so essentially means that you don't actually want to keep those changes.

    0 讨论(0)
提交回复
热议问题