Let's walk through an example of staging some changes, and manually editing a hunk to stage them into the patches we want.
Create a temporary Git repository, this will be a just some basic stuff for testing.
% cd /tmp % git init foo % cd foo
From here on, we will assume the working directory to be
/tmp/foo.
Inside this new Git repository, add a new file, quicksort.exs:
defmodule Quicksort do
def sort(list) do
_sort(list)
end
defp _sort([]), do: []
defp _sort(list = [h|t]) do
_sort(Enum.filter(list, &(&1 < h))) ++ [h] ++ _sort(Enum.filter(list, &(&1 > h)))
end
end
Perform the usual actions, git-add and git-commit:
% git add quicksort.exs
% git commit -m 'initial commit'
Now, let's make some changes. For one, there's compiler warning about the
unused variable t and the actually sorting seems a bit dense. Let's fix the
warning and breakup the sorting:
defmodule Quicksort do
def sort(list) do
_sort(list)
end
defp _sort([]), do: []
defp _sort(list = [h|_]) do
(list |> Enum.filter(&(&1 < h)) |> _sort)
++ [h] ++
(list |> Enum.filter(&(&1 > h)) |> _sort)
end
end
Saving this version of the file should produce a diff similar to the following:
diff --git a/quicksort.exs b/quicksort.exs index 97b60b4..ed2446b 100644 --- a/quicksort.exs +++ b/quicksort.exs @@ -5,8 +5,10 @@ defmodule Quicksort do end defp _sort([]), do: [] - defp _sort(list = [h|t]) do - _sort(Enum.filter(list, &(&1 < h))) ++ [h] ++ _sort(Enum.filter(list, &(&1 > h))) + defp _sort(list = [h|_]) do + (list |> Enum.filter(&(&1 < h)) |> _sort) + ++ [h] ++ + (list |> Enum.filter(&(&1 > h)) |> _sort) end end
However, since these changes are actually, argubly, two different changes, they
should live in two commits. Let's stage the change for t to _:
We will be presented with the diff from before:
diff --git a/quicksort.exs b/quicksort.exs index 97b60b4..ed2446b 100644 --- a/quicksort.exs +++ b/quicksort.exs @@ -5,8 +5,10 @@ defmodule Quicksort do end defp _sort([]), do: [] - defp _sort(list = [h|t]) do - _sort(Enum.filter(list, &(&1 < h))) ++ [h] ++ _sort(Enum.filter(list, &(&1 > h))) + defp _sort(list = [h|_]) do + (list |> Enum.filter(&(&1 < h)) |> _sort) + ++ [h] ++ + (list |> Enum.filter(&(&1 > h)) |> _sort) end end Stage this hunk [y,n,q,a,d,/,e,?]?
First thing we want to try is using the split(s) option. However, this is an
invalid choice because Git does not know how to split this hunk and we will be
presented with the available options and the hunk again. The option we then
want is edit(e).
We will be dropped into our default editor, environment variable $EDITOR, Git
core.editor setting. From there, we will be presented with something of the
following:
# Manual hunk edit mode -- see bottom for a quick guide @@ -5,8 +5,10 @@ defmodule Quicksort do end defp _sort([]), do: [] - defp _sort(list = [h|t]) do - _sort(Enum.filter(list, &(&1 < h))) ++ [h] ++ _sort(Enum.filter(list, &(&1 > h))) + defp _sort(list = [h|_]) do + (list |> Enum.filter(&(&1 < h)) |> _sort) + ++ [h] ++ + (list |> Enum.filter(&(&1 > h)) |> _sort) end end # --- # To remove '-' lines, make them ' ' lines (context). # To remove '+' lines, delete them. # Lines starting with # will be removed. # # If the patch applies cleanly, the edited hunk will immediately be # marked for staging. If it does not apply cleanly, you will be given # an opportunity to edit again. If all lines of the hunk are removed, # then the edit is aborted and the hunk is left unchanged.
From here, we want to replace the leading minus of the change removal to a space and remove the last three additions.
That is, we want the diff to look like:
@@ -5,8 +5,10 @@ defmodule Quicksort do end defp _sort([]), do: [] - defp _sort(list = [h|t]) do sort(Enum.filter(list, &(&1 < h))) ++ [h] ++ _sort(Enum.filter(list, &(&1 > h))) + defp _sort(list = [h|_]) do end end
Saving and closing the editor now, Git will have staged the desired diff. We
can check the staged changes via git-diff:
% git diff --cached diff --git a/quicksort.exs b/quicksort.exs index 97b60b4..94a5101 100644 --- a/quicksort.exs +++ b/quicksort.exs @@ -5,8 +5,8 @@ defmodule Quicksort do end defp _sort([]), do: [] - defp _sort(list = [h|t]) do _sort(Enum.filter(list, &(&1 < h))) ++ [h] ++ _sort(Enum.filter(list, &(&1 > h))) + defp _sort(list = [h|_]) do end end
Notice, the hunk context data was updated correctly to match the new changes.
From here, commit the first change, and then add and commit the second change.
Something to watch out for is over zealously removing changed lines. For
example, in Elixir quicksort example we have just did, if we entirely removed
the second - from the diff and manually updated the hunk header, the patch
will never apply cleanly. Therefore, be especially careful with removing -
lines.