For example, if I install package A, its dependencies packages B, C, and D will also be installed. Say, 1 month later I want to uninstall package A and its dependencies B and C, while keep D unchanged because it has become the dependency for another package E. How can I do that?
Several functions can help you achieve that.
You can uninstall package with
devtools::uninstall that wraps the previous one and help ensure that package is unloaded. This function do not uninstall dependency.
You can find dependency for one or several packages using
tools::package_dependencies against your installed packages
tools::package_dependencies("readr", db = installed.packages()) #> $readr #>  "Rcpp" "tibble" "hms" "R6" "clipr" "BH"
With this, you can find which to uninstall and which to keep. Use
recursive = TRUE to get the whole chain of dependency.
When uninstalling packages, you need to take care that the one you are uninstalling is not a dependency for any other. You can also do reverse dependency with the previous function
tools::package_dependencies("readr", db = installed.packages(), reverse = TRUE) #> $readr #>  "datapasta" "DiagrammeR" "googlesheets" "haven" #>  "kableExtra" "nomisr" "readODS" "rtweet" #>  "sparklyr" "tidyverse" "webreadr"
I think with these two functions you can write a wrapper function or just a script that help you iterates to uninstall A, B and C while keeping D because E needs it.
Great! I sometimes can't remove a package with
remove.packages() and I now wonder if the reason is that the package I want to remove is loaded. If so, your post suggests that
devtools::uninstall might help. My brute-force approach was to navigate the directory where R stores my packages and remove the one I want manually. Next time I'll try
(BTW, just noticed a tiny typo in your post. Notice the "s":
devtool:: should be