delete squash.md

This commit is contained in:
Mitchell Rosen 2024-06-26 12:27:49 -04:00
parent c5f4d6d5b7
commit 94580cc218
2 changed files with 0 additions and 686 deletions

View File

@ -1,157 +0,0 @@
```ucm:hide
.> builtins.merge
```
# Squash merges
`squash src dest` merges can be used to merge from `src` to `dest`, discarding the history of `src`. It's useful when the source namespace history is irrelevant or has a bunch of churn you wish to discard. Often when merging small pull requests, you'll use a squash merge.
Let's look at some examples. We'll start with a namespace with just the builtins. Let's take a look at the hash of this namespace:
```ucm
.> history builtin
.> fork builtin builtin2
```
(We make a copy of `builtin` for use later in this transcript.)
Now suppose we `fork` a copy of builtin, then rename `Nat.+` to `frobnicate`, then rename it back. Notice this produces multiple entries in the history:
```ucm
.> fork builtin mybuiltin
.mybuiltin> rename.term Nat.+ Nat.frobnicate
.mybuiltin> rename.term Nat.frobnicate Nat.+
.mybuiltin> history
```
If we merge that back into `builtin`, we get that same chain of history:
```ucm
.> merge.old mybuiltin builtin
.> history builtin
```
Let's try again, but using a `merge.squash` (or just `squash`) instead. The history will be unchanged:
```ucm
.> merge.old.squash mybuiltin builtin2
.> history builtin2
```
The churn that happened in `mybuiltin` namespace ended up back in the same spot, so the squash merge of that namespace with our original namespace had no effect.
## Another example
Let's look at a more interesting example, where the two namespaces have diverged a bit. Here's our starting namespace:
```unison:hide
x = 1
```
```ucm
.trunk> add
.> fork trunk alice
.> fork trunk bob
```
Alice now does some hacking:
```unison:hide
radNumber = 348
bodaciousNumero = 2394
neatoFun x = x
```
```ucm
.alice> add
.alice> rename.term radNumber superRadNumber
.alice> rename.term neatoFun productionReadyId
```
Meanwhile, Bob does his own hacking:
```unison:hide
whatIsLove = "?"
babyDon'tHurtMe = ".. Don't hurt me..."
no more = no more
```
```ucm
.bob> add
```
At this point, Alice and Bob both have some history beyond what's in trunk:
```ucm
.> history trunk
.> history alice
.> history bob
```
Alice then squash merges into `trunk`, as does Bob. It's as if Alice and Bob both made their changes in one single commit.
```ucm
.> merge.old.squash alice trunk
.> history trunk
.> merge.old.squash bob trunk
.> history trunk
```
Since squash merges don't produce any merge nodes, we can `undo` a couple times to get back to our starting state:
```ucm
.> undo
.> undo
.> history trunk
```
This time, we'll first squash Alice and Bob's changes together before squashing their combined changes into `trunk`. The resulting `trunk` will have just a single entry in it, combining both Alice and Bob's changes:
```ucm
.> merge.old.squash alice bob
.> merge.old.squash bob trunk
.> history trunk
```
So, there you have it. With squashing, you can control the granularity of your history.
## Throwing out all history
Another thing we can do is `squash` into an empty namespace. This effectively makes a copy of the namespace, but without any of its history:
```ucm
.> merge.old.squash alice nohistoryalice
.> history nohistoryalice
```
There's nothing really special here, `squash src dest` discards `src` history that comes after the LCA of `src` and `dest`, it's just that in the case of an empty namespace, that LCA is the beginning of time (the empty namespace), so all the history of `src` is discarded.
## Checking for handling of deletes
This checks to see that squashing correctly preserves deletions:
```ucm
.delete> builtins.merge
.delete> fork builtin builtin2
.delete> delete.term.verbose builtin2.Nat.+
.delete> delete.term.verbose builtin2.Nat.*
.delete> merge.old.squash builtin2 builtin
.delete> history builtin
```
Notice that `Nat.+` and `Nat.*` are deleted by the squash, and we see them deleted in one atomic step in the history.
Just confirming that those two definitions are in fact removed:
```ucm:error
.delete> view .delete.builtin.Nat.+
```
```ucm:error
.delete> view .delete.builtin.Nat.*
```
## Caveats
If you `squash mystuff trunk`, you're discarding any history of `mystuff` and just cons'ing onto the history of `trunk`. Thus, don't expect to be able to `merge trunk mystuff` later and get great results. Squashing should only be used when you don't care about the history (and you know others haven't pulled and built on your line of history being discarded, so they don't care about the history either).

View File

