pub fn finalize_cherry_pick_message(
original_message: &str,
append_source: bool,
signoff: bool,
committer_name: &str,
committer_email: &str,
config: &ConfigSet,
picked_commit_hex: &str,
) -> StringExpand description
Apply -x / -s rewriting plus optional commit.cleanup when -x is set.
Examples found in repository?
examples/cherry_pick.rs (lines 161-169)
48fn main() -> grit_lib::error::Result<()> {
49 let root = tempfile::tempdir()?;
50 let repo = init_repository(root.path(), false, "main", None, "files")?;
51
52 use grit_lib::index::{Index, IndexEntry, MODE_REGULAR};
53
54 // Base commit on main: one file.
55 let blob_a = repo.odb.write(ObjectKind::Blob, b"base\n")?;
56 let mut index = Index::new();
57 index.add_or_replace(IndexEntry {
58 ctime_sec: 0,
59 ctime_nsec: 0,
60 mtime_sec: 0,
61 mtime_nsec: 0,
62 dev: 0,
63 ino: 0,
64 mode: MODE_REGULAR,
65 uid: 0,
66 gid: 0,
67 size: 0,
68 oid: blob_a,
69 flags: 7,
70 flags_extended: None,
71 path: b"base.txt".to_vec(),
72 base_index_pos: 0,
73 });
74 repo.write_index(&mut index)?;
75 let index = repo.load_index()?;
76 let tree_a = write_tree_from_index(&repo.odb, &index, "")?;
77 let commit_a = commit_from_tree(&repo, tree_a, &[], "initial\n")?;
78 refs::write_ref(&repo.git_dir, "refs/heads/main", &commit_a)?;
79
80 // Topic commit: parent A, adds picked.txt (not on main yet).
81 let blob_pick = repo.odb.write(ObjectKind::Blob, b"hello from topic\n")?;
82 let mut index = Index::new();
83 index.add_or_replace(IndexEntry {
84 ctime_sec: 0,
85 ctime_nsec: 0,
86 mtime_sec: 0,
87 mtime_nsec: 0,
88 dev: 0,
89 ino: 0,
90 mode: MODE_REGULAR,
91 uid: 0,
92 gid: 0,
93 size: 0,
94 oid: blob_a,
95 flags: 7,
96 flags_extended: None,
97 path: b"base.txt".to_vec(),
98 base_index_pos: 0,
99 });
100 index.add_or_replace(IndexEntry {
101 ctime_sec: 0,
102 ctime_nsec: 0,
103 mtime_sec: 0,
104 mtime_nsec: 0,
105 dev: 0,
106 ino: 0,
107 mode: MODE_REGULAR,
108 uid: 0,
109 gid: 0,
110 size: 0,
111 oid: blob_pick,
112 flags: 9,
113 flags_extended: None,
114 path: b"picked.txt".to_vec(),
115 base_index_pos: 0,
116 });
117 repo.write_index(&mut index)?;
118 let index = repo.load_index()?;
119 let tree_b = write_tree_from_index(&repo.odb, &index, "")?;
120 let commit_b = commit_from_tree(&repo, tree_b, &[commit_a], "add picked file\n")?;
121 refs::write_ref(&repo.git_dir, "refs/heads/topic", &commit_b)?;
122
123 // Cherry-pick `topic` onto `main` (still at A).
124 let head = resolve_revision(&repo, "main")?;
125 let picked = resolve_revision(&repo, "topic")?;
126 let picked_obj = repo.odb.read(&picked)?;
127 let picked_data = parse_commit(&picked_obj.data)?;
128 let parent = picked_data.parents.first().copied().ok_or_else(|| {
129 grit_lib::error::Error::CorruptObject("picked commit has no parent".into())
130 })?;
131
132 let base_tree = tree_of_commit(&repo, parent)?;
133 let ours_tree = tree_of_commit(&repo, head)?;
134 let theirs_tree = picked_data.tree;
135
136 let merged = merge_trees_three_way(
137 &repo,
138 base_tree,
139 ours_tree,
140 theirs_tree,
141 MergeFavor::default(),
142 WhitespaceMergeOptions::default(),
143 grit_lib::merge_trees::TreeMergeConflictPresentation {
144 label_ours: "HEAD",
145 label_theirs: grit_lib::merge_trees::TheirsConflictLabel::Fixed("picked"),
146 label_base: "parent of picked commit",
147 style: grit_lib::merge_file::ConflictStyle::Merge,
148 checkout_merge: false,
149 },
150 )?;
151
152 if !merged.conflict_content.is_empty() {
153 return Err(grit_lib::error::Error::Message(format!(
154 "merge produced {} conflict path(s); this example expects a clean pick",
155 merged.conflict_content.len()
156 )));
157 }
158
159 let new_tree = write_tree_from_index(&repo.odb, &merged.index, "")?;
160 let config = ConfigSet::load_repo_local_only(&repo.git_dir)?;
161 let msg = commit_trailers::finalize_cherry_pick_message(
162 &picked_data.message,
163 true,
164 false,
165 "Example",
166 "example@example.com",
167 &config,
168 &picked.to_hex(),
169 );
170 let new_commit = commit_from_tree(&repo, new_tree, &[head], &msg)?;
171 refs::write_ref(&repo.git_dir, "refs/heads/main", &new_commit)?;
172
173 println!("cherry-picked {} onto {}", picked, head);
174 println!("new main: {new_commit}");
175 let out = repo.odb.read(&new_commit)?;
176 println!("message:\n{}", parse_commit(&out.data)?.message);
177
178 Ok(())
179}