So, the "head" is set to track the "list". How come in the end the they have different values?
The reason is that head never is assigned anything else after its first initialisation, while list is assigned something else in the loop. list initially is referencing the same (dummy) node as head, but then later starts referencing different nodes by doing list = list.next repeatedly.
It may help to visualise this. Let's say we merge two lists with values 1, 4 and 2, 3 respectively:
First we have the initialisation happening. Just before the loop starts, we have this siutation:
head list
↓ ↓
┌───────────┐
│ val: 0 │
│ next:null │
└───────────┘
list1
↓
┌───────────┐ ┌───────────┐
│ val: 1 │ │ val: 4 │
│ next: ──────► │ next:null │
└───────────┘ └───────────┘
┌───────────┐ ┌───────────┐
│ val: 2 │ │ val: 3 │
│ next: ──────► │ next:null │
└───────────┘ └───────────┘
↑
list2
In the first iteration of the loop, the first if condition is true, and so list.next = list1 gets executed. This leads to the following:
head list
↓ ↓
┌───────────┐
│ val: 0 │
│ next: ─┐ │
└────────│──┘
│
list1 │
↓ ▼
┌───────────┐ ┌───────────┐
│ val: 1 │ │ val: 4 │
│ next: ──────► │ next:null │
└───────────┘ └───────────┘
┌───────────┐ ┌───────────┐
│ val: 2 │ │ val: 3 │
│ next: ──────► │ next:null │
└───────────┘ └───────────┘
↑
list2
The next statement assigns a different node reference to list1 with list1 = list1.next:
head list
↓ ↓
┌───────────┐
│ val: 0 │
│ next: ─┐ │
└────────│──┘
│
│ list1
▼ ↓
┌───────────┐ ┌───────────┐
│ val: 1 │ │ val: 4 │
│ next: ──────► │ next:null │
└───────────┘ └───────────┘
┌───────────┐ ┌───────────┐
│ val: 2 │ │ val: 3 │
│ next: ──────► │ next:null │
└───────────┘ └───────────┘
↑
list2
The last statement in the first iteration of the loop, moves the list reference, with list = list.next, which means head and list no longer reference the same node; and they will never be the same reference again:
head
↓
┌───────────┐
│ val: 0 │
│ next: ─┐ │
└────────│──┘
│
list │ list1
↓ ▼ ↓
┌───────────┐ ┌───────────┐
│ val: 1 │ │ val: 4 │
│ next: ──────► │ next:null │
└───────────┘ └───────────┘
┌───────────┐ ┌───────────┐
│ val: 2 │ │ val: 3 │
│ next: ──────► │ next:null │
└───────────┘ └───────────┘
↑
list2
In the second iteration of the loop, we get into the else block, and there we set list.next = list2:
head
↓
┌───────────┐
│ val: 0 │
│ next: ─┐ │
└────────│──┘
│
list │ list1
↓ ▼ ↓
┌───────────┐ ┌───────────┐
│ val: 1 │ │ val: 4 │
│ next: ─┐ │ │ next:null │
└────────│──┘ └───────────┘
▼
┌───────────┐ ┌───────────┐
│ val: 2 │ │ val: 3 │
│ next: ──────► │ next:null │
└───────────┘ └───────────┘
↑
list2
Then list1 = list1.next will lead to:
head
↓
┌───────────┐
│ val: 0 │
│ next: ─┐ │
└────────│──┘
│
list │ list1
↓ ▼ ↓
┌───────────┐ ┌───────────┐
│ val: 1 │ │ val: 4 │
│ next: ─┐ │ │ next:null │
└────────│──┘ └───────────┘
▼
┌───────────┐ ┌───────────┐
│ val: 2 │ │ val: 3 │
│ next: ──────► │ next:null │
└───────────┘ └───────────┘
↑
list2
And again, the final statement of this second iteration, will move list:
head
↓
┌───────────┐
│ val: 0 │
│ next: ─┐ │
└────────│──┘
│
│ list1
▼ ↓
┌───────────┐ ┌───────────┐
│ val: 1 │ │ val: 4 │
│ next: ─┐ │ │ next:null │
└────────│──┘ └───────────┘
▼
┌───────────┐ ┌───────────┐
│ val: 2 │ │ val: 3 │
│ next: ──────► │ next:null │
└───────────┘ └───────────┘
↑ ↑
list list2
And so the process continues,... Never is head moving, but list is. When the loop exits, the situation will be this:
head
↓
┌───────────┐
│ val: 0 │
│ next: ─┐ │
└────────│──┘
│
│ list1 == null
▼
┌───────────┐ ┌───────────┐
│ val: 1 │ │ val: 4 │
│ next: ─┐ │ │ next:null │
└────────│──┘ └───────────┘
▼ ▲
┌───────────┐ ┌─────────│─┐
│ val: 2 │ │ val: 3 │ │
│ next: ──────► │ next: ──┘ │
└───────────┘ └───────────┘
↑
list list2 == null
The return value is head.next, which indeed is the reference to the first node (with value 1) of the merged list.
I hope this clarified it.