From f5a40e60be2b9fcc99a90f27bdb5a5ccc3954283 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Fri, 8 May 2009 19:54:50 -0500 Subject: [PATCH] add 9-conflicts --- 0-outline | 2 +- 7-tothefuture | 10 +--- 8-thestagingarea | 2 + 9-conflicts | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+), 10 deletions(-) create mode 100644 9-conflicts diff --git a/0-outline b/0-outline index 0dceee8..0b2e34f 100644 --- a/0-outline +++ b/0-outline @@ -8,7 +8,7 @@ A brief list of topics I want to cover, vaguely in order: * 6-alternatetimelines - branches * 7-tothefuture - rebasing * 8-thestagingarea -* TODO: conflict resolution +* 9-conflicts * TODO: collaboration "optional" topics: diff --git a/7-tothefuture b/7-tothefuture index 67f3620..263edae 100644 --- a/7-tothefuture +++ b/7-tothefuture @@ -44,11 +44,7 @@ Git cannot simply move crazyidea to master, as you would lose the work you've do Remember, if you screw this up, you can always find your old commits using "git reflog" (or at least, you can do that until 30 days after they disappear). - -[TODO: somewhere before here I have to explain diffs] - -[TODO: somewhere before here I have to explain the staging area; hopefully once I get conflict resolution it'll make more sense to me] - +[TODO: Remove redundant information about patches?] So, first off, here is how rebase would approach the problem: * Create a list of the commits that are in crazyidea but not in master. @@ -99,7 +95,3 @@ However, the merge only changes the branch you had checked out. The master branch will not have your changes from the crazyidea branch. Just remember, Git will only alter a branch if you have it checked out. - - -[TODO: Apparently I have to explain how to resolve conflicts? Not looking forward to that.] - diff --git a/8-thestagingarea b/8-thestagingarea index 68ed22b..411da60 100644 --- a/8-thestagingarea +++ b/8-thestagingarea @@ -47,3 +47,5 @@ No one would ever have to know it's there. Except for one thing: you have to get your files into the index first or even "git commit -a" will ignore them. So I invented a "tracked files" list and made the claim that "git add" added files to that list. +[TODO: Explain how to stage partial changes?] + diff --git a/9-conflicts b/9-conflicts new file mode 100644 index 0000000..63b65d5 --- /dev/null +++ b/9-conflicts @@ -0,0 +1,144 @@ + +Whenever Git fails to apply a patch, it will put your tree in a state of conflict. + +Up until now, I've advised you to deal with conflicts using the reset command, essentially running away from the problem. + +At this point, I think you're ready to face them head-on. + + +During the conflict, your tree looks like this: +* All of the changes Git could safely make are in the staging area. +* All of the changes Git cannot safely make are marked in your local tree but not the staging area. +* All files with changes Git cannot safely make are marked as "unmerged". + +To resolve the conflict, you must fix the unmerged files and add them to the index. + + +(TODO: make a better conflict than this next one. It's confusing.) + +Conflicting areas are marked in your local tree like this: + +[code] +<<<<<<< HEAD:server/trace.c + fprintf( stderr, " src_process=%04x", req->src_process ); + fprintf( stderr, ", src_handle=%04x", req->src_handle ); + fprintf( stderr, ", dst_process=%04x", req->dst_process ); + fprintf( stderr, ", access=%08x", req->access ); + fprintf( stderr, ", attributes=%08x", req->attributes ); + fprintf( stderr, ", options=%08x", req->options ); +======= + fprintf( stderr, " src_process=%p,", req->src_process ); + fprintf( stderr, " src_handle=%p,", req->src_handle ); + fprintf( stderr, " dst_process=%p,", req->dst_process ); + fprintf( stderr, " access=%08x,", req->access ); + fprintf( stderr, " inherit=%d,", req->inherit ); + fprintf( stderr, " options=%d", req->options ); +>>>>>>> 7b910f4... server: Use attributes instead of inherit flag in dup_handle request.:server/trace.c +[code] + +The <<<<<<< line tells you which revision the first section is from. +The ======= line divides the two sections. +The >>>>>>> line identifies the second section. + +In this case, I created the conflict by reverting a random patch in the Wine project. + +The first section, HEAD, is from my tree as it was when I started the revert. +The second section is from my tree as it was just before the patch I'm reverting. + +To make it more clear what's going on, here's a section from the patch I'm reverting: + +[code] +@@ -846,8 +846,8 @@ static void dump_dup_handle_request( const struct dup_handle_request *req ) + fprintf( stderr, " src_handle=%p,", req->src_handle ); + fprintf( stderr, " dst_process=%p,", req->dst_process ); + fprintf( stderr, " access=%08x,", req->access ); +- fprintf( stderr, " inherit=%d,", req->inherit ); +- fprintf( stderr, " options=%d", req->options ); ++ fprintf( stderr, " attributes=%08x,", req->attributes ); ++ fprintf( stderr, " options=%08x", req->options ); + } +[/code] + +To revert this change, Git must replace "attributes" with "inherit" and change the %08x in each of these lines to %d. + +However, these lines do not exist in HEAD. +From the Git's marking of the conflict, I can see they look like this: + +[code] + fprintf( stderr, ", attributes=%08x", req->attributes ); + fprintf( stderr, ", options=%08x", req->options ); +[/code] + +Since that patch was applied, a comma was moved. + +The solution is to take the first section (my current HEAD), and manually change it as Git would if it could. +As a human, I know the difference in punctuation is unimportant and can be ignored. +The conflicting section now looks like this: + +[code] + fprintf( stderr, " src_process=%04x", req->src_process ); + fprintf( stderr, ", src_handle=%04x", req->src_handle ); + fprintf( stderr, ", dst_process=%04x", req->dst_process ); + fprintf( stderr, ", access=%08x", req->access ); + fprintf( stderr, ", inherit=%d", req->inherit ); + fprintf( stderr, ", options=%d", req->options ); +[/code] + +Now, git diff shows me this odd-looking thing: + +[code] +@@@ -1281,12 -842,12 +1281,12 @@@ static void dump_set_handle_info_reply + + static void dump_dup_handle_request( const struct dup_handle_request *req ) + { + - fprintf( stderr, " src_process=%p,", req->src_process ); + - fprintf( stderr, " src_handle=%p,", req->src_handle ); + - fprintf( stderr, " dst_process=%p,", req->dst_process ); + - fprintf( stderr, " access=%08x,", req->access ); + - fprintf( stderr, " inherit=%d,", req->inherit ); + - fprintf( stderr, " options=%d", req->options ); + + fprintf( stderr, " src_process=%04x", req->src_process ); + + fprintf( stderr, ", src_handle=%04x", req->src_handle ); + + fprintf( stderr, ", dst_process=%04x", req->dst_process ); + + fprintf( stderr, ", access=%08x", req->access ); +- fprintf( stderr, ", attributes=%08x", req->attributes ); +- fprintf( stderr, ", options=%08x", req->options ); +++ fprintf( stderr, ", inherit=%d", req->inherit ); +++ fprintf( stderr, ", options=%d", req->options ); + } +[/code] + +That is a 3-way diff. + +It's Git's way of showing two patches at once. +Instead of a single column of spaces, pluses, and minuses, there are two columns. + +The first column tells how the working tree differs from the first revision, the current HEAD. +The lines that have minuses in the first column are in HEAD but not in the working tree. +The lines that have pluses in the first column are in the working tree but not HEAD. + +Similarly, the second column tells how the working tree differs from the revision before the reverted patch. + +(TODO: I really need to find a better example. This is ugly and confusing.) + +Once the conflict in each file is resolved, let git know by updating the index: + +[code] +$ git add server/trace.c +[/code] + +Once all conflicts are resolved, run +[code] +git commit +[/code] + +If you are doing a rebase, you'll need to run +[code] +git rebase --continue +[/code] + +[TODO: does "git commit" work properly here during a rebase?] + + +[TODO: are merges different in any important way?] + -- 2.11.4.GIT