@ -1,529 +0,0 @@
# Squash merges
`squash src dest` merges can be used to merge from `src` to `dest`, discarding the history of `src`. It's useful when the source namespace history is irrelevant or has a bunch of churn you wish to discard. Often when merging small pull requests, you'll use a squash merge.
Let's look at some examples. We'll start with a namespace with just the builtins. Let's take a look at the hash of this namespace:
```ucm
.> history builtin
Note: The most recent namespace hash is immediately below this
message.
□ 1. #i3vp9o9btm (start of history)
.> fork builtin builtin2
Done.
```
(We make a copy of `builtin` for use later in this transcript.)
Now suppose we `fork` a copy of builtin, then rename `Nat.+` to `frobnicate`, then rename it back. Notice this produces multiple entries in the history:
```ucm
.> fork builtin mybuiltin
Done.
.mybuiltin> rename.term Nat.+ Nat.frobnicate
Done.
.mybuiltin> rename.term Nat.frobnicate Nat.+
Done.
.mybuiltin> history
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #tpkjb488ei
> Moves:
Original name New name
Nat.frobnicate Nat.+
⊙ 2. #334ak3epqt
> Moves:
Original name New name
Nat.+ Nat.frobnicate
□ 3. #i3vp9o9btm (start of history)
```
If we merge that back into `builtin`, we get that same chain of history:
```ucm
.> merge.old mybuiltin builtin
Nothing changed as a result of the merge.
Applying changes from patch...
.> history builtin
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #tpkjb488ei
> Moves:
Original name New name
Nat.frobnicate Nat.+
⊙ 2. #334ak3epqt
> Moves:
Original name New name
Nat.+ Nat.frobnicate
□ 3. #i3vp9o9btm (start of history)
```
Let's try again, but using a `merge.squash` (or just `squash`) instead. The history will be unchanged:
```ucm
.> merge.old.squash mybuiltin builtin2
Nothing changed as a result of the merge.
😶
builtin2 was already up-to-date with mybuiltin.
.> history builtin2
Note: The most recent namespace hash is immediately below this
message.
□ 1. #i3vp9o9btm (start of history)
```
The churn that happened in `mybuiltin` namespace ended up back in the same spot, so the squash merge of that namespace with our original namespace had no effect.
## Another example
Let's look at a more interesting example, where the two namespaces have diverged a bit. Here's our starting namespace:
```unison
x = 1
```
```ucm
☝️ The namespace .trunk is empty.
.trunk> add
⍟ I've added these definitions:
x : ##Nat
.> fork trunk alice
Done.
.> fork trunk bob
Done.
```
Alice now does some hacking:
```unison
radNumber = 348
bodaciousNumero = 2394
neatoFun x = x
```
```ucm
.alice> add
⍟ I've added these definitions:
bodaciousNumero : ##Nat
neatoFun : x -> x
radNumber : ##Nat
.alice> rename.term radNumber superRadNumber
Done.
.alice> rename.term neatoFun productionReadyId
Done.
```
Meanwhile, Bob does his own hacking:
```unison
whatIsLove = "?"
babyDon'tHurtMe = ".. Don't hurt me..."
no more = no more
```
```ucm
.bob> add
⍟ I've added these definitions:
babyDon'tHurtMe : ##Text
no : more -> r
whatIsLove : ##Text
```
At this point, Alice and Bob both have some history beyond what's in trunk:
```ucm
.> history trunk
Note: The most recent namespace hash is immediately below this
message.
□ 1. #i52j9fd57b (start of history)
.> history alice
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #e9jd55555o
> Moves:
Original name New name
neatoFun productionReadyId
⊙ 2. #l5ocoo2eac
> Moves:
Original name New name
radNumber superRadNumber
⊙ 3. #i1vq05628n
+ Adds / updates:
bodaciousNumero neatoFun radNumber
□ 4. #i52j9fd57b (start of history)
.> history bob
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #brr4400742
+ Adds / updates:
babyDon'tHurtMe no whatIsLove
□ 2. #i52j9fd57b (start of history)
```
Alice then squash merges into `trunk`, as does Bob. It's as if Alice and Bob both made their changes in one single commit.
```ucm
.> merge.old.squash alice trunk
Here's what's changed in trunk after the merge:
Added definitions:
1. bodaciousNumero : Nat
2. productionReadyId : x -> x
3. superRadNumber : Nat
Tip: You can use `todo` to see if this generated any work to
do in this namespace and `test` to run the tests. Or you
can use `undo` or `reflog` to undo the results of this
merge.
Applying changes from patch...
.> history trunk
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #f9lvm9gd2k
+ Adds / updates:
bodaciousNumero productionReadyId superRadNumber
□ 2. #i52j9fd57b (start of history)
.> merge.old.squash bob trunk
Here's what's changed in trunk after the merge:
Added definitions:
1. babyDon'tHurtMe : Text
2. no : more -> r
3. whatIsLove : Text
Tip: You can use `todo` to see if this generated any work to
do in this namespace and `test` to run the tests. Or you
can use `undo` or `reflog` to undo the results of this
merge.
Applying changes from patch...
.> history trunk
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #dbp78ts6q3
+ Adds / updates:
babyDon'tHurtMe no whatIsLove
⊙ 2. #f9lvm9gd2k
+ Adds / updates:
bodaciousNumero productionReadyId superRadNumber
□ 3. #i52j9fd57b (start of history)
```
Since squash merges don't produce any merge nodes, we can `undo` a couple times to get back to our starting state:
```ucm
.> undo
Here are the changes I undid
Name changes:
Original Changes
1. bob.babyDon'tHurtMe 2. trunk.babyDon'tHurtMe (added)
3. bob.no 4. trunk.no (added)
5. bob.whatIsLove 6. trunk.whatIsLove (added)
.> undo
Here are the changes I undid
Name changes:
Original Changes
1. alice.bodaciousNumero 2. trunk.bodaciousNumero (added)
3. alice.productionReadyId 4. trunk.productionReadyId (added)
5. alice.superRadNumber 6. trunk.superRadNumber (added)
.> history trunk
Note: The most recent namespace hash is immediately below this
message.
□ 1. #i52j9fd57b (start of history)
```
This time, we'll first squash Alice and Bob's changes together before squashing their combined changes into `trunk`. The resulting `trunk` will have just a single entry in it, combining both Alice and Bob's changes:
```ucm
.> merge.old.squash alice bob
Here's what's changed in bob after the merge:
Added definitions:
1. bodaciousNumero : Nat
2. productionReadyId : x -> x
3. superRadNumber : Nat
Tip: You can use `todo` to see if this generated any work to
do in this namespace and `test` to run the tests. Or you
can use `undo` or `reflog` to undo the results of this
merge.
Applying changes from patch...
.> merge.old.squash bob trunk
Here's what's changed in trunk after the merge:
Added definitions:
1. babyDon'tHurtMe : Text
2. bodaciousNumero : Nat
3. no : more -> r
4. productionReadyId : x -> x
5. superRadNumber : Nat
6. whatIsLove : Text
Tip: You can use `todo` to see if this generated any work to
do in this namespace and `test` to run the tests. Or you
can use `undo` or `reflog` to undo the results of this
merge.
Applying changes from patch...
.> history trunk
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #qtotqgds4i
+ Adds / updates:
babyDon'tHurtMe bodaciousNumero no productionReadyId
superRadNumber whatIsLove
□ 2. #i52j9fd57b (start of history)
```
So, there you have it. With squashing, you can control the granularity of your history.
## Throwing out all history
Another thing we can do is `squash` into an empty namespace. This effectively makes a copy of the namespace, but without any of its history:
```ucm
.> merge.old.squash alice nohistoryalice
Here's what's changed in nohistoryalice after the merge:
Added definitions:
1. bodaciousNumero : Nat
2. productionReadyId : x -> x
3. superRadNumber : Nat
4. x : Nat
Tip: You can use `todo` to see if this generated any work to
do in this namespace and `test` to run the tests. Or you
can use `undo` or `reflog` to undo the results of this
merge.
Applying changes from patch...
.> history nohistoryalice
Note: The most recent namespace hash is immediately below this
message.
□ 1. #1d9haupn3d (start of history)
```
There's nothing really special here, `squash src dest` discards `src` history that comes after the LCA of `src` and `dest`, it's just that in the case of an empty namespace, that LCA is the beginning of time (the empty namespace), so all the history of `src` is discarded.
## Checking for handling of deletes
This checks to see that squashing correctly preserves deletions:
```ucm
☝️ The namespace .delete is empty.
.delete> builtins.merge
Done.
.delete> fork builtin builtin2
Done.
.delete> delete.term.verbose builtin2.Nat.+
Name changes:
Original Changes
1. builtin.Nat.+ ┐ 2. builtin2.Nat.+ (removed)
3. builtin2.Nat.+ ┘
Tip: You can use `undo` or `reflog` to undo this change.
.delete> delete.term.verbose builtin2.Nat.*
Name changes:
Original Changes
1. builtin.Nat.* ┐ 2. builtin2.Nat.* (removed)
3. builtin2.Nat.* ┘
Tip: You can use `undo` or `reflog` to undo this change.
.delete> merge.old.squash builtin2 builtin
Here's what's changed in builtin after the merge:
Removed definitions:
1. Nat.* : Nat -> Nat -> Nat
2. Nat.+ : Nat -> Nat -> Nat
Tip: You can use `todo` to see if this generated any work to
do in this namespace and `test` to run the tests. Or you
can use `undo` or `reflog` to undo the results of this
merge.
Applying changes from patch...
.delete> history builtin
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #dv00hf6vmg
- Deletes:
Nat.* Nat.+
□ 2. #i3vp9o9btm (start of history)
```
Notice that `Nat.+` and `Nat.*` are deleted by the squash, and we see them deleted in one atomic step in the history.
Just confirming that those two definitions are in fact removed:
```ucm
.delete> view .delete.builtin.Nat.+
⚠️
The following names were not found in the codebase. Check your spelling.
.delete.builtin.Nat.+
```
```ucm
.delete> view .delete.builtin.Nat.*
⚠️
The following names were not found in the codebase. Check your spelling.
.delete.builtin.Nat.*
```
## Caveats
If you `squash mystuff trunk`, you're discarding any history of `mystuff` and just cons'ing onto the history of `trunk`. Thus, don't expect to be able to `merge trunk mystuff later and get great results. Squashing should only be used when you don't care about the history (and you know others haven't pulled and built on your line of history being discarded, so they don't care about the history either).