Skip to content

Commit b2b5a0f

Browse files
authored
Add undo_last_commit command (#769)
closes #758
1 parent 12b9071 commit b2b5a0f

File tree

6 files changed

+94
-2
lines changed

6 files changed

+94
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
## Added
11+
- undo-last-commit command under `[U]` key [[@remique](https://github.com/remique)] ([#758](https://github.com/extrawurst/gitui/issues/758))
12+
1013
## Fixed
1114
- openssl vendoring broken on macos ([#772](https://github.com/extrawurst/gitui/issues/772))
1215

asyncgit/src/sync/utils.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,21 @@ pub fn stage_add_all(repo_path: &str, pattern: &str) -> Result<()> {
149149
Ok(())
150150
}
151151

152+
/// Undo last commit in repo
153+
pub fn undo_last_commit(repo_path: &str) -> Result<()> {
154+
let repo = repo(repo_path)?;
155+
let previous_commit = repo.revparse_single("HEAD~")?;
156+
157+
Repository::reset(
158+
&repo,
159+
&previous_commit,
160+
git2::ResetType::Soft,
161+
None,
162+
)?;
163+
164+
Ok(())
165+
}
166+
152167
/// stage a removed file
153168
pub fn stage_addremoved(repo_path: &str, path: &Path) -> Result<()> {
154169
scope_time!("stage_addremoved");
@@ -206,9 +221,11 @@ mod tests {
206221
use super::*;
207222
use crate::sync::{
208223
commit,
224+
diff::get_diff,
209225
status::{get_status, StatusType},
210226
tests::{
211-
debug_cmd_print, get_statuses, repo_init, repo_init_empty,
227+
debug_cmd_print, get_statuses, repo_init,
228+
repo_init_empty, write_commit_file,
212229
},
213230
};
214231
use std::{
@@ -282,6 +299,43 @@ mod tests {
282299
Ok(())
283300
}
284301

302+
#[test]
303+
fn test_undo_commit_empty_repo() {
304+
let (_td, repo) = repo_init().unwrap();
305+
let root = repo.path().parent().unwrap();
306+
let repo_path = root.as_os_str().to_str().unwrap();
307+
308+
// expect to fail
309+
assert!(undo_last_commit(repo_path).is_err());
310+
}
311+
312+
#[test]
313+
fn test_undo_commit() {
314+
let (_td, repo) = repo_init().unwrap();
315+
let root = repo.path().parent().unwrap();
316+
let repo_path = root.as_os_str().to_str().unwrap();
317+
318+
// write commit file test.txt
319+
let c1 =
320+
write_commit_file(&repo, "test.txt", "content1", "c1");
321+
let _c2 =
322+
write_commit_file(&repo, "test.txt", "content2", "c2");
323+
assert!(undo_last_commit(repo_path).is_ok());
324+
325+
// Make sure that HEAD points to c1
326+
assert_eq!(c1, get_head_repo(&repo).unwrap());
327+
328+
// Make sure that now we have 1 file staged
329+
assert_eq!(get_statuses(repo_path), (0, 1));
330+
331+
// And that file is test.txt
332+
let diff = get_diff(repo_path, "test.txt", true).unwrap();
333+
assert_eq!(
334+
diff.hunks[0].lines[0].content,
335+
String::from("@@ -1 +1 @@\n")
336+
);
337+
}
338+
285339
#[test]
286340
fn test_not_staging_untracked_folder() -> Result<()> {
287341
let (_td, repo) = repo_init().unwrap();

src/keys.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ pub struct KeyConfig {
8181
pub force_push: KeyEvent,
8282
pub pull: KeyEvent,
8383
pub abort_merge: KeyEvent,
84+
pub undo_commit: KeyEvent,
8485
}
8586

8687
#[rustfmt::skip]
@@ -144,6 +145,7 @@ impl Default for KeyConfig {
144145
select_tag: KeyEvent { code: KeyCode::Enter, modifiers: KeyModifiers::empty()},
145146
push: KeyEvent { code: KeyCode::Char('p'), modifiers: KeyModifiers::empty()},
146147
force_push: KeyEvent { code: KeyCode::Char('P'), modifiers: KeyModifiers::SHIFT},
148+
undo_commit: KeyEvent { code: KeyCode::Char('U'), modifiers: KeyModifiers::SHIFT},
147149
pull: KeyEvent { code: KeyCode::Char('f'), modifiers: KeyModifiers::empty()},
148150
abort_merge: KeyEvent { code: KeyCode::Char('M'), modifiers: KeyModifiers::SHIFT},
149151
open_file_tree: KeyEvent { code: KeyCode::Char('F'), modifiers: KeyModifiers::SHIFT},

src/strings.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,16 @@ pub mod commands {
579579
CMD_GROUP_GENERAL,
580580
)
581581
}
582+
pub fn undo_commit(key_config: &SharedKeyConfig) -> CommandText {
583+
CommandText::new(
584+
format!(
585+
"Undo Commit [{}]",
586+
key_config.get_hint(key_config.undo_commit),
587+
),
588+
"undo last commit",
589+
CMD_GROUP_GENERAL,
590+
)
591+
}
582592
pub fn commit_open(key_config: &SharedKeyConfig) -> CommandText {
583593
CommandText::new(
584594
format!(

src/tabs/status.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
FileTreeItemKind,
88
},
99
keys::SharedKeyConfig,
10-
queue::{Action, InternalEvent, Queue, ResetItem},
10+
queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem},
1111
strings, try_or_popup,
1212
ui::style::SharedTheme,
1313
};
@@ -468,6 +468,14 @@ impl Status {
468468
}
469469
}
470470

471+
fn undo_last_commit(&self) {
472+
try_or_popup!(
473+
self,
474+
"undo commit failed:",
475+
sync::utils::undo_last_commit(CWD)
476+
);
477+
}
478+
471479
fn branch_compare(&mut self) {
472480
self.git_branch_state =
473481
self.git_branch_name.last().and_then(|branch| {
@@ -579,6 +587,12 @@ impl Component for Status {
579587
!focus_on_diff,
580588
));
581589

590+
out.push(CommandInfo::new(
591+
strings::commands::undo_commit(&self.key_config),
592+
true,
593+
!focus_on_diff,
594+
));
595+
582596
out.push(CommandInfo::new(
583597
strings::commands::abort_merge(&self.key_config),
584598
true,
@@ -687,6 +701,14 @@ impl Component for Status {
687701
{
688702
self.pull();
689703
Ok(EventState::Consumed)
704+
} else if k == self.key_config.undo_commit
705+
&& !self.is_focus_on_diff()
706+
{
707+
self.undo_last_commit();
708+
self.queue.borrow_mut().push_back(
709+
InternalEvent::Update(NeedsUpdate::ALL),
710+
);
711+
Ok(EventState::Consumed)
690712
} else if k == self.key_config.abort_merge
691713
&& Self::can_abort_merge()
692714
{

vim_style_key_config.ron

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
// Also just plain text characters will not work because the commit
3535
// msg editor will interpret them as text input
3636
open_commit_editor: ( code: Char('e'), modifiers: ( bits: 2,),),
37+
undo_commit: ( code: Char('U'), modifiers: ( bits: 1,),),
3738

3839
move_left: ( code: Char('h'), modifiers: ( bits: 0,),),
3940
move_right: ( code: Char('l'), modifiers: ( bits: 0,),),

0 commit comments

Comments
 (0)