Changing the commit message while grafting a large number of changesets using Mercurial - version-control

I need to graft a large number (thousands) of small changesets from branch A to branch B - but need to alter the commit message in the process.
The message change needs to look roughly like this:
"Ref XXX: Fixed foo and bar" -> "GRAFT: Ref YYY: Fixed foo and bar".
In other words, I need to prepend "GRAFT:" and change a reference number. If I can't make these replacements directly with Mercurial, I could create the new commit messages all in advance then make a script to apply each new message during its respective graft. Happily, Mercurial allows editing commit messages during grafting, with the -e argument:
https://www.mercurial-scm.org/repo/hg/help/graft
The problem is that this pops up a text editor for each changeset for me to make the change manually. There doesn't seem to be a way to amend the message in a programmatic way, or just to provide an entirely new message, at the comment line. Given the size of operation, using the editor each time isn't plausible.
My last option would be to use the text editor with some sort of AutoIt/Macro script to enter the right things in the places at the right times - but the thought of needing to resort to this is frankly making me feel a bit ill.
Save me from this ugly fate.
Thanks in advance.

A possible workaround is to specify the use of a shell script in lieu of an editor. For example:
#!/bin/sh
sed -e '1,1s/^/GRAFT: /' -i "$1"
We're making use of the fact that with -i, sed will do an in-place edit. Don't forget to make the shell script executable. Then you can run
hg graft --config ui.editor=/path/to/prepend-graft.sh -e -r <revision>
where /path/to/prepend-graft.sh is the path of the aforementioned shell script.
Changing a number may require code that's more complex than a sed script, but would follow the same approach.

Related

VSCode - How to delete a specific command history in command palette (as opposed to clearing everything)?

I would like to delete several commands from VSCode command palette's "recently used" section, but not clear the entire history. How?
So in Chrome's Omnibar, you can use Shift+del to delete a suggestion. But I cannot find an analogous shortcut in VSCode's command palette.
I also looked for a "meta-command" for this, but I only found Clear Command History in the command palette. I want something like Edit/Manage Command History instead.
Edit: a history file that I can directly edit (analogous to ~/.bash_history for Bash) would also do.
Okay, so this question was upvoted today, which brought it back to my attention. I decided to bite the bullet this time and dug into the nuts and bolts of VSCode's files and found where this history is stored.
TLDR
Modifying the history is doable (obviously, because it has to be stored somewhere), but it's not very practical at all. Unfortunately it will continue to be very difficult, until VSCode implements official support (which may be never). I recommend using the following method ONLY IF you absolutely need a history entry deleted.
The method
Note:
I'm using Code OSS (the debranded build of VSCode) on Linux. The method should be applicable to other OSes, but the specific commands and paths will be different.
This method works on VSCode 1.74.2, the latest version as of 2023-01-04. It may or may not work with future versions.
0. Exit VSCode completely
Obviously.
Check with your resource/task/process manager to make sure VSCode is completely killed. If you're not sure, just reboot.
1. Locate lastSyncglobalState.json
This file contains the command palette history data. On Linux it's located at $XDG_CONFIG_HOME/Code - OSS/User/sync/globalState/lastSyncglobalState.json. On Windows it's probably under a similar path in %APPDATA%. Not sure about MacOS. Copy this file to somewhere convenient.
If you are curious how I discovered this file, I did a search of a command I recently ran using rg in $XDG_CONFIG_HOME/Code - OSS/. Note that you have to search the "programmatic name" of the command, not its display name (e.g. rust-analyzer.reload, not rust-analyzer: Restart server).
2. Extract the relevant data
If you open up lastSyncglobalState.json with a text editor directly, you'll find a Russian doll of escaped JSON. Technically you can do the modification straight from here, but I'm not eating this 💩.
Fortunately jq makes this somewhat easier:
# This is Bash but I think it works on Windows CMD too? Not sure.
jq '.syncData.content | fromjson.storage."commandPalette.mru.cache".value | fromjson.entries' lastSyncglobalState.json > history.json
The extracted history.json should look something like this:
[
{
"key": "rust-analyzer.debug",
"value": 297
},
{
"key": "rust-analyzer.syntaxTree",
"value": 298
},
// more entries...
]
3. Modify
Copy history.json to history-new.json, and simply remove the entries you want to delete from history-new.json. Do not modify history.json; we will need it in a bit.
Check that it's still valid JSON after your edits; in particular make sure that you have not left a trailing comma in the array.
4. Write back
The responsible way to do this is to perform the inverse of step 2, starting from the bottom up, update a field, json-encode, then update the field one level up, json-encode again, etc, until we get to the top level. But that's an enormous pain in the arse to do with jq.
Much easier I think, simply double (triple?) json-encode history-new.json, and perform a textual replacement. This is where the original history.json comes in handy:
# In lastSyncglobalState.json, replace the output of...
jq 'tojson | tojson' history.json
# with the output of...
jq 'tojson | tojson' history-new.json
Note that since the output of jq is quoted, it's necessary to remove the outmost layer of quotes (") on both the search string and the replace string. With rg we can automate this:
jq 'tojson | tojson' history.json | rg '^"(.+)"$' -r '$1'
jq 'tojson | tojson' history-new.json | rg '^"(.+)"$' -r '$1'
Of course there's nothing wrong with doing it manually, or with using sed instead if you want to. Again, just be careful you're not creating invalid JSON.
5. Copy back into VSCode directory
Honestly, you probably want to make a backup of the entire $XDG_CONFIG_HOME/Code - OSS/ directory (or whatever it is on your machine) before doing this. It's probably big I know, but I'm not sure what crazy thing VSCode will do if it finds lastSyncglobalState.json unparseable. Better be safe than sorry.
After you've done that, just copy your modified lastSyncglobalState.json back into $XDG_CONFIG_HOME/Code - OSS/User/sync/globalState/lastSyncglobalState.json and voila.
VSCode terminal uses external shell. For linux the default shell it's bash, for windows it's powershell.
If your terminal shell is powershell, go to C:\Users\john\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline on your file explorer
Visit this link for more details, if the above does not help.

