Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git_rebase.md « git « topics « doc - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d9bf9f758f65bc878f21e748dda608bd8fb2fdab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
---
stage: Create
group: Source Code
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments"
description: "Introduction to Git rebase and force push, methods to resolve merge conflicts through the command line."
---

# Git rebase and force push **(FREE ALL)**

In Git, a rebase updates your branch with the contents of another branch.
A rebase confirms that changes in your branch don't conflict with
changes in the target branch.

If you have a [merge conflict](../../user/project/merge_requests/conflicts.md),
you can rebase to fix it.

## What happens during rebase

When you rebase:

1. Git imports all the commits submitted to your target branch after you initially created
   your branch from it.
1. Git stacks the commits you have in your branch on top of all
   the commits it imported from that branch:

   ![Git rebase illustration](img/git_rebase_v13_5.png)

While most rebases are performed against `main`, you can rebase against any other
branch, such as `release-15-3`. You can also specify a different remote repository
(such as `upstream`) instead of `origin`.

WARNING:
`git rebase` rewrites the commit history. It **can be harmful** to do it in
shared branches. It can cause complex and hard to resolve
merge conflicts. Instead of rebasing your branch against the default branch,
consider pulling it instead (`git pull origin master`). Pulling has similar
effects with less risk of compromising others' work.

## Rebase by using Git

When you use Git to rebase, each commit is applied to your branch.
When merge conflicts occur, you are prompted to address them.

