Fred: So, you know Darcs?
Lisa: Sure.
Fred: I heard it is quite flexible in managing patches. Wanna show me?
Lisa: Ok, let's make a new repository for some imaginary project.
# mkdir project; cd project; darcs init
Fred: Ok, now add these files. A Main
module using some helper
function from a Utilities
module.
# echo define helperFunction > Utilities
# echo import Utilities > Main
# echo use helperFunction >> Main
Lisa: Let's make a patch including all these changes.
# darcs -lam "added initial Main and Utilities"
Fred: I want to add database access. I make a new module and use it in Main.
# echo define access > Database
# echo use Database.access >> Main
Fred: I also add a helper to Utilities
and use it in Database
.
# echo define dbHelper >> Utilities
# echo use dbHelper >> Database
Lisa: Here is a patch for that.
# darcs record -lam "added database access with helper"
Lisa: I add a GUI and use your database helper for that.
# echo import Utilities > GUI
# echo use dbHelper >> GUI
Lisa: I also add another helper function and use it.
# echo define guiHelper >> Utilities
# echo use guiHelper >> GUI
Fred: By now, I know how to make a patch.
# darcs record -lam "added GUI with helper and using DB helper"
Lisa: Let's see what we have until now.
# yes | darcs changes --reverse
[added initial Main and Utilities]
addfile ./Main
hunk ./Main 1
+import Utilities
+use helperFuntion
addfile ./Utilities
hunk ./Utilities 1
+define helperFunction
[added database access with helper]
addfile ./Database
hunk ./Database 1
+define access
+use dbHelper
hunk ./Main 3
+use Database.access
hunk ./Utilities 2
+define dbHelper
[added GUI with helper and using DB helper]
addfile ./GUI
hunk ./GUI 1
+import Utilities
+use dbHelper
+use guiHelper
hunk ./Utilities 3
+define guiHelper
Fred: Ok, I see which files were added by which patch and hunks seem to be changes to the contents of files.
Lisa: Right. Now I want to remove database access but keep the GUI.
Fred: You can't remove the database patch because the GUI patch
depends on it adding the dbHelper
.
Lisa: It would be nice, if Darcs would let me split your patch, so I
can remove your changes to Database
and Main
but keep your changes
to Utilities
. There is no split command but we can do it by hand.
# cd ..; mkdir clone; cd clone; darcs init
# echo yyny | darcs pull ../project
Fred: Now we have a clone containing only the first two patches and can remove the second because nothing depends on it?
Lisa: Right. We can use unrecord for that. Then we record two patches, splitting your changes.
# echo yny | darcs unrecord
# echo nnyy | darcs record -m "added database helper"
# yes | darcs record -m "added database access"
Lisa: Now we can pull the remaining changes. This will also include the original big patch adding database access and the helper function.
# yes | darcs pull project
Fred: So now we are back where we started?
Lisa: But we can now obliterate the big database patch as well as the small one that I don't need for the GUI.
# echo nyyy | darcs obliterate
Fred: Let's see what we have now.
# yes | darcs changes --reverse
[added initial Main and Utilities]
addfile ./Main
hunk ./Main 1
+import Utilities
+use helperFuntion
addfile ./Utilities
hunk ./Utilities 1
+define helperFunction
[added database helper]
hunk ./Utilities 2
+define dbHelper
[added GUI with helper and using DB helper]
addfile ./GUI
hunk ./GUI 1
+import Utilities
+use dbHelper
+use guiHelper
hunk ./Utilities 3
+define guiHelper
Fred: Ok, but that sure was complicated. There should be a split command that does what you just did by hand. Can we now pull back the changes from the clone into our project?
# cd ../project; darcs pull ../clone
darcs: bug at src/Darcs/Patch/Depends.hs:322
Failed to commute common patches:
* added GUI with helper and using DB helper
* added database access with helper
Lisa: Oops! Let's just work in the clone.
Fred: I know how to drastically simplify your GUI implementation. I
don't need the guiHelper
and just delete it from GUI
and
Utilities
.
# sed -i "$ d" Utilities
# sed -i "$ d" GUI
Fred: Let's record that.
# darcs record -am "simplified GUI"
Lisa: There are now two patches for adding the GUI.
# yes | darcs changes --reverse --last=2
[added GUI with helper and using DB helper]
addfile ./GUI
hunk ./GUI 1
+import Utilities
+use dbHelper
+use guiHelper
hunk ./Utilities 3
+define guiHelper
[simplified GUI]
hunk ./GUI 3
-use guiHelper
hunk ./Utilities 3
-define guiHelper
Fred: Hmm, I wish I could merge them into a single patch that just
adds the GUI
file without using guiHelper
.
Lisa: Then you should have used amend-record instead of recording a new patch. Now you can still unrecord and then amend the changes.
# echo yny | darcs unrecord
# yes | darcs amend-record
Fred: But unrecording would not work if there were already other patches depending on the simplified GUI.
Lisa: Right. That would complicate things again. Seems like there should be a merge command. Or can splitting and merging be implemented using rebase for Darcs?
Fred: Well, you said you know Darcs!