How to limit number of diff lines shown in gitk?

Looking for an option/workaround to limit the diff content (shown in the bottom panel) for any particular file (e.g. to first N lines only), as the patch/diff may be too big and causes the GUI to freeze. I did try the different options accepted by git diff, but don't see any way to pass them to gitk (unlike git-gui). Note that limiting the number of lines of context does not work since the diff will still be shown with zero context.
You will have to change gitk's source code. It's one big Tcl/Tk file you can edit directly or make a copy of. It's location may depend on your operating system. If you are on linux or macos it's probably /usr/bin/gitk or /usr/local/bin/gitk.
Inside the procedure diffcmd, change this line:
set cmd [concat | git diff-tree -r $flags $ids]
You could add diff-tree arguments, or simply pipe the diff output to another program, like head:
set cmd [concat | git diff-tree -r $flags $ids | head -n500]
This applies to the complete diff, not just to one file.

How to load fish command history from file

Is there a way to load commands-history of fish from a file?
I like to clear my history periodically, but keep a set of useful commands always in history for easily accessing.
In bash this can be done via:
history -r file.txt
Can this be done in fish?
In my experience what you want to do isn't really necessary since a) fish only remembers the most recent instance of a command and b) generally does a really good job of using available context to provide the most appropriate entry from the command history, and c) already trims old entries once the number of saved commands reaches a limit.
But, assuming you've saved your preferred history subset to ~/.local/share/fish/fish_history.save:
builtin history clear
cp ~/.local/share/fish/fish_history.save ~/.local/share/fish/fish_history
history merge
The builtin in the first instance is to avoid the prompt asking if you really want to clear your history. Note that your saved history has to be valid YAML. It's a text file but is a little more complex than just each command on a separate line.

Can't Delete File On Terminal

Please, open File 1 to access the problem. If I type it here some important characters that I believe to be what's causing the drama won't show on the post. Thank you!
I basically created a file that I can't get rid of.
Screen shoot of what I have done
Space, <, and > are all treated specially by your shell.
Because of that, you'll need to quote the name. Try this:
rm 'index.html <RET>'
In cases where you can't figure out how to quote/escape the filename appropriately, a convenient approach is:
rm -i index.html*
You will be prompted (because of the -i option) to delete each filename matching the specified glob pattern, one at a time. Simply answer y to the ones you want to delete.
Quoting the arguments correctly is safest (it avoids any possibility of accidentally deleting something you didn't mean to delete), so I recommend always doing so when you can; but if you've managed to generate a really garbled filename (Unix places very few constraints upon filenames) then this method can be very useful.

Which Version control?

If a project has multiple people, say, A,B,C working together and they all edit a same source file.
Couple months later, they realize that what A has been doing is wrong and they want to roll back the file in such a way that only parts/functions/lines/... that A "touched" are removed and the work B and C did is still in the roll back version. In other words, the roll back version has only the work of B and C up to the time they decide to remove A's work.
Is there any version/source control software out there (free/commercial) can do that?
Thanks.
Git and a bit of scripting will do that. Probably a bit of hand work too, but you can resort commits using interactive rebase.
Most VCSs should be able to do this -- it's a reverse merge. In Subversion you would identify the revisions made by A and merge them in again, but the other way round. To oversimplify, this means turning line additions into line removals, and vice versa.
# Don't want revision 37 because A made it.
$ svn merge -r 37:36 path
http://svnbook.red-bean.com/en/1.5/svn.branchmerge.basicmerging.html#svn.branchmerge.basicmerging.undo
I use TFS and Git. But, there are a lot of free and open source version control softwares. You can find all the source control softwares here.
In Git, you would probably do something like
git revert `git rev-list --author=A`
[Note: completely untested.]
I bet it can (easily) be done with Monotone by using `mtn local kill_certs selector certname [certval]' command (see reference) which:
This command deletes certs with the given name on revisions that match the given selector. If a value is given, it restricts itself to only delete certs that also have that same value. Like kill_revision, it is a very dangerous command; it permanently and irrevocably deletes historical information from your database.
So, by using A's certificate, the above command will eliminate 'wrong work' done by him.