~jan0sch/darcs-book

Showing details for patch a2ae80284727abf3d058a5159be6915914522dac.
2018-07-19 (Thu), 7:52 PM - - a2ae80284727abf3d058a5159be6915914522dac

add new chapter 7

Summary of changes
2 files added
  • en/07-dependencies-and-good-patches.md
  • img/branches.png
1 files modified with 6 lines added and 3 lines removed
  • Makefile with 6 added and 3 removed lines
diff -rN -u old-darcs-book/en/07-dependencies-and-good-patches.md new-darcs-book/en/07-dependencies-and-good-patches.md
--- old-darcs-book/en/07-dependencies-and-good-patches.md	1970-01-01 00:00:00.000000000 +0000
+++ new-darcs-book/en/07-dependencies-and-good-patches.md	2024-11-23 20:35:48.682781430 +0000
@@ -0,0 +1,220 @@
+Dependencies and good patches
+=============================
+
+I think this is a good place to take a little breath and start talking about
+patches and how to actually create a good history. This can be a tricky task to
+accomplish but it's worth it in the long run. Think of your set of patches as
+little building blocks from which you build a whole project, it'll help you
+later when you might want to track down a problem. A cleanly crafted set of
+patches can be extremely helpful here. Maybe a patch has introduced a bug if the
+patch is self-contained you can simply `rollback` that single patch and you can
+start thinking about a better way to solve the issue than this patch did. Or you
+can just pick some patches that you are really interested in without pulling in
+other ones that might currently just interfere with your work.
+
+In this chapter we will take a look at some more details about patches and some
+thought about how to create good patches.
+
+Dependencies in `darcs`
+-----------------------
+
+First we should take a step back and take a look at how `darcs` looks at our
+patches again. Whenever we take a look at our changes with `darcs log`
+everything is presented to us in a linear fashion, but that's not the only way
+we can think of organizing our patches. We now have heard numerous times that a
+"repository's state is defined by a set a changes". We have also heard what it
+means when to patches `A` and `B` commute, namely that it does not matter in
+which order we apply them. Until now we didn't really exploit these properties
+of `darcs` that much. So let's talk a little bit about dependencies so we can
+get the most out of recording and crafting our patches.
+
+To illustrate how patches can depend on each other in `darcs` let's create a
+very simple repository with two files called `A` and `B`. First we are going to
+`add` these two files and then we are going to change their contents.
+
+```
+$ touch A B
+$ darcs add A
+Adding 'A'
+$ darcs record -m 'add A' -a
+Finished recording patch 'add A'
+$ darcs add B
+Adding 'B'
+$ darcs record -m 'add B' -a
+Finished recording patch 'add B'
+$ echo A >> A
+$ darcs record -m 'change A' -a A
+Recording changes in: "A"
+Finished recording patch 'change A'
+$ echo B >> B
+$ darcs record -m 'change B' -a B
+Recording changes in: "B"
+Finished recording patch 'change B'
+patch 376b1bc0febb10802797a5afe7d55e35e42ac89f
+Author: raichoo@example.com
+Date:   Mon Jul  9 19:04:01 CEST 2018
+  * change B
+
+patch 1f9b4b1566ce3410c70ad5231ff21abb0dfed04b
+Author: raichoo@example.com
+Date:   Mon Jul  9 19:02:49 CEST 2018
+  * change A
+
+patch 0d87b94c8d03fea3a2b613c43032df8da8cbff93
+Author: raichoo@example.com
+Date:   Mon Jul  9 19:02:02 CEST 2018
+  * add B
+
+patch 0b2f173ea79d311c34d8e321b6a8d86582d18ff4
+Author: raichoo@example.com
+Date:   Mon Jul  9 19:01:03 CEST 2018
+  * add A
+```
+
+Nothing too surprising has happened here. We have added some files and then we
+have changed them. Everything looks nice and linear. But let's take a look at
+how these patches depend on each other.
+
+`darcs show dependencies` will give us some `graphviz` output that we can pipe
+into the `dot` command to generate a visual representation of all the patch
+dependencies in our repository. The command to do this looks like this.
+
+```
+darcs show dependencies | dot -Tpng -o dependencies-1.png
+```
+
+For our little example repository `darcs` and `dot` will generate a `png` file
+that looks like this.
+
+![](../img/dependencies-1.png)
+
+Huh, now that looks radically different. Let's talk about what this output
+actually means. We see that `change B` depends on `add B` and `change A` depends
+on `add A`. That's not really surprising. You can only really change a file
+after you have added it. Makes sense doesn't it. But how does `darcs` figure out
+what patches depend on each other? It's quite simple. Remember when we talked
+about **commuting patches**. To patches `A` and `B` commute if we can apply them
+to our repository in any order and end up with the same result. Now that's
+clearly not the case for our patches above. I can't change a file that isn't
+there, therefore I have to `add` it before changing it. These to patches do not
+commute, and this is what we call a **dependency**. You need to satisfy all the
+dependencies of a patch before you can apply it.
+
+In our dependency graph you can also see that all our changes concerning the
+files `A` and `B` are totally independent from each other. So I could pull only
+the changes concerning `B` from the repository while ignoring the changes
+regarding `A` altogether. This is an incredibly powerful mechanism that
+**snapshot based** version control systems do not have. Now you can pull in a
+set of patches and ignore all those that don't depend on the change you are
+currently interested in. Other version control systems like `git` for example
+call this **cherry picking**, but compared to `darcs` they are suffering from
+some short comings. In those version control system you re-record the patch when
+you **cherry pick** it. That means that its whole identity changes, one way in
+which this manifests is that it will get a different hash. So even though it's
+the exact same change the patches are now different. This can become quite
+annoying when working in a distributed setting, with `darcs` this is a complete
+non-issue.
+
+Let's play some more with this. We now want to change file `A` but let's pretend
+that we are referencing something that is in file `B` (maybe a function, or a
+paragraph).
+
+```
+$ echo use B >> A
+$ darcs record -m 'use B' -a A
+```
+
+![](../img/dependencies-2.png)
+
+Darn, that's not really what we wanted. Now we have a change in file `A` that
+depends on file `B` being present, but `darcs` has no understanding of the
+semantics of a file's content. This is problematic because if someone decided to
+pull in the `use B` patch without pulling in all our `B` patches the state of
+our repository would not make sense. You can't use anything in `B` if it isn't
+there, makes sense doesn't it? But fear not, we can instruct `record` to prompt
+us for dependencies, so we can inform `darcs` about semantic relationships
+between patches. So let's try again!
+
+```
+$ darcs record --ask-deps -m 'use B' -a A
+Recording changes in: "A"
+hunk ./A 2
++use B
+Shall I record this change? (1/1)  [ynW...], or ? for more options: y
+Do you want to Record these changes? [Yglqk...], or ? for more options: y
+patch 376b1bc0febb10802797a5afe7d55e35e42ac89f
+Author: raichoo@example.com
+Date:   Mon Jul  9 19:04:01 CEST 2018
+  * change B
+Shall I depend on this patch? (1/2)  [ynW...], or ? for more options: y
+Will not ask whether to depend on 1 already decided patch.
+Do you want to Depend on these patches? [Yglqk...], or ? for more options: y
+Finished recording patch 'use B'
+```
+
+The `--ask-deps` flag instructs `darcs` to prompt us for dependencies and we
+tell it that we want our new patch to depend on the patch `change B`. Now the
+dependency graph looks like this.
+
+![](../img/dependencies-3.png)
+
+This gives us unprecedented control over our patches. We now can enrich them
+with semantic information and our collaborators can leverage that information to
+mix and match patches to their liking. Want to `pull` in one feature but not the
+other one because it's still too experimental for you, or maybe clashes with
+some feature you are working on? You can do that now, and all of that while
+maintaining the identity of patches. This is one of the true powers of `darcs`.
+
+A thought on patches
+--------------------
+
+I want to talk a little bit about "good practices" regarding patches here. If
+you are just starting out with version control you might find it hard to figure
+out what goes into a patch, in the beginning you might start out just randomly
+recording patches with everything new you have and move along. I'm not
+going to lie, even for experienced developers, crafting good patches can be
+somewhat of a challenge.
+
+The most important thing is to try to make patches that make sense. That sounds
+deceptively easy but this can be a bit tricky. Each patch should constitute unit
+of work, so if you were to apply it and it's dependencies, the resulting working
+tree should also make sense.
+
+So what does it mean for a set of changes in our repository to make sense? In
+some cases this question is easy to answer in others it's sadly not that simple.
+When it comes to a software project, I usually try to make patches and their
+dependency not break the project. So no matter which patches I `pull` in, the
+project should always compile and work as expected. If your project is not code
+this might become a little harder, like when you are writing a text. If you want
+to change something throughout your project it makes sense to turn that single
+change into one patch, here we might think about "making sense" in another way.
+Like in an earlier example we talked about writing a novel and then renaming the
+protagonist. A patch that would only perform the renaming on a couple of pages
+would not be very useful, a better patch would do that throughout the existing
+parts of the novel. This is a very useful approach because if you change your
+mind, it gets a lot easier to `rollback` all of the changes you have decided
+against.
+
+Writing good patches is takes a lot of experience and practice but it's a
+valuable skill to train. `darcs` is a VCS that rewards good patches by allowing
+you to *cherry pick** in a way no other VCS can, so striving for good patches is
+something that you want to keep in mind, especially if you are working with
+others on a team. Your fellow cooperators will be thankful.
+
+Spontaneous branches
+--------------------
+
+One way where this becomes really quite powerful is something that we call
+**spontaneous branches**. If you look at a repository where you are working on a
+lot of things at the same time you might see a lot of "loose end" in your
+dependency graph. Take a look at this.
+
+![](../img/branches.png)
+
+So here you can see a repository where were are tracking the development of 3
+different features `A`, `B` and `C`. Since `darcs` knows about dependencies we
+can work on each of these features separately without interfering the others. I
+someone else chooses to work on feature `A` and we are working on feature `B` we
+can do that in a single repository without getting in each others way. Not many
+version control systems can do that without changing the identity of the patches
+involved which makes working in distributed teams a lot harder.
Binary files old-darcs-book/img/branches.png and new-darcs-book/img/branches.png differ
diff -rN -u old-darcs-book/Makefile new-darcs-book/Makefile
--- old-darcs-book/Makefile	2024-11-23 20:35:48.682781430 +0000
+++ new-darcs-book/Makefile	2024-11-23 20:35:48.682781430 +0000
@@ -19,14 +19,17 @@
 	${PANDOC} -V prev:chapter04 -V next:chapter06 en/05-a-little-help-from-my-friends.md -o dist/chapter05.html
 
 dist/chapter06.html: dist