If you want more advanced options for your commits,
do [an interactive rebase](#rebase-interactively-by-using-git).

Prerequisites:

- You must have permission to force push to branches.

To use Git to rebase your branch against the target branch:

1. Open a terminal and change to your project.
1. Ensure you have the latest contents of the target branch.
   In this example, the target branch is `main`:

   ```shell
   git fetch origin main
   ```

1. Check out your branch:

   ```shell
   git checkout my-branch
   ```

1. Optional. Create a backup of your branch:

   ```shell
   git branch my-branch-backup
   ```

   Changes added to `my-branch` after this point are lost
   if you restore from the backup branch.

1. Rebase against the main branch:

   ```shell
   git rebase origin/main
   ```

1. If merge conflicts exist:
   1. Fix the conflicts in your editor.

   1. Add the files:

      ```shell
      git add .
      ```

   1. Continue the rebase:

      ```shell
      git rebase --continue
      ```

1. Force push your changes to the target branch, while protecting others' commits:

   ```shell
   git push origin my-branch --force-with-lease
   ```

## Rebase from the UI

You can rebase a merge request from the GitLab UI.

Prerequisites:

- No merge conflicts must exist.
- You must have at least the **Developer** role for the source project. This role grants you
  permission to push to the source branch for the source project.
- If the merge request is in a fork, the fork must allow commits
  [from members of the upstream project](../../user/project/merge_requests/allow_collaboration.md).

To rebase from the UI:

1. Go to your merge request.
1. Type `/rebase` in a comment.
1. Select **Comment**.

GitLab schedules a rebase of the branch against the default branch and
executes it as soon as possible.

## Rebase interactively by using Git

Use an interactive rebase when you want to specify how to handle each commit.
You must do an interactive rebase from the command line.

Prerequisites:

- [Vim](https://www.vim.org/) must be your text editor to follow these instructions.

To rebase interactively:

1. Open a terminal and change to your project.
1. Ensure you have the latest contents of the target branch.
   In this example, the target branch is `main`:

   ```shell
   git fetch origin main
   ```

1. Check out your branch:

   ```shell
   git checkout my-branch
   ```

1. Optional. Create a backup of your branch:

   ```shell
   git branch my-branch-backup
   ```

   Changes added to `my-branch` after this point are lost
   if you restore from the backup branch.

1. In the GitLab UI, in your merge request, confirm how many commits
   you want to rebase by viewing the **Commits** tab.

1. Open these commits. For example, to edit the last five commits in your branch (`HEAD~5`), type:

   ```shell
   git rebase -i HEAD~5
   ```

   Git opens the last five commits in your terminal text editor, oldest commit first.
   Each commit shows the action to take on it, the SHA, and the commit title:

   ```shell
   pick 111111111111 Second round of structural revisions
   pick 222222222222 Update inbound link to this changed page
   pick 333333333333 Shifts from H4 to H3
   pick 444444444444 Adds revisions from editorial
   pick 555555555555 Revisions continue to build the concept part out

   # Rebase 111111111111..222222222222 onto zzzzzzzzzzzz (5 commands)
   #
   # Commands:
   # p, pick <commit> = use commit
   # r, reword <commit> = use commit, but edit the commit message
   # e, edit <commit> = use commit, but stop for amending
   # s, squash <commit> = use commit, but meld into previous commit
   # f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
   ```

1. Switch to Vim's edit mode by pressing <kbd>i</kbd>.
1. Move to the second commit in the list by using your keyboard arrows.
1. Change the word `pick` to `squash` or `fixup` (or `s` or `f`).
1. Do the same for the remaining commits. Leave the first commit as `pick`.
1. End edit mode, save, and quit:

   - Press <kbd>ESC</kbd>.
   - Type `:wq`.

1. When squashing, Git outputs the commit message so you have a chance to edit it:

   - All lines starting with `#` are ignored and not included in the commit
     message. Everything else is included.
   - To leave it as-is, type `:wq`. To edit the commit message, switch to
     edit mode, edit the commit message, and save.

1. Commit to the target branch.

   - If you didn't push your commits to the target branch before rebasing,
     push your changes without a force push:

     ```shell
     git push origin my-branch
     ```

   - If you pushed these commits already, use a force push:

     ```shell
     git push origin my-branch --force-with-lease
     ```

## Force pushing

Complex operations in Git require you to force an update to the remote branch.
Operations like squashing commits, resetting a branch, or rebasing a branch rewrite
the history of your branch. Git requires a forced update to help safeguard against
these more destructive changes from happening accidentally.

Force pushing is not recommended on shared branches, because you risk destroying
others' changes.

If the branch you want to force push is [protected](../../user/project/protected_branches.md),
you can't force push to it unless you either:

- Unprotect it.
- [Allow force pushes](../../user/project/protected_branches.md#allow-force-push-on-a-protected-branch)
  to it.

Then you can force push and protect it again.

## Restore your backed up branch

Your branch is backed up, and you can try a rebase or a force push.
If anything goes wrong, restore your branch from its backup:

1. Make sure you're in the correct branch:

   ```shell
   git checkout my-branch
   ```

1. Reset your branch against the backup:

   ```shell
   git reset --hard my-branch-backup
   ```

## Approving after rebase

If you rebase a branch, you've added commits.
If your project is configured to
[prevent approvals by users who add commits](../../user/project/merge_requests/approvals/settings.md#prevent-approvals-by-users-who-add-commits),
you can't approve a merge request if you have rebased it.

## Related topics

- [Numerous undo possibilities in Git](numerous_undo_possibilities_in_git/index.md#undo-staged-local-changes-without-modifying-history)
- [Git documentation for branches and rebases](https://git-scm.com/book/en/v2/Git-Branching-Rebasing)
- [Project squash and merge settings](../../user/project/merge_requests/squash_and_merge.md#configure-squash-options-for-a-project)

## Troubleshooting

### `Unmergeable state` after `/rebase` quick action

The `/rebase` command schedules a background task. The task attempts to rebase
the changes in the source branch on the latest commit of the target branch.
If, after using the `/rebase`
[quick action](../../user/project/quick_actions.md#issues-merge-requests-and-epics),
you see this error, a rebase cannot be scheduled:

```plaintext
This merge request is currently in an unmergeable state, and cannot be rebased.
```

This error occurs if any of these conditions are true:

- Conflicts exist between the source and target branches.
- The source branch contains no commits.
- Either the source or target branch does not exist.
- An error has occurred, resulting in no diff being generated.

To resolve the `unmergeable state` error:

1. Resolve any merge conflicts.
1. Confirm the source branch exists, and has commits.
1. Confirm the target branch exists.
1. Confirm the diff has been generated.

### `/merge` quick action ignored after `/rebase`

If `/rebase` is used, `/merge` is ignored to avoid a race condition where the source branch is merged or deleted before it is rebased.