~jan0sch/darcs-book
Showing details for patch d5466d79702ae864cdc6157e4da6ea258274f468.
diff -rN -u old-darcs-book/en/06-conflict-management.md new-darcs-book/en/06-conflict-management.md --- old-darcs-book/en/06-conflict-management.md 2024-11-23 23:34:58.416776570 +0000 +++ new-darcs-book/en/06-conflict-management.md 2024-11-23 23:34:58.416776570 +0000 @@ -319,3 +319,170 @@ would not conflict we would have pulled them in only leaving out the culprit. This is one of the nice and powerful properties of **patch based** version control systems like `darcs`. + +Avoiding conflicts with `replace` +--------------------------------- + +In chapter 3 we were introduced to the `replace` change and until now it got +relatively little attention. I would like to show you a very nice application of +this kind of change that allows us to reduce the attack surface for conflicts. + +As a simple example I'm going write a simple piece of Haskell code that only +contains a function called `foo`. + +``` +$ cat Fun.hs +foo :: Int -> Int +foo x = x + 1 +``` + +I'm working on this piece of code with my friends alexej and bodems. They both +have a copy of my repository and apply the following changes to it. + +alexej wants the `foo` function to be a little more generic so they change the +type signature of the function to reflect that. + +``` +$ darcs log --last 1 -v +patch 9ca832bb0187d46d37e129b05837af39275246f4 +Author: alexej@example.com +Date: Tue Jul 3 11:41:22 CEST 2018 + * make foo more generic + hunk ./Fun.hs 1 + -foo :: Int -> Int + +foo :: Num a => a -> a +``` + +By doing this alexej introduced a `hunk` that replaces the first line of the +file with a new one that features the more generic type signature. + +bodems thinks that the name `foo` is just not descriptive enough. So they change +it by introducing the following change. + +``` +$ darcs log --last 1 -v +patch 592af55bbf1395376c745fffc47da598e3233149 +Author: bodems@example.com +Date: Tue Jul 3 11:41:04 CEST 2018 + * give foo an appropriate name + hunk ./Fun.hs 1 + -foo :: Int -> Int + -foo x = x + 1 + +inc :: Int -> Int + +inc x = x + 1 + +``` + +Once again `darcs` uses a hunk change to reflect that change and swaps out +entire lines just to change the name. + +Now I come along to pull in both of their changes. I'm careful and therefore +using the `--dry-run` flag of `pull` to take a brief look at their changes +first. + +``` +$ darcs pull --dry-run -v \ + https://hub.darcs.net/bodems/project \ + https://hub.darcs.net/alexej/project +They have the following patches to pull: +patch 592af55bbf1395376c745fffc47da598e3233149 +Author: bodems@example.com +Date: Tue Jul 3 11:41:04 CEST 2018 + * give foo an appropriate name +patch 9ca832bb0187d46d37e129b05837af39275246f4 +Author: alexej@example.com +Date: Tue Jul 3 11:41:22 CEST 2018 + * make foo more generic +Would pull the following changes: +patch 592af55bbf1395376c745fffc47da598e3233149 +Author: bodems@example.com +Date: Tue Jul 3 11:41:04 CEST 2018 + * give foo an appropriate name + hunk ./Fun.hs 1 + -foo :: Int -> Int + -foo x = x + 1 + +inc :: Int -> Int + +inc x = x + 1 + +patch 9ca832bb0187d46d37e129b05837af39275246f4 +Author: alexej@example.com +Date: Tue Jul 3 11:41:22 CEST 2018 + * make foo more generic + conflictor [ + hunk ./Fun.hs 1 + -foo :: Int -> Int + -foo x = x + 1 + +inc :: Int -> Int + +inc x = x + 1 + ] + : + hunk ./Fun.hs 1 + -foo :: Int -> Int + +foo :: Num a => a -> a + +Making no changes: this is a dry run. +``` + +Oh snap! We have a conflict! Not really surprising when we consider that both +changes are changing the sames lines of code. + +Now thankfully Sandra comes along, being very good at solving conflicts they use +`replace` instead of a plain `hunk`. + +``` +$ darcs replace foo inc Fun.hs +$ darcs whatsnew +replace ./Fun.hs [A-Za-z_0-9] foo inc +$ darcs record -a -m 'give foo an appropriate name' +Finished recording patch 'give foo an appropriate name' +``` + +No when I pull in this patch instead of the one bodems made this is going to +happen. + +``` +$ darcs pull --dry-run -v \ + https://hub.darcs.net/sandra/project \ + https://hub.darcs.net/alexej/project +They have the following patches to pull: +patch 9ea86844a018aeb9c7cf96657d0466960787b359 +Author: sandra@example.com +Date: Tue Jul 3 12:00:09 CEST 2018 + * give foo an appropriate name +patch 9ca832bb0187d46d37e129b05837af39275246f4 +Author: alexej@example.com +Date: Tue Jul 3 11:41:22 CEST 2018 + * make foo more generic +Would pull the following changes: +patch 9ea86844a018aeb9c7cf96657d0466960787b359 +Author: sandra@example.com +Date: Tue Jul 3 12:00:09 CEST 2018 + * give foo an appropriate name + replace ./Fun.hs [A-Za-z_0-9] foo inc + +patch 9ca832bb0187d46d37e129b05837af39275246f4 +Author: alexej@example.com +Date: Tue Jul 3 11:41:22 CEST 2018 + * make foo more generic + hunk ./Fun.hs 1 + -inc :: Int -> Int + +inc :: Num a => a -> a + +Making no changes: this is a dry run. +``` + +VoilĂ ! No conflicts at all! `darcs` could figure out that these changes do not +conflict because of the properties of the `replace` change. If I'd `pull` in +those patches my `Fun.hs` would have changed based on both of my collaborator's +changes. + +``` +$ cat Fun.hs +inc :: Num a => a -> a +inc x = x + 1 +``` + +`replace` changes are quite unique to `darcs`. I have yet to find another +version control system that features this. On the other hand they do not make a +lot of sense in **snapshot based** version control systems anyway, whereas in a +**patch based** system they do.