-	${PANDOC} -V prev:chapter05 en/06-conflict-management.md -o dist/chapter06.html
+	${PANDOC} -V prev:chapter05 -V next:chapter07 en/06-conflict-management.md -o dist/chapter06.html
+
+dist/chapter07.html: dist
+	${PANDOC} -V prev:chapter06 -V next:chapter08 en/07-dependencies-and-good-patches.md -o dist/chapter07.html
 
 dist/chapter08.html: dist
-	${PANDOC} -V next:chapter09 en/08-rewriting-history.md -o dist/chapter08.html
+	${PANDOC} -V prev:chapter07 -V next:chapter09 en/08-rewriting-history.md -o dist/chapter08.html
 
 dist/chapter09.html: dist
 	${PANDOC} -V prev:chapter08 en/09-tag-youre-it.md -o dist/chapter09.html
 
-all: dist/chapter01.html dist/chapter02.html dist/chapter03.html dist/chapter04.html dist/chapter05.html dist/chapter06.html dist/chapter08.html dist/chapter09.html
+all: dist/chapter01.html dist/chapter02.html dist/chapter03.html dist/chapter04.html dist/chapter05.html dist/chapter06.html dist/chapter07.html dist/chapter08.html dist/chapter09.html
 clean:
 	rm -r dist